This commit is contained in:
Your Name
2026-06-02 14:15:49 +08:00
parent 707e4888ad
commit 860b550180
13 changed files with 348 additions and 44 deletions
@@ -0,0 +1,137 @@
<template>
<view class="tab-dock">
<view class="tab-dock__inner">
<view class="tab-dock__item" @click="goHome">
<image
class="tab-dock__icon"
:src="active === 0 ? '/static/user/home_no.png' : '/static/user/home.png'"
mode="aspectFit"
/>
<text class="tab-dock__label" :style="{ color: active === 0 ? activeColor : color }">首页</text>
</view>
<view class="tab-dock__item tab-dock__item--center" @click="goWeekly">
<view class="tab-dock__fab" :class="{ 'tab-dock__fab--active': active === 1 }">
<text class="tab-dock__fab-text"></text>
</view>
<text class="tab-dock__label tab-dock__label--center" :style="{ color: active === 1 ? activeColor : color }">血糖</text>
</view>
<view class="tab-dock__item" @click="goUser">
<image
class="tab-dock__icon"
:src="active === 2 ? '/static/user/user_no.png' : '/static/user/user.png'"
mode="aspectFit"
/>
<text class="tab-dock__label" :style="{ color: active === 2 ? activeColor : color }">我的</text>
</view>
</view>
<view class="tab-dock__safe" />
</view>
</template>
<script setup>
const props = defineProps({
/** 0 首页 1 血糖 2 我的 */
active: {
type: Number,
default: 0
}
})
const color = '#8a8a8a'
const activeColor = '#204e2b'
function goHome() {
if (props.active === 0) return
uni.redirectTo({ url: '/pages/index/index' })
}
function goUser() {
if (props.active === 2) return
uni.redirectTo({ url: '/pages/user/user' })
}
function goWeekly() {
if (props.active === 1) return
uni.redirectTo({ url: '/tongji/pages/weekly' })
}
</script>
<style scoped lang="scss">
.tab-dock {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 999;
background: #ffffff;
border-top: 1rpx solid rgba(0, 0, 0, 0.06);
box-shadow: 0 -6rpx 20rpx rgba(0, 0, 0, 0.04);
}
.tab-dock__inner {
display: flex;
align-items: flex-end;
height: 100rpx;
}
.tab-dock__item {
flex: 1;
height: 100rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.tab-dock__item--center {
justify-content: flex-end;
padding-bottom: 6rpx;
}
.tab-dock__icon {
width: 46rpx;
height: 46rpx;
}
.tab-dock__label {
margin-top: 6rpx;
font-size: 22rpx;
line-height: 1.2;
}
.tab-dock__label--center {
margin-top: 8rpx;
}
.tab-dock__fab {
width: 96rpx;
height: 96rpx;
margin-top: -48rpx;
border-radius: 50%;
background: linear-gradient(180deg, #2d7340 0%, #204e2b 100%);
border: 6rpx solid #ffffff;
box-shadow: 0 10rpx 24rpx rgba(32, 78, 43, 0.35);
display: flex;
align-items: center;
justify-content: center;
}
.tab-dock__fab--active {
transform: scale(1.04);
box-shadow: 0 12rpx 28rpx rgba(32, 78, 43, 0.42);
}
.tab-dock__fab-text {
color: #ffffff;
font-size: 38rpx;
font-weight: 700;
line-height: 1;
}
.tab-dock__safe {
height: env(safe-area-inset-bottom);
background: #ffffff;
}
</style>
+1 -1
View File
@@ -1,5 +1,5 @@
import App from './App' import App from './App'
var baseUrl ='https://admin.zhenyangtang.com.cn/'; var baseUrl ='https://css.zhenyangtang.com.cn/';
function joinApiUrl(base, path) { function joinApiUrl(base, path) {
const b = String(base || '').replace(/\/+$/, '') const b = String(base || '').replace(/\/+$/, '')
+15 -28
View File
@@ -3,7 +3,9 @@
{ {
"path": "pages/index/index", "path": "pages/index/index",
"style": { "style": {
"navigationBarTitleText": "甄养堂" "navigationBarTitleText": "甄养堂",
"backgroundColor": "#F8F8F8",
"backgroundColorTop": "#F8F8F8"
} }
}, },
{ {
@@ -43,7 +45,9 @@
{ {
"path": "pages/user/user", "path": "pages/user/user",
"style": { "style": {
"navigationBarTitleText": "我的" "navigationBarTitleText": "我的",
"backgroundColor": "#e8eaed",
"backgroundColorTop": "#e8eaed"
} }
}, },
{ {
@@ -177,15 +181,6 @@
} }
} }
}, },
{
"path": "pages/more",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "日常护理",
"backgroundColor": "#f4fbf4",
"enablePullDownRefresh": true
}
},
{ {
"path": "pages/weekly", "path": "pages/weekly",
"style": { "style": {
@@ -203,6 +198,15 @@
} }
} }
}, },
{
"path": "pages/more",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "日常护理",
"backgroundColor": "#f4fbf4",
"enablePullDownRefresh": true
}
},
{ {
"path": "pages/game", "path": "pages/game",
"style": { "style": {
@@ -215,23 +219,6 @@
] ]
} }
], ],
"tabBar": {
"color": "#8a8a8a",
"selectedColor": "#204e2b",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "/static/user/home.png",
"selectedIconPath": "/static/user/home_no.png",
"text": "首页"
},{
"pagePath": "pages/user/user",
"iconPath": "/static/user/user.png",
"selectedIconPath": "/static/user/user_no.png",
"text": "我的"
}]
},
"globalStyle": { "globalStyle": {
"navigationBarTextStyle": "black", "navigationBarTextStyle": "black",
"navigationBarTitleText": "甄养堂互联网医院", "navigationBarTitleText": "甄养堂互联网医院",
+5 -2
View File
@@ -118,13 +118,15 @@
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
<TabBarDock :active="0" />
</view> </view>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { getCurrentInstance } from 'vue' import { getCurrentInstance } from 'vue'
import { onShow, onShareAppMessage } from '@dcloudio/uni-app' import { onShareAppMessage } from '@dcloudio/uni-app'
import TabBarDock from '@/components/app-tab-bar/tab-bar-dock.vue'
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
const doctors = ref([]) const doctors = ref([])
@@ -263,7 +265,8 @@ $outline: #727970;
.container { .container {
background: $background; background: $background;
min-height: 100vh; min-height: 100vh;
padding: 24rpx 32rpx 120rpx; padding: 24rpx 32rpx;
padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
font-family: 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif; font-family: 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
} }
+7 -4
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="mine-page"> <view class="mine-page">
<!-- 顶部用户信息卡片 --> <!-- 顶部用户信息卡片 -->
<div class="user-card" @click="navigateTo('/pages/user/userinfo')"> <div class="user-card" @click="navigateTo('/pages/user/userinfo')">
<div class="user-header"> <div class="user-header">
@@ -90,16 +90,18 @@
</div> </div>
<!-- DEV 开发悬浮入口生产环境自动隐藏 --> <!-- DEV 开发悬浮入口生产环境自动隐藏 -->
<dev-training-entry /> <dev-training-entry :bottom="360" />
</div> <TabBarDock :active="2" />
</view>
</template> </template>
<script> <script>
import { onShow, onShareAppMessage } from '@dcloudio/uni-app' import { onShow, onShareAppMessage } from '@dcloudio/uni-app'
import DevTrainingEntry from '@/components/dev-training-entry/index.vue' import DevTrainingEntry from '@/components/dev-training-entry/index.vue'
import TabBarDock from '@/components/app-tab-bar/tab-bar-dock.vue'
export default { export default {
name: 'profileB', name: 'profileB',
components: { DevTrainingEntry }, components: { DevTrainingEntry, TabBarDock },
data() { data() {
return { return {
userInfo: { userInfo: {
@@ -170,6 +172,7 @@ export default {
min-height: 100vh; min-height: 100vh;
background: #e8eaed; background: #e8eaed;
padding: 40rpx; padding: 40rpx;
padding-bottom: calc(40rpx + 200rpx + env(safe-area-inset-bottom));
} }
.user-card { .user-card {
+1 -1
View File
@@ -3516,7 +3516,7 @@ function goBack() {
uni.navigateBack({ delta: 1 }) uni.navigateBack({ delta: 1 })
return return
} }
uni.redirectTo({ url: '/tongji/pages/weekly' }) uni.navigateTo({ url: '/tongji/pages/weekly' })
} }
function goGlucosePage() { function goGlucosePage() {
+42 -3
View File
@@ -228,8 +228,16 @@
<view class="st-main-spacer" /> <view class="st-main-spacer" />
</view> </view>
<!-- 收起后的重新唤起按钮 -->
<view v-if="diagnosisId && floatAskClosed" class="st-float-reopen" @click="floatAskClosed = false">
<TongjiIcon name="sparkles" size="sm" color="#ffffff" />
</view>
<!-- 底部浮动 AI 输入栏 --> <!-- 底部浮动 AI 输入栏 -->
<view v-if="diagnosisId" class="st-float-ask"> <view v-if="diagnosisId && !floatAskClosed" class="st-float-ask">
<view class="st-float-close" @click="floatAskClosed = true">
<text class="st-float-close-icon">×</text>
</view>
<view class="st-float-inner"> <view class="st-float-inner">
<view class="st-float-icon"> <view class="st-float-icon">
<TongjiIcon name="sparkles" size="sm" color="#006c49" /> <TongjiIcon name="sparkles" size="sm" color="#006c49" />
@@ -274,6 +282,17 @@
</view> </view>
</view> </view>
<!-- 语音长按状态浮层居中显示避免被键盘/底栏遮挡 -->
<view v-if="sttHolding && !dietAiAsking" class="st-voice-overlay">
<view class="st-voice-card">
<view class="st-voice-icon" :class="{ active: sttListening }">
<TongjiIcon name="mic" size="lg" color="#ffffff" />
</view>
<text class="st-voice-title">{{ sttListening ? '正在聆听…' : '准备录音…' }}</text>
<text class="st-voice-sub">松开手指结束并识别</text>
</view>
</view>
<!-- 无就诊卡授权手机号后可录入 --> <!-- 无就诊卡授权手机号后可录入 -->
<view v-if="phoneGateVisible" class="input-modal-mask" @click="closePhoneGate"> <view v-if="phoneGateVisible" class="input-modal-mask" @click="closePhoneGate">
<view class="input-modal phone-gate-modal" @click.stop> <view class="input-modal phone-gate-modal" @click.stop>
@@ -323,7 +342,7 @@
<!-- 录入今日数据弹层 --> <!-- 录入今日数据弹层 -->
<view v-if="inputForm.visible" class="input-modal-mask" @click="closeInputForm"> <view v-if="inputForm.visible" class="input-modal-mask" @click="closeInputForm">
<view class="input-modal" @click.stop> <view class="input-modal" :style="keyboardHeight ? { marginBottom: keyboardHeight + 'px' } : {}" @click.stop>
<view class="input-modal-grip" /> <view class="input-modal-grip" />
<view class="input-modal-head"> <view class="input-modal-head">
<view class="input-modal-title-wrap"> <view class="input-modal-title-wrap">
@@ -352,6 +371,7 @@
<view class="input-field-input"> <view class="input-field-input">
<input <input
type="digit" type="digit"
:adjust-position="false"
:value="inputForm.fasting_blood_sugar" :value="inputForm.fasting_blood_sugar"
placeholder="如 6.5" placeholder="如 6.5"
placeholder-class="input-placeholder" placeholder-class="input-placeholder"
@@ -367,6 +387,7 @@
<view class="input-field-input"> <view class="input-field-input">
<input <input
type="digit" type="digit"
:adjust-position="false"
:value="inputForm.postprandial_blood_sugar" :value="inputForm.postprandial_blood_sugar"
placeholder="如 8.0" placeholder="如 8.0"
placeholder-class="input-placeholder" placeholder-class="input-placeholder"
@@ -382,6 +403,7 @@
<view class="input-field-input"> <view class="input-field-input">
<input <input
type="digit" type="digit"
:adjust-position="false"
:value="inputForm.other_blood_sugar" :value="inputForm.other_blood_sugar"
placeholder="如 7.2" placeholder="如 7.2"
placeholder-class="input-placeholder" placeholder-class="input-placeholder"
@@ -398,6 +420,7 @@
placeholder-class="input-placeholder" placeholder-class="input-placeholder"
:show-confirm-bar="false" :show-confirm-bar="false"
:auto-height="true" :auto-height="true"
:adjust-position="false"
@input="onInputField('remark', $event)" @input="onInputField('remark', $event)"
/> />
</view> </view>
@@ -423,6 +446,7 @@
</view> </view>
</view> </view>
</block> </block>
<TabBarDock :active="1" />
</view> </view>
</template> </template>
@@ -433,6 +457,7 @@ import SugarTreeGraphic from '../components/SugarTreeGraphic.vue'
import TongjiIcon from '../components/TongjiIcon.vue' import TongjiIcon from '../components/TongjiIcon.vue'
import { useDietAi } from '../composables/useDietAi.js' import { useDietAi } from '../composables/useDietAi.js'
import { useSpeechToText } from '../composables/useSpeechToText.js' import { useSpeechToText } from '../composables/useSpeechToText.js'
import TabBarDock from '@/components/app-tab-bar/tab-bar-dock.vue'
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
@@ -501,6 +526,15 @@ const {
openDietForm openDietForm
} = useDietAi(proxy, { diagnosisId, showUserToast, formatUserMessage }) } = useDietAi(proxy, { diagnosisId, showUserToast, formatUserMessage })
/** 底部 AI 浮动卡片是否被用户收起 */
const floatAskClosed = ref(false)
/** 键盘高度(px):录入弹窗据此整体上移,避免输入框被键盘遮挡 */
const keyboardHeight = ref(0)
function onKeyboardHeightChange(res) {
keyboardHeight.value = res && res.height ? Math.round(res.height) : 0
}
const { const {
sttListening, sttListening,
sttHolding, sttHolding,
@@ -1373,7 +1407,7 @@ function goGamePage() {
} }
function navToUser() { function navToUser() {
uni.switchTab({ url: '/pages/user/user' }) uni.redirectTo({ url: '/pages/user/user' })
} }
// ============ 时段问候 / 打卡 / 健康日历 ============ // ============ 时段问候 / 打卡 / 健康日历 ============
@@ -2519,6 +2553,7 @@ onLoad((options) => {
onShow(() => { onShow(() => {
initHeaderSafeArea() initHeaderSafeArea()
try { uni.onKeyboardHeightChange(onKeyboardHeightChange) } catch (e) {}
if (authChecking.value) return if (authChecking.value) return
resetCanvasCache() resetCanvasCache()
nextTick(() => scheduleChartRedraw()) nextTick(() => scheduleChartRedraw())
@@ -2534,11 +2569,15 @@ onPullDownRefresh(async () => {
onHide(() => { onHide(() => {
ttsStop() ttsStop()
stopSpeechToText() stopSpeechToText()
try { uni.offKeyboardHeightChange(onKeyboardHeightChange) } catch (e) {}
keyboardHeight.value = 0
}) })
onUnload(() => { onUnload(() => {
ttsStop() ttsStop()
stopSpeechToText() stopSpeechToText()
try { uni.offKeyboardHeightChange(onKeyboardHeightChange) } catch (e) {}
keyboardHeight.value = 0
}) })
// ============ 邀请观看(家人分享页)============ // ============ 邀请观看(家人分享页)============
@@ -5,7 +5,7 @@
inset: 0; inset: 0;
background: rgba(15, 23, 42, 0.45); background: rgba(15, 23, 42, 0.45);
backdrop-filter: blur(12px); backdrop-filter: blur(12px);
z-index: 999; z-index: 2000;
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
justify-content: center; justify-content: center;
@@ -6,6 +6,8 @@
--st-shadow-ambient: 0 24rpx 60rpx -20rpx rgba(0, 108, 73, 0.08), 0 8rpx 20rpx -8rpx rgba(0, 0, 0, 0.03); --st-shadow-ambient: 0 24rpx 60rpx -20rpx rgba(0, 108, 73, 0.08), 0 8rpx 20rpx -8rpx rgba(0, 0, 0, 0.03);
--st-shadow-cta: 0 16rpx 32rpx rgba(0, 108, 73, 0.2); --st-shadow-cta: 0 16rpx 32rpx rgba(0, 108, 73, 0.2);
--st-shadow-float: 0 16rpx 64rpx rgba(0, 108, 73, 0.15); --st-shadow-float: 0 16rpx 64rpx rgba(0, 108, 73, 0.15);
--tab-dock-full-offset: calc(220rpx + env(safe-area-inset-bottom));
padding-bottom: var(--tab-dock-full-offset);
} }
/* ===== Header ===== */ /* ===== Header ===== */
@@ -606,8 +608,43 @@
position: fixed; position: fixed;
left: var(--st-container-margin); left: var(--st-container-margin);
right: var(--st-container-margin); right: var(--st-container-margin);
bottom: calc(24rpx + env(safe-area-inset-bottom)); bottom: var(--tab-dock-full-offset);
z-index: 90; z-index: 210;
}
.weekly-page .st-float-close {
position: absolute;
top: -18rpx;
right: -6rpx;
width: 44rpx;
height: 44rpx;
border-radius: 50%;
background: rgba(0, 0, 0, 0.45);
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
}
.weekly-page .st-float-close-icon {
color: #ffffff;
font-size: 30rpx;
line-height: 1;
}
.weekly-page .st-float-reopen {
position: fixed;
right: var(--st-container-margin);
bottom: var(--tab-dock-full-offset);
width: 88rpx;
height: 88rpx;
border-radius: 50%;
background: linear-gradient(180deg, #2d7340 0%, #006c49 100%);
box-shadow: var(--st-shadow-float);
display: flex;
align-items: center;
justify-content: center;
z-index: 210;
} }
.weekly-page .st-float-inner { .weekly-page .st-float-inner {
@@ -681,6 +718,63 @@
line-height: 1.4; line-height: 1.4;
} }
.weekly-page .st-voice-overlay {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 3000;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.32);
pointer-events: none;
}
.weekly-page .st-voice-card {
display: flex;
flex-direction: column;
align-items: center;
gap: 20rpx;
padding: 56rpx 64rpx;
border-radius: 32rpx;
background: rgba(20, 24, 22, 0.86);
box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.35);
}
.weekly-page .st-voice-icon {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, #2d7340 0%, #006c49 100%);
}
.weekly-page .st-voice-icon.active {
animation: st-voice-pulse 1.1s ease-in-out infinite;
}
@keyframes st-voice-pulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(0, 108, 73, 0.45); }
50% { box-shadow: 0 0 0 20rpx rgba(0, 108, 73, 0); }
}
.weekly-page .st-voice-title {
font-size: 32rpx;
font-weight: 700;
color: #ffffff;
line-height: 1.3;
}
.weekly-page .st-voice-sub {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.7);
line-height: 1.3;
}
@keyframes st-float-mic-pulse { @keyframes st-float-mic-pulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(0, 108, 73, 0.35); } 0%, 100% { box-shadow: 0 0 0 0 rgba(0, 108, 73, 0.35); }
50% { box-shadow: 0 0 0 12rpx rgba(0, 108, 73, 0); } 50% { box-shadow: 0 0 0 12rpx rgba(0, 108, 73, 0); }
+20
View File
@@ -290,6 +290,23 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="统计端就诊卡" prop="show_card">
<el-switch
v-model="formData.show_card"
:active-value="1"
:inactive-value="0"
active-text="显示"
inactive-text="隐藏"
inline-prompt
/>
<span class="form-tips ml-3">
关闭后该就诊卡将不会出现在小程序统计端
</span>
</el-form-item>
</el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
@@ -874,6 +891,7 @@ const formData = ref({
current_medications: '', current_medications: '',
status: 1, status: 1,
create_source: 'admin', create_source: 'admin',
show_card: 1,
external_userid: '' external_userid: ''
}) })
@@ -1155,6 +1173,7 @@ async function loadDiagnosisDetailIntoForm(id: number): Promise<void> {
formData.value = data formData.value = data
formData.value.create_source = data.create_source ?? '' formData.value.create_source = data.create_source ?? ''
formData.value.show_card = Number(data.show_card) === 0 ? 0 : 1
const y = data.diabetes_discovery_year const y = data.diabetes_discovery_year
formData.value.diabetes_discovery_year = y == null || y === '' ? '' : String(y) formData.value.diabetes_discovery_year = y == null || y === '' ? '' : String(y)
} }
@@ -1317,6 +1336,7 @@ const handleClose = () => {
current_medications: '', current_medications: '',
status: 1, status: 1,
create_source: 'admin', create_source: 'admin',
show_card: 1,
external_userid: '' external_userid: ''
} }
@@ -3028,9 +3028,10 @@ class DiagnosisLogic extends BaseLogic
return []; return [];
} }
// 根据诊断ID列表查询诊单详情 // 根据诊断ID列表查询诊单详情show_card=0 的诊单不在统计端就诊卡列表中出现)
$cardList = Diagnosis::whereIn('id', $viewRecords) $cardList = Diagnosis::whereIn('id', $viewRecords)
->where('delete_time', null) ->where('delete_time', null)
->where('show_card', 1)
->field([ ->field([
'id', 'patient_id', 'patient_name', 'gender', 'age', 'id', 'patient_id', 'patient_name', 'gender', 'age',
'diagnosis_date', 'diagnosis_type', 'syndrome_type', 'diagnosis_date', 'diagnosis_type', 'syndrome_type',
@@ -0,0 +1,16 @@
-- 处方业务订单:退款(须填写原因;关联收款单标记已退款)
-- 执行前确认表前缀为 zyt_;若已有相同 perms 则跳过。
SET @po_menu_id := (SELECT id FROM zyt_system_menu WHERE perms = 'tcm.prescriptionOrder/lists' LIMIT 1);
INSERT INTO zyt_system_menu (
pid, type, name, icon, sort, perms, paths, component,
selected, params, is_cache, is_show, is_disable, create_time, update_time
)
SELECT
@po_menu_id, 'A', '业务订单退款', '', 63,
'tcm.prescriptionOrder/refund', '', '',
'', '', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
FROM DUAL
WHERE @po_menu_id IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM zyt_system_menu WHERE perms = 'tcm.prescriptionOrder/refund');
@@ -0,0 +1,4 @@
-- 就诊卡展示开关:控制该诊单是否在小程序「统计」端的就诊卡列表中出现
-- 默认 1=展示(历史数据保持原有可见),0=不展示(统计端就诊卡直接不存在)
ALTER TABLE `zyt_tcm_diagnosis`
ADD COLUMN `show_card` tinyint(1) NOT NULL DEFAULT 1 COMMENT '统计端就诊卡是否展示:1=展示 0=隐藏' AFTER `create_source`;