1. 诊所管理
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
<view class="quick-wrap">
|
||||
<text
|
||||
v-for="opt in discountQuickOptions"
|
||||
:key="'d-' + opt.value"
|
||||
:key="opt.value"
|
||||
class="quick"
|
||||
@click="discountInput = String(opt.value)"
|
||||
>{{ opt.name }}</text>
|
||||
@@ -26,7 +26,7 @@
|
||||
<view class="quick-wrap">
|
||||
<text
|
||||
v-for="opt in markupQuickOptions"
|
||||
:key="'m-' + opt.value"
|
||||
:key="opt.value"
|
||||
class="quick markup"
|
||||
@click="discountInput = String(opt.value)"
|
||||
>{{ opt.name }}</text>
|
||||
|
||||
@@ -45,7 +45,8 @@
|
||||
<view class="action-btn" @click="goConsultation">在线复诊配置</view>
|
||||
<view class="action-btn" @click="goPromoters">管理推广员</view>
|
||||
<view class="action-btn" @click="openQr">诊所二维码</view>
|
||||
<view class="action-btn warn" @click="openPc">开通后台</view>
|
||||
<view class="action-btn" @click="goBankCardReport">{{ bankCardReportButtonText }}</view>
|
||||
<view v-if="!hasAdminAccount" class="action-btn warn" @click="openPc">开通后台</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -89,6 +90,17 @@ export default {
|
||||
clinicTypeIndex() {
|
||||
return Number(this.store.clinic_type) || 0;
|
||||
},
|
||||
hasAdminAccount() {
|
||||
const admin = this.store.new_admin || this.store.newAdmin;
|
||||
return !!(admin && (admin.id || admin.code));
|
||||
},
|
||||
bankCardReportButtonText() {
|
||||
const text = this.store.bank_card_report_status_text;
|
||||
if (Number(this.store.bank_card_report_status) === 0 || !text || text === '未报备') {
|
||||
return '银行卡报备';
|
||||
}
|
||||
return `银行卡报备(${text})`;
|
||||
},
|
||||
},
|
||||
onLoad(options) {
|
||||
this.storeId = Number(options.id || 0);
|
||||
@@ -148,6 +160,12 @@ export default {
|
||||
goPromoters() {
|
||||
uni.navigateTo({ url: `${MANAGE_ROOT}/index?mode=platform&store_id=${this.storeId}` });
|
||||
},
|
||||
goBankCardReport() {
|
||||
if (!this.storeId) return;
|
||||
uni.navigateTo({
|
||||
url: `/subPackages/sub_salesperson/store-bank-card/report?store_id=${this.storeId}`,
|
||||
});
|
||||
},
|
||||
async openQr() {
|
||||
uni.showLoading({ title: '生成中' });
|
||||
try {
|
||||
@@ -170,6 +188,7 @@ export default {
|
||||
const wrap = await openStorePcWindows(this.storeId);
|
||||
if (wrap && wrap.ok) {
|
||||
uni.showToast({ title: '开通成功', icon: 'success' });
|
||||
await this.loadDetail();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
<view class="tag-row">
|
||||
<text class="mini-tag" :class="{ on: Number(item.salesperson_see_price) === 1 }">推广员可见价格</text>
|
||||
<text class="mini-tag" :class="{ on: Number(item.is_shipping_free) === 1 }">包邮</text>
|
||||
<text v-if="Number(item.bank_card_report_status) === 0" class="mini-tag warn">需报备银行卡</text>
|
||||
<text v-else-if="item.bank_card_report_status_text" class="mini-tag bank">{{ item.bank_card_report_status_text }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -111,4 +113,6 @@ export default {
|
||||
.tag-row { display: flex; gap: 12rpx; flex-wrap: wrap; }
|
||||
.mini-tag { font-size: 22rpx; color: #999; background: #f5f5f5; padding: 4rpx 12rpx; border-radius: 8rpx; }
|
||||
.mini-tag.on { color: #22C55E; background: #F0FDF4; }
|
||||
.mini-tag.warn { color: #D97706; background: #FEF3C7; }
|
||||
.mini-tag.bank { color: #3B82F6; background: #EFF6FF; }
|
||||
</style>
|
||||
|
||||
@@ -34,6 +34,7 @@ export function applyDoctorDraft(vm, draft) {
|
||||
vm.selectedStoreInputIds = Array.isArray(ui.selectedStoreInputIds)
|
||||
? [...ui.selectedStoreInputIds]
|
||||
: (Array.isArray(ui.selectedStoreIds) ? [...ui.selectedStoreIds] : [])
|
||||
vm.selectedStoreIds = Array.isArray(ui.selectedStoreIds) ? [...ui.selectedStoreIds] : []
|
||||
vm.departIndex = ui.departIndex != null ? ui.departIndex : Math.max(0, vm.departOptions.findIndex((d) => d.id === vm.form.depart_id))
|
||||
vm.titleIndex = ui.titleIndex != null ? ui.titleIndex : Math.max(0, vm.titleOptions.findIndex((t) => t.id === vm.form.title_id))
|
||||
vm.typeIndex = ui.typeIndex != null ? ui.typeIndex : (Number(vm.form.type) === 2 ? 1 : 0)
|
||||
@@ -45,7 +46,8 @@ export function serializeDoctorDraft(vm) {
|
||||
return {
|
||||
form: JSON.parse(JSON.stringify(vm.form)),
|
||||
ui: {
|
||||
selectedStoreInputIds: [...(vm.selectedStoreInputIds || vm.selectedStoreIds || [])],
|
||||
selectedStoreInputIds: [...(vm.selectedStoreInputIds || [])],
|
||||
selectedStoreIds: [...(vm.selectedStoreIds || [])],
|
||||
departIndex: vm.departIndex,
|
||||
titleIndex: vm.titleIndex,
|
||||
typeIndex: vm.typeIndex,
|
||||
|
||||
@@ -1,35 +1,63 @@
|
||||
<template>
|
||||
<view class="picker-wrap">
|
||||
<view class="store-input-picker" @click="openDrawer">
|
||||
<text :class="summary ? 'summary-text' : 'placeholder-text'">{{ summary || placeholder }}</text>
|
||||
<u-icon v-if="!disabled" name="arrow-right" color="#c0c4cc" size="28"></u-icon>
|
||||
</view>
|
||||
|
||||
<drawer-page-container v-model="show" title="选择预填门店">
|
||||
<view class="drawer-body">
|
||||
<scroll-view scroll-y class="card-scroll">
|
||||
<view v-if="loading" class="empty">加载中...</view>
|
||||
<view v-else-if="!options.length" class="empty">暂无预填门店</view>
|
||||
<view
|
||||
v-for="item in options"
|
||||
:key="item.id"
|
||||
class="store-card"
|
||||
:class="{ active: innerValue.includes(item.id) }"
|
||||
@click="toggle(item.id)"
|
||||
>
|
||||
<view class="card-head">
|
||||
<text class="card-name">{{ item.name || '-' }}</text>
|
||||
<text class="card-status" :class="'s' + item.status">{{ item.status_text }}</text>
|
||||
</view>
|
||||
<text class="card-mobile">{{ item.mobile || '-' }}</text>
|
||||
<text v-if="innerValue.includes(item.id)" class="card-check">已选</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="drawer-footer">
|
||||
<u-button type="primary" :custom-style="primaryStyle" @click="confirm">确定({{ innerValue.length }})</u-button>
|
||||
</view>
|
||||
<text :class="summary ? 'summary-text' : 'placeholder-text'">{{ summary || placeholder }}</text>
|
||||
<u-icon v-if="!disabled" name="arrow-right" color="#c0c4cc" size="28"></u-icon>
|
||||
</view>
|
||||
</drawer-page-container>
|
||||
|
||||
<drawer-page-container v-model="show" title="选择关联门店">
|
||||
<view class="drawer-body">
|
||||
<view class="tab-wrap">
|
||||
<u-subsection
|
||||
:list="tabLabels"
|
||||
:current="activeTab"
|
||||
active-color="#6acdbb"
|
||||
@change="onTabChange"
|
||||
/>
|
||||
</view>
|
||||
<scroll-view scroll-y class="card-scroll">
|
||||
<template v-if="activeTab === 0">
|
||||
<view v-if="loading" class="empty">加载中...</view>
|
||||
<view v-else-if="!options.length" class="empty">暂无预填诊所</view>
|
||||
<view
|
||||
v-for="item in options"
|
||||
:key="item.id"
|
||||
class="store-card"
|
||||
:class="{ active: innerInputIds.includes(item.id) }"
|
||||
@click="toggleInput(item.id)"
|
||||
>
|
||||
<view class="card-head">
|
||||
<text class="card-name">{{ item.name || '-' }}</text>
|
||||
<text class="card-status" :class="'s' + item.status">{{ item.status_text }}</text>
|
||||
</view>
|
||||
<text class="card-mobile">{{ item.mobile || '-' }}</text>
|
||||
<text v-if="innerInputIds.includes(item.id)" class="card-check">已选</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view v-if="formalLoading" class="empty">加载中...</view>
|
||||
<view v-else-if="!formalOptions.length" class="empty">暂无正式诊所</view>
|
||||
<view
|
||||
v-for="item in formalOptions"
|
||||
:key="item.id"
|
||||
class="store-card"
|
||||
:class="{ active: innerStoreIds.includes(item.id) }"
|
||||
@click="toggleStore(item.id)"
|
||||
>
|
||||
<view class="card-head">
|
||||
<text class="card-name">{{ item.name || '-' }}</text>
|
||||
</view>
|
||||
<text v-if="innerStoreIds.includes(item.id)" class="card-check">已选</text>
|
||||
</view>
|
||||
</template>
|
||||
</scroll-view>
|
||||
<view class="drawer-footer">
|
||||
<u-button type="primary" :custom-style="primaryStyle" @click="confirm">
|
||||
确定({{ totalSelected }})
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</drawer-page-container>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -41,16 +69,22 @@ export default {
|
||||
components: { DrawerPageContainer },
|
||||
props: {
|
||||
value: { type: Array, default: () => [] },
|
||||
storeIds: { type: Array, default: () => [] },
|
||||
options: { type: Array, default: () => [] },
|
||||
formalOptions: { type: Array, default: () => [] },
|
||||
loading: { type: Boolean, default: false },
|
||||
formalLoading: { type: Boolean, default: false },
|
||||
disabled: { type: Boolean, default: false },
|
||||
placeholder: { type: String, default: '请选择预填门店' },
|
||||
placeholder: { type: String, default: '请选择关联门店' },
|
||||
defaultStoreInputId: { type: [Number, String], default: 0 },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
innerValue: [],
|
||||
activeTab: 0,
|
||||
innerInputIds: [],
|
||||
innerStoreIds: [],
|
||||
tabLabels: ['预填诊所', '正式诊所'],
|
||||
primaryStyle: {
|
||||
backgroundColor: '#6acdbb',
|
||||
color: '#ffffff',
|
||||
@@ -59,13 +93,21 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
totalSelected() {
|
||||
return this.innerInputIds.length + this.innerStoreIds.length
|
||||
},
|
||||
summary() {
|
||||
if (!this.value.length) return ''
|
||||
const names = this.options
|
||||
const inputNames = this.options
|
||||
.filter((o) => this.value.includes(o.id))
|
||||
.map((o) => o.name)
|
||||
const storeNames = this.formalOptions
|
||||
.filter((o) => this.storeIds.includes(o.id))
|
||||
.map((o) => o.name)
|
||||
const names = [...inputNames, ...storeNames]
|
||||
if (names.length) return names.join('、')
|
||||
return `已选 ${this.value.length} 个门店`
|
||||
const total = this.value.length + this.storeIds.length
|
||||
if (total > 0) return `已选 ${total} 个门店`
|
||||
return ''
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
@@ -82,24 +124,35 @@ export default {
|
||||
methods: {
|
||||
openDrawer() {
|
||||
if (this.disabled) return
|
||||
this.innerValue = [...this.value]
|
||||
this.innerInputIds = [...this.value]
|
||||
this.innerStoreIds = [...this.storeIds]
|
||||
const preset = Number(this.defaultStoreInputId || 0)
|
||||
if (preset > 0 && !this.innerValue.includes(preset)) {
|
||||
this.innerValue.push(preset)
|
||||
if (preset > 0 && !this.innerInputIds.includes(preset)) {
|
||||
this.innerInputIds.push(preset)
|
||||
}
|
||||
this.activeTab = 0
|
||||
this.show = true
|
||||
},
|
||||
toggle(id) {
|
||||
const idx = this.innerValue.indexOf(id)
|
||||
if (idx === -1) this.innerValue.push(id)
|
||||
else this.innerValue.splice(idx, 1)
|
||||
onTabChange(index) {
|
||||
this.activeTab = index
|
||||
},
|
||||
toggleInput(id) {
|
||||
const idx = this.innerInputIds.indexOf(id)
|
||||
if (idx === -1) this.innerInputIds.push(id)
|
||||
else this.innerInputIds.splice(idx, 1)
|
||||
},
|
||||
toggleStore(id) {
|
||||
const idx = this.innerStoreIds.indexOf(id)
|
||||
if (idx === -1) this.innerStoreIds.push(id)
|
||||
else this.innerStoreIds.splice(idx, 1)
|
||||
},
|
||||
confirm() {
|
||||
if (!this.innerValue.length) {
|
||||
uni.showToast({ title: '请选择预填门店', icon: 'none' })
|
||||
if (!this.innerInputIds.length && !this.innerStoreIds.length) {
|
||||
uni.showToast({ title: '请选择关联门店', icon: 'none' })
|
||||
return
|
||||
}
|
||||
this.$emit('input', [...this.innerValue])
|
||||
this.$emit('input', [...this.innerInputIds])
|
||||
this.$emit('update:storeIds', [...this.innerStoreIds])
|
||||
this.show = false
|
||||
},
|
||||
},
|
||||
@@ -118,7 +171,8 @@ export default {
|
||||
.summary-text { font-size: 28rpx; color: #303133; flex: 1; }
|
||||
.placeholder-text { font-size: 28rpx; color: #c0c4cc; flex: 1; }
|
||||
.drawer-body { display: flex; flex-direction: column; max-height: 70vh; }
|
||||
.card-scroll { flex: 1; max-height: 58vh; padding: 16rpx 24rpx; box-sizing: border-box; }
|
||||
.tab-wrap { padding: 16rpx 24rpx 0; flex-shrink: 0; }
|
||||
.card-scroll { flex: 1; max-height: 52vh; padding: 16rpx 24rpx; box-sizing: border-box; }
|
||||
.store-card {
|
||||
background: #f7f8fa;
|
||||
border-radius: 16rpx;
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
<u-form :model="form" ref="uForm" label-width="220" label-align="left">
|
||||
<view v-show="currentStep === 0" class="step-content">
|
||||
<view class="section-title">基础信息</view>
|
||||
<u-form-item label="预填门店" :required="true">
|
||||
<u-form-item label="关联门店" :required="true">
|
||||
<store-input-picker
|
||||
:value="selectedStoreInputIds"
|
||||
:store-ids.sync="selectedStoreIds"
|
||||
:options="storeInputOptions"
|
||||
:formal-options="formalStoreOptions"
|
||||
:loading="storeInputLoading"
|
||||
:formal-loading="formalStoreLoading"
|
||||
:default-store-input-id="presetStoreInputId"
|
||||
@input="selectedStoreInputIds = $event"
|
||||
/>
|
||||
@@ -195,7 +198,10 @@ export default {
|
||||
showSignPad: false,
|
||||
storeInputOptions: [],
|
||||
storeInputLoading: false,
|
||||
formalStoreOptions: [],
|
||||
formalStoreLoading: false,
|
||||
selectedStoreInputIds: [],
|
||||
selectedStoreIds: [],
|
||||
presetStoreInputId: 0,
|
||||
departOptions: [],
|
||||
titleOptions: [],
|
||||
@@ -245,10 +251,13 @@ export default {
|
||||
return this.titleOptions.map((t) => ({ label: t.name, value: t.id }))
|
||||
},
|
||||
selectedStoreNames() {
|
||||
return this.storeInputOptions
|
||||
const inputNames = this.storeInputOptions
|
||||
.filter((s) => this.selectedStoreInputIds.includes(s.id))
|
||||
.map((s) => s.name)
|
||||
.join('、')
|
||||
const storeNames = this.formalStoreOptions
|
||||
.filter((s) => this.selectedStoreIds.includes(s.id))
|
||||
.map((s) => s.name)
|
||||
return [...inputNames, ...storeNames].join('、')
|
||||
},
|
||||
},
|
||||
onLoad(q) {
|
||||
@@ -257,11 +266,16 @@ export default {
|
||||
if (draftId) this.currentDraftId = draftId
|
||||
this.presetStoreInputId = !this.id ? Number(q.storeInputId || 0) : 0
|
||||
this.storeInputLoading = true
|
||||
this.formalStoreLoading = true
|
||||
Promise.all([
|
||||
this.bizApi.getStoreInputOption().then((w) => {
|
||||
this.storeInputLoading = false
|
||||
this.storeInputOptions = w.data || []
|
||||
}).catch(() => { this.storeInputLoading = false }),
|
||||
this.bizApi.getStoreOption().then((w) => {
|
||||
this.formalStoreLoading = false
|
||||
this.formalStoreOptions = w.data || []
|
||||
}).catch(() => { this.formalStoreLoading = false }),
|
||||
this.bizApi.getDepartOption().then((w) => { this.departOptions = w.data || [] }),
|
||||
this.bizApi.getDoctorTitleOption().then((w) => { this.titleOptions = w.data || [] }),
|
||||
]).then(() => {
|
||||
@@ -398,7 +412,20 @@ export default {
|
||||
Object.assign(this.form, createDefaultDoctorInputForm(), w.data)
|
||||
this.selectedStoreInputIds = w.data.store_input_ids?.length
|
||||
? [...w.data.store_input_ids]
|
||||
: (w.data.store_ids || (w.data.store_id ? [w.data.store_id] : []))
|
||||
: []
|
||||
if (w.data.stores?.length) {
|
||||
this.selectedStoreIds = w.data.stores
|
||||
.filter((s) => !Number(s.store_input_id))
|
||||
.map((s) => Number(s.store_id))
|
||||
.filter((id) => id > 0)
|
||||
} else {
|
||||
const allStoreIds = (w.data.store_ids || []).map(Number).filter((id) => id > 0)
|
||||
this.selectedStoreIds = allStoreIds.filter((id) => {
|
||||
return !this.storeInputOptions.some((opt) => {
|
||||
return this.selectedStoreInputIds.includes(opt.id) && Number(opt.synced_store_id) === id
|
||||
})
|
||||
})
|
||||
}
|
||||
this.syncPickerFromForm()
|
||||
})
|
||||
},
|
||||
@@ -411,7 +438,9 @@ export default {
|
||||
validateCurrentStep() {
|
||||
const f = this.form
|
||||
if (this.currentStep === 0) {
|
||||
if (!this.selectedStoreInputIds.length) return this.showError('请选择预填门店')
|
||||
if (!this.selectedStoreInputIds.length && !this.selectedStoreIds.length) {
|
||||
return this.showError('请选择关联门店')
|
||||
}
|
||||
if (!String(f.name || '').trim()) return this.showError('请输入医生姓名')
|
||||
if (!String(f.mobile || '').trim()) return this.showError('请输入手机号')
|
||||
if (!String(f.idcard || '').trim()) return this.showError('请输入身份证')
|
||||
@@ -445,8 +474,8 @@ export default {
|
||||
const payload = {
|
||||
...this.form,
|
||||
store_input_ids: this.selectedStoreInputIds,
|
||||
store_ids: this.selectedStoreInputIds,
|
||||
store_id: this.selectedStoreInputIds[0] || 0,
|
||||
store_ids: this.selectedStoreIds,
|
||||
store_id: this.selectedStoreInputIds[0] || this.selectedStoreIds[0] || 0,
|
||||
}
|
||||
const req = this.id
|
||||
? this.bizApi.updateDoctorInput({ ...payload, id: this.id })
|
||||
|
||||
@@ -146,6 +146,7 @@ export default {
|
||||
return !this.canAudit && Number(this.info.status) === 0 && !!this.editPath
|
||||
},
|
||||
canAudit() {
|
||||
if (Number(this.info.status) !== 0) return false
|
||||
if (this.inputType === 'doctor') return !!this.bizCap.canDoctorInputAudit
|
||||
return !!this.bizCap.canStoreInputAudit
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user