diff --git a/subPackages/sub_business_shared/components/OrderPricePercentAdjustPopup.vue b/subPackages/sub_business_shared/components/OrderPricePercentAdjustPopup.vue index 97150da..905512d 100644 --- a/subPackages/sub_business_shared/components/OrderPricePercentAdjustPopup.vue +++ b/subPackages/sub_business_shared/components/OrderPricePercentAdjustPopup.vue @@ -14,7 +14,7 @@ {{ opt.name }} @@ -26,7 +26,7 @@ {{ opt.name }} diff --git a/subPackages/sub_platform_admin/store/detail.vue b/subPackages/sub_platform_admin/store/detail.vue index cec73e9..e0fd611 100644 --- a/subPackages/sub_platform_admin/store/detail.vue +++ b/subPackages/sub_platform_admin/store/detail.vue @@ -45,7 +45,8 @@ 在线复诊配置 管理推广员 诊所二维码 - 开通后台 + {{ bankCardReportButtonText }} + 开通后台 @@ -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(); } }, }); diff --git a/subPackages/sub_platform_admin/store/index.vue b/subPackages/sub_platform_admin/store/index.vue index 994eb08..951c57c 100644 --- a/subPackages/sub_platform_admin/store/index.vue +++ b/subPackages/sub_platform_admin/store/index.vue @@ -30,6 +30,8 @@ 推广员可见价格 包邮 + 需报备银行卡 + {{ item.bank_card_report_status_text }} @@ -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; } diff --git a/subPackages/sub_salesperson/common/inputDraftHelpers.js b/subPackages/sub_salesperson/common/inputDraftHelpers.js index fac628f..d74b870 100644 --- a/subPackages/sub_salesperson/common/inputDraftHelpers.js +++ b/subPackages/sub_salesperson/common/inputDraftHelpers.js @@ -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, diff --git a/subPackages/sub_salesperson/components/StoreInputPicker.vue b/subPackages/sub_salesperson/components/StoreInputPicker.vue index 4b00755..c0662a8 100644 --- a/subPackages/sub_salesperson/components/StoreInputPicker.vue +++ b/subPackages/sub_salesperson/components/StoreInputPicker.vue @@ -1,35 +1,63 @@ @@ -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; diff --git a/subPackages/sub_salesperson/doctor-input/form.vue b/subPackages/sub_salesperson/doctor-input/form.vue index 5da164d..594d927 100644 --- a/subPackages/sub_salesperson/doctor-input/form.vue +++ b/subPackages/sub_salesperson/doctor-input/form.vue @@ -8,11 +8,14 @@ 基础信息 - + @@ -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 }) diff --git a/subPackages/sub_salesperson/input/InputDetailPage.vue b/subPackages/sub_salesperson/input/InputDetailPage.vue index 71fa2ee..f4e6c6b 100644 --- a/subPackages/sub_salesperson/input/InputDetailPage.vue +++ b/subPackages/sub_salesperson/input/InputDetailPage.vue @@ -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 },