From 8daf6ce4e509a72c298e8fedf91f4ddecac04ff9 Mon Sep 17 00:00:00 2001 From: zhanchao Date: Thu, 27 Aug 2026 14:10:42 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=A5=97=E9=A4=90?= =?UTF-8?q?=E6=94=B9=E9=80=A0=E5=B9=B6=E4=B8=94=E5=8A=A0=E5=85=A5=E6=9D=83?= =?UTF-8?q?=E7=9B=8A=E8=AF=A6=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/case/archive-detail.vue | 8 + .../archive-detail/benefit-project-tab.vue | 451 ++++++++++++++++++ pages/message/benefit-entry.vue | 332 ++++++++++++- pages/message/components/chat-input.vue | 14 +- pages/message/index.vue | 1 + utils/api.js | 3 + 6 files changed, 793 insertions(+), 16 deletions(-) create mode 100644 pages/case/components/archive-detail/benefit-project-tab.vue diff --git a/pages/case/archive-detail.vue b/pages/case/archive-detail.vue index e033313..cf84f4c 100644 --- a/pages/case/archive-detail.vue +++ b/pages/case/archive-detail.vue @@ -118,6 +118,12 @@ :reachBottomTime="reachBottomTime" :floatingBottom="floatingBottom" /> + + + + + {{ item.label }} + + + + + + + {{ item.projectName || '未命名权益项目' }} + + {{ item.statusLabel }} + + 已治疗 + + + + + + + + + 加载中... + 暂无{{ currentType === 'treatment' ? '权益记录' : '治疗明细' }} + + + + + + + + + + + + diff --git a/pages/message/benefit-entry.vue b/pages/message/benefit-entry.vue index 20cc06c..7e0a9ce 100644 --- a/pages/message/benefit-entry.vue +++ b/pages/message/benefit-entry.vue @@ -22,6 +22,71 @@ 权益项目 + + @@ -148,15 +214,16 @@ - 选择权益项目 + 选择权益项目或套餐 - + - 单项目 + {{ project.projectName }} @@ -164,7 +231,12 @@ ¥{{ Number(project.price || 0).toFixed(2) }} - 暂无可用权益项目 + 套餐 + + {{ packageItem.name }}{{ packageItem.packageType === "free" ? `自由组合:${packageItem.projects.length}选${packageItem.projectNumber}` : "固定组合" }} · {{ (packageItem.projects || []).map((item) => item.projectName).join("、") }} + ¥{{ Number(packageItem.packagePrice || 0).toFixed(2) }} + + 暂无可用权益项目或套餐 加载中... 已加载全部权益项目 @@ -206,8 +278,10 @@ const projectPickerVisible = ref(false); const projectPickerIndex = ref(-1); const projectKeyword = ref(""); const projectList = ref([]); +const packageList = ref([]); const projectLoading = ref(false); const projectHasMore = ref(true); +const packageHasMore = ref(true); const projectPage = ref(1); const projectPageSize = 30; const VALID_YEAR_SPAN = 50; @@ -413,31 +487,47 @@ function normalizeProject(project = {}) { async function loadProjects({ reset = false } = {}) { if (projectLoading.value) return; - if (!reset && !projectHasMore.value) return; + if (!reset && !projectHasMore.value && !packageHasMore.value) return; const page = reset ? 1 : projectPage.value; projectLoading.value = true; if (reset) { projectList.value = []; + packageList.value = []; projectHasMore.value = true; + packageHasMore.value = true; } try { - const res = await api("getProjectList", { + const [res, packageRes] = await Promise.all([api("getProjectList", { corpId: corpId.value, page, pageSize: projectPageSize, projectName: projectKeyword.value.trim(), projectStatus: "enable", showDepts: true, - }, false); + }, false), api("getProjectPackageList", { + corpId: corpId.value, + page, + pageSize: projectPageSize, + name: projectKeyword.value.trim(), + enable: true, + }, false)]); const list = res?.data?.list || res?.list || res?.data || []; const nextList = Array.isArray(list) ? list.map(normalizeProject) : []; projectList.value = reset ? nextList : projectList.value.concat(nextList); + const packages = packageRes?.data?.list || packageRes?.list || packageRes?.data || []; + const nextPackages = Array.isArray(packages) ? packages.filter((item) => Array.isArray(item.projects) && item.projects.length) : []; + packageList.value = reset ? nextPackages : packageList.value.concat(nextPackages); projectPage.value = page + 1; projectHasMore.value = nextList.length >= projectPageSize; + packageHasMore.value = nextPackages.length >= projectPageSize; } catch (error) { - if (reset) projectList.value = []; + if (reset) { + projectList.value = []; + packageList.value = []; + } projectHasMore.value = false; + packageHasMore.value = false; uni.showToast({ title: "项目加载失败", icon: "none" }); } finally { projectLoading.value = false; @@ -525,6 +615,110 @@ function selectProject(project) { closeProjectPicker(); } +function createPackageProjectEntry(project = {}, packageItem = {}) { + const normalizedProject = normalizeProject(project); + const hasValidDays = packageItem.hasValidDays === true; + const validDays = Number(packageItem.validDays || 0); + const validDate = hasValidDays && validDays > 0 + ? formatDate(new Date(Date.now() + validDays * 24 * 60 * 60 * 1000)) + : ""; + return { + ...createEntry(), + project: normalizedProject, + price: Number(normalizedProject.price ?? project.price ?? 0), + usageCount: Number(project.number || 1), + discount: packageItem.packageType === "free" ? 10 : Number(project.discount || 10), + totalPrice: Number(project.totalPrice || 0), + selected: packageItem.packageType === "fixed" || project.required === true, + required: project.required === true, + hasValidDays, + validDays, + validTime: validDate, + dept: normalizedProject.depts?.length === 1 ? normalizedProject.depts[0] : null, + }; +} + +async function selectPackage(packageItem) { + const targetIndex = projectPickerIndex.value; + if (targetIndex < 0) return; + try { + uni.showLoading({ title: "加载套餐项目" }); + const ids = packageItem.projects.map((item) => item._id).filter(Boolean); + const res = await api("getProjectList", { corpId: corpId.value, ids, page: 1, pageSize: ids.length, projectStatus: "enable", showDepts: true }, false); + const fullProjects = res?.data?.list || res?.list || res?.data || []; + const projects = packageItem.projects.map((item) => { + const fullProject = Array.isArray(fullProjects) ? fullProjects.find((project) => project._id === item._id) : null; + return createPackageProjectEntry({ ...(fullProject || {}), ...item }, packageItem); + }); + const requiredCount = projects.filter((item) => item.required).length; + const entry = { + ...createEntry(), + isPackage: true, + packageId: packageItem._id, + packageName: packageItem.name, + packageType: packageItem.packageType, + packagePrice: Number(packageItem.packagePrice || 0), + price: Number(packageItem.packagePrice || 0), + usageCount: 1, + discount: 10, + totalPrice: Number(packageItem.packagePrice || 0), + projectNumber: Number(packageItem.projectNumber || projects.length), + requiredCount, + optionalCount: Math.max(Number(packageItem.projectNumber || projects.length) - requiredCount, 0), + projects, + }; + syncPackageSelection(entry); + syncPackageTotals(entry); + entries.value.splice(targetIndex, 1, entry); + closeProjectPicker(); + } catch (error) { + uni.showToast({ title: "套餐加载失败", icon: "none" }); + } finally { + uni.hideLoading(); + } +} + +function syncPackageSelection(entry) { + entry.selectedCount = entry.projects.filter((item) => item.selected).length; + entry.optionalSelectedCount = Math.max(entry.selectedCount - entry.requiredCount, 0); +} + +function isPackageSelectionFull(entry) { + return Number(entry.selectedCount || 0) >= Number(entry.projectNumber || 0); +} + +function togglePackageProject(entry, projectEntry) { + if (projectEntry.required) return; + if (!projectEntry.selected && isPackageSelectionFull(entry)) { + uni.showToast({ title: "已达到可选项目上限", icon: "none" }); + return; + } + projectEntry.selected = !projectEntry.selected; + syncPackageSelection(entry); + syncPackageTotals(entry); +} + +function calculatePackageTotal(entry) { + entry.usageCount = Math.max(1, Number(entry.usageCount || 1)); + entry.discount = clampNumber(toNumber(entry.discount, 10), 0, 10); + entry.totalPrice = toFixedNumber(Number(entry.price || 0) * entry.usageCount * entry.discount / 10, 2); + syncPackageTotals(entry); +} + +function syncPackageTotals(entry) { + const selected = entry.projects.filter((item) => item.selected); + const baseTotal = selected.reduce((sum, item) => sum + Number(item.price || 0) * Number(item.usageCount || 1), 0); + let allocated = 0; + selected.forEach((item, index) => { + const total = index === selected.length - 1 + ? Number(entry.totalPrice || 0) - allocated + : (baseTotal ? Number(entry.totalPrice || 0) * (Number(item.price || 0) * Number(item.usageCount || 1)) / baseTotal : 0); + item.totalPrice = toFixedNumber(Math.max(total, 0), 2); + item.discount = item.price && item.usageCount ? toFixedNumber(item.totalPrice / (item.price * item.usageCount) * 10, 1) : 0; + allocated += item.totalPrice; + }); +} + function changeDept(event, entry) { entry.dept = getProjectDepts(entry)[Number(event.detail.value)] || null; entry.treatmentDoctorUserId = ""; @@ -576,9 +770,33 @@ function goBack() { uni.navigateBack(); } +function goBackToConversation() { + if (!groupId.value) { + goBack(); + return; + } + const conversationID = `GROUP${groupId.value}`; + uni.redirectTo({ + url: `/pages/message/index?conversationID=${encodeURIComponent(conversationID)}&groupID=${encodeURIComponent(groupId.value)}&fromCase=true`, + }); +} + function validateEntries() { for (let index = 0; index < entries.value.length; index += 1) { const entry = entries.value[index]; + if (entry.isPackage) { + if (!Number(entry.usageCount) || Number(entry.usageCount) <= 0) return `${entry.packageName}数量必须大于0`; + if (!Number.isFinite(Number(entry.discount)) || Number(entry.discount) < 0 || Number(entry.discount) > 10) return `${entry.packageName}折扣需在0到10之间`; + if (entry.packageType === "free" && entry.selectedCount !== entry.projectNumber) { + return `${entry.packageName}需要选择${entry.projectNumber}项,当前已选择${entry.selectedCount}项`; + } + const selectedProjects = entry.projects.filter((item) => item.selected); + for (const projectEntry of selectedProjects) { + if (!projectEntry.dept?._id) return `${projectEntry.project.projectName}请选择治疗科室`; + if (projectEntry.hasValidDays && !projectEntry.validTime) return `${projectEntry.project.projectName}请选择有效日期`; + } + continue; + } const label = `第${index + 1}个权益项目`; if (!entry.project?._id) return `${label}请选择项目`; if (Number(entry.price) < 0 || Number.isNaN(Number(entry.price))) return `${label}价格不能小于0`; @@ -643,7 +861,17 @@ async function submitEntries() { const userId = accountStore.doctorInfo?.userid || accountStore.account?.userid || ""; try { const createdEntries = []; - for (const entry of entries.value) { + const submitEntries = entries.value.flatMap((entry) => { + if (!entry.isPackage) return [entry]; + return entry.projects.filter((item) => item.selected).map((item) => ({ + ...item, + packageId: entry.packageId, + packageName: entry.packageName, + packageType: entry.packageType, + packagePrice: Number(entry.packagePrice || 0), + })); + }); + for (const entry of submitEntries) { const count = Number(entry.usageCount); const price = Number(entry.price); const discount = Number(entry.discount); @@ -670,16 +898,22 @@ async function submitEntries() { createTreatementTime: Date.now(), billTime: Date.now(), validTime: entry.validTime ? new Date(`${entry.validTime} 23:59:59`).getTime() : null, + hasValidDays: Boolean(entry.hasValidDays), + validDays: Number(entry.validDays || 0), + packageId: entry.packageId || "", + packageName: entry.packageName || "", + packageType: entry.packageType || "", + packagePrice: Number(entry.packagePrice || 0), teamId: teamId.value, corpId: corpId.value, }; - const res = await api("addTreatmentRecord", { params: treatmentData }, false); + const res = await api("addTreatmentRecord", { userId, operationSource: "wxApp", params: treatmentData }, false); if (!res?.success) throw new Error(res?.message || "权益录入失败"); createdEntries.push(entry); } queueBenefitMessage(createdEntries); uni.showToast({ title: "权益录入成功", icon: "success" }); - setTimeout(goBack, 500); + setTimeout(goBackToConversation, 500); } catch (error) { uni.showToast({ title: error.message || "权益录入失败", icon: "none" }); } finally { @@ -817,6 +1051,75 @@ async function submitEntries() { box-shadow: 0 10rpx 28rpx rgba(15, 23, 42, 0.05); } +.package-card-head { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 20rpx; +} + +.package-name { + color: #111827; + font-size: 30rpx; + font-weight: 600; + line-height: 1.4; +} + +.package-price { + flex-shrink: 0; + color: #e85c2f; + font-size: 30rpx; + font-weight: 700; +} + +.package-summary { + display: flex; + flex-wrap: wrap; + gap: 10rpx 20rpx; + margin-top: 18rpx; + padding: 16rpx; + border-radius: 12rpx; + background: #f5f7fa; + color: #606266; + font-size: 24rpx; +} + +.package-project-card { + margin-top: 20rpx; + padding: 20rpx; + border: 1rpx solid #e5e7eb; + border-radius: 14rpx; + background: #fafbfc; +} + +.package-project-title { + display: flex; + align-items: center; + gap: 10rpx; + color: #1f2937; + font-size: 28rpx; + font-weight: 600; +} + +.package-project-detail { + margin-top: 10rpx; + color: #6b7280; + font-size: 24rpx; +} + +.readonly-input { + display: flex; + align-items: center; + height: 76rpx; + box-sizing: border-box; + padding: 0 20rpx; + border-radius: 12rpx; + background: #f3f4f6; + color: #606266; + font-size: 28rpx; + font-weight: 600; +} + .field-label { margin-bottom: 12rpx; color: #374151; @@ -1068,6 +1371,13 @@ async function submitEntries() { max-height: 55vh; } +.picker-group-title { + padding: 18rpx 8rpx 8rpx; + color: #374151; + font-size: 26rpx; + font-weight: 700; +} + .project-item { display: flex; justify-content: space-between; diff --git a/pages/message/components/chat-input.vue b/pages/message/components/chat-input.vue index 67249d0..092d5b3 100644 --- a/pages/message/components/chat-input.vue +++ b/pages/message/components/chat-input.vue @@ -90,6 +90,7 @@ const props = defineProps({ corpId: { type: String, default: "" }, orderStatus: { type: String, default: "" }, isGenerating: { type: Boolean, default: false }, + canBenefitEntry: { type: Boolean, default: false }, }); // Emits @@ -481,11 +482,6 @@ const morePanelButtons = computed(() => { icon: "/static/icon/xuanjiaowenzhang.png", action: goToArticleList, }, - { - text: "权益录入", - icon: "/static/icon/quanyi.svg", - action: goToBenefitEntry, - }, { text: "问卷", icon: "/static/icon/wenjuan.png", @@ -493,6 +489,14 @@ const morePanelButtons = computed(() => { }, ]; + if (props.canBenefitEntry) { + buttons.splice(4, 0, { + text: "权益录入", + icon: "/static/icon/quanyi.svg", + action: goToBenefitEntry, + }); + } + // 根据订单状态显示不同的按钮 if (props.orderStatus === "finished") { // 已结束状态:显示"开启会话"按钮 diff --git a/pages/message/index.vue b/pages/message/index.vue index ea49ec0..4e416ba 100644 --- a/pages/message/index.vue +++ b/pages/message/index.vue @@ -157,6 +157,7 @@ :patientInfo="patientInfo" :orderStatus="orderStatus" :isGenerating="isGenerating" + :canBenefitEntry="doctorInfo?.benefitEntryEnabled === true" @scrollToBottom="() => scrollToBottom(true)" @messageSent="() => scrollToBottom(true)" @endConsult="handleEndConsult" diff --git a/utils/api.js b/utils/api.js index 3daa57c..f792b38 100644 --- a/utils/api.js +++ b/utils/api.js @@ -94,6 +94,9 @@ const urlsConfig = { // 健康档案相关接口 addMedicalRecord: 'addMedicalRecord', addTreatmentRecord: "addTreatmentRecord", + getProjectPackageList: "getProjectPackageList", + getTreatmentRecord: "getTreatmentRecord", + getDeductRecord: "getDeductRecord", getMedicalRecordById: 'getMedicalRecordById', updateMedicalRecord: 'updateMedicalRecord', removeMedicalRecord: 'removeMedicalRecord', From 1e0cd71432fe5cc0e306b14d53ddcd21b416ffc8 Mon Sep 17 00:00:00 2001 From: zhanchao Date: Thu, 27 Aug 2026 14:47:13 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=E6=9D=83=E7=9B=8A=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=BE=85=E5=8A=9E=E5=8A=9F=E8=83=BD=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/case/followup-detail.vue | 10 + pages/message/benefit-entry.vue | 343 +++++++++++++++++++++++++++++++- pages/work/todo/todo-detail.vue | 12 +- utils/api.js | 5 +- utils/todo-const.js | 1 + 5 files changed, 367 insertions(+), 4 deletions(-) diff --git a/pages/case/followup-detail.vue b/pages/case/followup-detail.vue index 5625ec0..48d0a98 100644 --- a/pages/case/followup-detail.vue +++ b/pages/case/followup-detail.vue @@ -368,6 +368,16 @@ function markDone() { const result = String(form.result || '').trim() || '已完成'; const r = await api('setTodoStatus', { corpId, id: taskId.value, eventStatus: 'treated', result, userId, todoMethod: methodValue }); if (!r?.success) return toast(r?.message || '操作失败'); + if (todo.value?.benefitDeductOnComplete && todo.value?.benefitRecordId) { + const deductRes = await api('completeBenefitTodo', { + corpId, + todoId: taskId.value, + treatmentRecordId: todo.value.benefitRecordId, + executorUserId: userId, + completedAt: Date.now(), + }); + if (!deductRes?.success) return toast(deductRes?.message || '待办已完成,但权益自动核销失败'); + } toast('操作成功'); uni.$emit('archive-detail:followup-changed'); setTimeout(() => uni.navigateBack(), 300); diff --git a/pages/message/benefit-entry.vue b/pages/message/benefit-entry.vue index 7e0a9ce..904d198 100644 --- a/pages/message/benefit-entry.vue +++ b/pages/message/benefit-entry.vue @@ -83,6 +83,17 @@ 有效期 {{ projectEntry.validTime }} + + 生成待办 + + + + + 类型:{{ getTodoTypeLabel(projectEntry.todoConfig.eventType) }} + 回访日期{{ projectEntry.todoConfig.planDate }}截止日期{{ projectEntry.todoConfig.expireDate }} + {{ projectEntry.todoConfig.executorName || '请选择团队和处理人' }} + 完成关联核销权益 + 删除套餐 @@ -185,6 +196,17 @@ + + 生成待办 + + + + + 类型:{{ getTodoTypeLabel(entry.todoConfig.eventType) }} + 回访日期{{ entry.todoConfig.planDate }}截止日期{{ entry.todoConfig.expireDate }} + {{ entry.todoConfig.executorName || '请选择团队和处理人' }} + 完成关联核销权益 + 计划治疗医生 @@ -211,6 +233,22 @@ 添加权益项目 + + + 请选择团队和处理人 + + + {{ team.name }} + + {{ member.name }}已选择 + + 暂无团队成员 + + 暂无可选团队 + + + + @@ -254,11 +292,12 @@ diff --git a/pages/case/components/archive-detail/benefit-project-tab.vue b/pages/case/components/archive-detail/benefit-project-tab.vue index cf9e525..872a24c 100644 --- a/pages/case/components/archive-detail/benefit-project-tab.vue +++ b/pages/case/components/archive-detail/benefit-project-tab.vue @@ -47,7 +47,7 @@ 录单人 - {{ item.creatorName || item.billdCreator || '--' }} + @@ -70,7 +70,7 @@ 治疗医生 - {{ item.doctorName || item.treatmentDoctorUserId || '--' }} + {{ item.treatmentRemark }} @@ -105,6 +105,7 @@ import { storeToRefs } from 'pinia'; import api from '@/utils/api'; import useAccountStore from '@/store/account'; import { toast } from '@/utils/widget'; +import WwUser from '@/components/ww-user/index.vue'; const props = defineProps({ data: { type: Object, default: () => ({}) }, @@ -165,7 +166,7 @@ function mapTreatment(row) { purchaseDate: formatDate(row.billTime || row.createTreatementTime), statusLabel: expired ? '已过期' : row.restUsageCount > 0 ? '可使用' : '已用完', statusClass: expired ? 'status-red' : row.restUsageCount > 0 ? 'status-green' : 'status-gray', - creatorName: row.billdCreatorName || row.doctorName || '', + creatorName: row.creatorName || row.billdCreatorName || '', }; } @@ -446,6 +447,6 @@ watch(() => props.archiveId, (value, oldValue) => { align-items: center; justify-content: center; box-shadow: 0 20rpx 36rpx rgba(8, 119, 241, 0.3); - z-index: 20; + z-index: 1000; } diff --git a/pages/case/components/archive-detail/follow-up-manage-tab.vue b/pages/case/components/archive-detail/follow-up-manage-tab.vue index 59dcabc..d2fdced 100644 --- a/pages/case/components/archive-detail/follow-up-manage-tab.vue +++ b/pages/case/components/archive-detail/follow-up-manage-tab.vue @@ -1600,7 +1600,7 @@ watch( align-items: center; justify-content: center; box-shadow: 0 10px 18px rgba(79, 110, 247, 0.35); - z-index: 20; + z-index: 1000; } .popup { diff --git a/pages/case/components/archive-detail/health-profile-tab.vue b/pages/case/components/archive-detail/health-profile-tab.vue index 4afb775..560c77f 100644 --- a/pages/case/components/archive-detail/health-profile-tab.vue +++ b/pages/case/components/archive-detail/health-profile-tab.vue @@ -893,7 +893,7 @@ watch( right: 32rpx; width: 104rpx; height: 104rpx; - z-index: 20; + z-index: 1000; } .fab { diff --git a/pages/case/components/archive-detail/service-info-tab.vue b/pages/case/components/archive-detail/service-info-tab.vue index b96d216..809b39a 100644 --- a/pages/case/components/archive-detail/service-info-tab.vue +++ b/pages/case/components/archive-detail/service-info-tab.vue @@ -885,7 +885,7 @@ watch( align-items: center; justify-content: center; box-shadow: 0 20rpx 36rpx rgba(79, 110, 247, 0.35); - z-index: 20; + z-index: 1000; } .popup { From 17b2a434cce8fa74a97bb513ca7d07059a43ae24 Mon Sep 17 00:00:00 2001 From: huxuejian Date: Tue, 1 Sep 2026 15:33:31 +0800 Subject: [PATCH 05/11] =?UTF-8?q?fix:=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- baseData/index.js | 28 +++++++++++++++++- pages/case/new-followup.vue | 7 +++-- utils/todo-const.js | 59 ++++++++++++++++++++++++++----------- 3 files changed, 73 insertions(+), 21 deletions(-) diff --git a/baseData/index.js b/baseData/index.js index eb40923..9cc6d25 100644 --- a/baseData/index.js +++ b/baseData/index.js @@ -20,7 +20,33 @@ export const ToDoEventType = { followupAppointment: "复诊预约", confirmArrival: "确认到院", prenatalFollowUp: "孕期回访", -}; + childHealthFollowUp: "儿童保健回访", + benefitExecution: "权益执行", +} +// { +// followUpNoShow: "未到院回访", +// followUpNoDeal: "未成交回访", +// followUp: "诊后回访", +// followUpPostSurgery: "术后回访", +// followUpPostTreatment: "治疗后回访", +// appointmentReminder: "就诊提醒", +// followUpReminder: "复诊提醒", +// medicationReminder: "用药提醒", +// serviceSummary: "咨询服务", +// eventNotification: "活动通知", +// ContentReminder: "宣教发送", +// questionnaire: "问卷调查", +// followUpComplaint: "投诉回访", +// followUpActivity: "活动回访", +// other: "其他", +// Feedback: "意见反馈", +// // 预约相关服务类型 +// treatmentAppointment: "治疗预约", +// followupAppointment: "复诊预约", +// confirmArrival: "确认到院", +// prenatalFollowUp: "孕期回访", +// }; + export const statusNames = { notStart: "未开始", diff --git a/pages/case/new-followup.vue b/pages/case/new-followup.vue index fd692f3..bb78bba 100644 --- a/pages/case/new-followup.vue +++ b/pages/case/new-followup.vue @@ -158,9 +158,10 @@ const __NEW_FOLLOWUP_EVENT_TYPE_VALUES__ = [ 'followUpNoShow', 'other', ]; -const eventTypeList = __NEW_FOLLOWUP_EVENT_TYPE_VALUES__ - .map((v) => __ALL_TODO_EVENT_TYPE_OPTIONS__.find((i) => i.value === v)) - .filter(Boolean); +// const eventTypeList = __NEW_FOLLOWUP_EVENT_TYPE_VALUES__ +// .map((v) => __ALL_TODO_EVENT_TYPE_OPTIONS__.find((i) => i.value === v)) +// .filter(Boolean); +const eventTypeList = __ALL_TODO_EVENT_TYPE_OPTIONS__; const accountStore = useAccountStore(); const { account, doctorInfo } = storeToRefs(accountStore); diff --git a/utils/todo-const.js b/utils/todo-const.js index 150d47c..942f793 100644 --- a/utils/todo-const.js +++ b/utils/todo-const.js @@ -1,21 +1,46 @@ export const TODO_EVENT_TYPE_LABELS = { - benefitExecution: '权益执行', - followUpNoShow: '未到院回访', - followUpNoDeal: '未成交回访', - followUp: '诊后回访', - followUpPostSurgery: '术后回访', - followUpPostTreatment: '治疗后回访', - appointmentReminder: '就诊提醒', - followUpReminder: '复诊提醒', - medicationReminder: '用药提醒', - serviceSummary: '咨询服务', - eventNotification: '活动通知', - ContentReminder: '宣教发送', - questionnaire: '问卷调查', - followUpComplaint: '投诉回访', - followUpActivity: '活动回访', - other: '其他', -}; + followUpNoShow: "未到院回访", + followUpNoDeal: "未成交回访", + followUp: "诊后回访", + followUpPostSurgery: "术后回访", + followUpPostTreatment: "治疗后回访", + appointmentReminder: "就诊提醒", + followUpReminder: "复诊提醒", + medicationReminder: "用药提醒", + serviceSummary: "咨询服务", + eventNotification: "活动通知", + ContentReminder: "宣教发送", + questionnaire: "问卷调查", + followUpComplaint: "投诉回访", + followUpActivity: "活动回访", + other: "其他", + Feedback: "意见反馈", + // 预约相关服务类型 + treatmentAppointment: "治疗预约", + followupAppointment: "复诊预约", + confirmArrival: "确认到院", + prenatalFollowUp: "孕期回访", + childHealthFollowUp: "儿童保健回访", + benefitExecution: "权益执行", +} +// { +// benefitExecution: '权益执行', +// followUpNoShow: '未到院回访', +// followUpNoDeal: '未成交回访', +// followUp: '诊后回访', +// followUpPostSurgery: '术后回访', +// followUpPostTreatment: '治疗后回访', +// appointmentReminder: '就诊提醒', +// followUpReminder: '复诊提醒', +// medicationReminder: '用药提醒', +// serviceSummary: '咨询服务', +// eventNotification: '活动通知', +// ContentReminder: '宣教发送', +// questionnaire: '问卷调查', +// followUpComplaint: '投诉回访', +// followUpActivity: '活动回访', +// other: '其他', +// }; export function getTodoEventTypeLabel(value) { const v = String(value || ''); From 0126068ae613c7dc807e51ed85d0f9214fc18156 Mon Sep 17 00:00:00 2001 From: zhanchao Date: Tue, 1 Sep 2026 15:42:31 +0800 Subject: [PATCH 06/11] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/message/benefit-entry.vue | 57 ++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/pages/message/benefit-entry.vue b/pages/message/benefit-entry.vue index 6221268..72f922b 100644 --- a/pages/message/benefit-entry.vue +++ b/pages/message/benefit-entry.vue @@ -58,22 +58,30 @@ - + + + + + 必选 {{ projectEntry.project.projectName }} ¥{{ Number(projectEntry.price || 0).toFixed(2) }} × {{ projectEntry.usageCount }},折扣 {{ Number(projectEntry.discount || 0).toFixed(1) }} 治疗科室 - {{ projectEntry.dept?.deptName || "请选择治疗科室" }} + {{ projectEntry.dept?.deptName || "请选择治疗科室" }} @@ -94,7 +102,7 @@ 类型:{{ getTodoTypeLabel(projectEntry.todoConfig.eventType) }} 回访日期{{ projectEntry.todoConfig.planDate }}截止日期{{ projectEntry.todoConfig.expireDate }} - {{ projectEntry.todoConfig.executorName || '请选择团队和处理人' }} + {{ projectEntry.todoConfig.executorName || '请选择团队和处理人' }} 完成关联核销权益 @@ -102,7 +110,7 @@ @@ -70,7 +70,7 @@ 治疗医生 - + {{ item.treatmentRemark }} @@ -447,6 +447,6 @@ watch(() => props.archiveId, (value, oldValue) => { align-items: center; justify-content: center; box-shadow: 0 20rpx 36rpx rgba(8, 119, 241, 0.3); - z-index: 1000; + z-index: 9999; } From e50d222a02c2ba7e88f57c319afad7e3f218c87b Mon Sep 17 00:00:00 2001 From: zhanchao Date: Tue, 1 Sep 2026 17:42:46 +0800 Subject: [PATCH 08/11] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8Dlast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/message/benefit-entry.vue | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/pages/message/benefit-entry.vue b/pages/message/benefit-entry.vue index 72f922b..a400db9 100644 --- a/pages/message/benefit-entry.vue +++ b/pages/message/benefit-entry.vue @@ -90,9 +90,21 @@ {{ projectEntry.treatmentDoctorName || "选择治疗医生" }} - + 有效期 - {{ projectEntry.validTime }} + + + + + {{ projectEntry.validTime || "选择日期/长期" }} + + + + 套餐有效期已锁定 + 生成待办 @@ -1104,7 +1116,9 @@ function validateEntries() { const selectedProjects = entry.projects.filter((item) => item.selected); for (const projectEntry of selectedProjects) { if (!projectEntry.dept?._id) return `${projectEntry.project.projectName}请选择治疗科室`; - if (projectEntry.hasValidDays && !projectEntry.validTime) return `${projectEntry.project.projectName}请选择有效日期`; + if (Number(projectEntry.validDays || 0) > 0 && !projectEntry.validTime) { + return `${projectEntry.project.projectName}请选择有效日期`; + } const todoError = validateTodo(projectEntry); if (todoError) return todoError; } @@ -1794,6 +1808,17 @@ async function submitEntries() { min-width: 0; } +.disabled-picker { + opacity: 0.65; +} + +.valid-time-locked-tip { + flex-shrink: 0; + color: #9ca3af; + font-size: 24rpx; + white-space: nowrap; +} + .unlimited-button { flex-shrink: 0; height: 76rpx; From 24ee4a48f50775a509374051fdc33585d31714b9 Mon Sep 17 00:00:00 2001 From: zhanchao Date: Wed, 2 Sep 2026 14:50:21 +0800 Subject: [PATCH 09/11] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/case/archive-detail.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pages/case/archive-detail.vue b/pages/case/archive-detail.vue index cf84f4c..f6118da 100644 --- a/pages/case/archive-detail.vue +++ b/pages/case/archive-detail.vue @@ -570,7 +570,10 @@ onLoad((options) => { fetchArchive(); }); -onShow(() => { +onShow(async () => { + // 每次进入用户详情页重新获取医生信息,及时同步管理端变更的权益权限。 + await getDoctorInfo(); + const cached = uni.getStorageSync(STORAGE_KEY); const cachedId = cached && typeof cached === 'object' ? String(cached._id || cached.id || '') : ''; if (cached && typeof cached === 'object' && (!cachedId || !archiveId.value || cachedId === archiveId.value)) { From 01ee09524b07a68702413148c6f45bd0899d69f2 Mon Sep 17 00:00:00 2001 From: huxuejian Date: Thu, 3 Sep 2026 17:35:08 +0800 Subject: [PATCH 10/11] =?UTF-8?q?fix:=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/case/followup-detail.vue | 71 ++++++++++++++++++++++++++---- pages/case/new-followup-record.vue | 1 - utils/api.js | 2 + 3 files changed, 64 insertions(+), 10 deletions(-) diff --git a/pages/case/followup-detail.vue b/pages/case/followup-detail.vue index 48d0a98..e9e0459 100644 --- a/pages/case/followup-detail.vue +++ b/pages/case/followup-detail.vue @@ -47,13 +47,8 @@ 回访结果 -