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/components/ww-user/index.vue b/components/ww-user/index.vue
new file mode 100644
index 0000000..a8d3c3a
--- /dev/null
+++ b/components/ww-user/index.vue
@@ -0,0 +1,48 @@
+
+ {{ displayName }}
+
+
+
diff --git a/pages/case/archive-detail.vue b/pages/case/archive-detail.vue
index 88e5ef8..d5b2d80 100644
--- a/pages/case/archive-detail.vue
+++ b/pages/case/archive-detail.vue
@@ -118,6 +118,12 @@
:reachBottomTime="reachBottomTime"
:floatingBottom="floatingBottom"
/>
+
{
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)) {
diff --git a/pages/case/components/archive-detail/benefit-project-tab.vue b/pages/case/components/archive-detail/benefit-project-tab.vue
new file mode 100644
index 0000000..957600d
--- /dev/null
+++ b/pages/case/components/archive-detail/benefit-project-tab.vue
@@ -0,0 +1,452 @@
+
+
+
+
+ {{ item.label }}
+
+
+
+
+
+
+
+
+
+
+ 总数
+ {{ item.usageCount }}
+
+
+ 剩余数
+ {{ item.restUsageCount }}
+
+
+ 有效期
+ {{ item.validTimeText }}
+
+
+
+ 购买日期
+ {{ item.purchaseDate }}
+
+
+ 治疗科室
+ {{ item.treatmentDeptName || '--' }}
+
+
+ 录单人
+
+
+
+
+
+
+ 治疗日期
+ {{ item.treatmentDate }}
+
+
+ 治疗数
+ {{ item.deductUsageCount }}
+
+
+ 治疗部位
+ {{ item.treatmentArea || '--' }}
+
+
+ 治疗科室
+ {{ item.treatmentDeptName || '--' }}
+
+
+ 治疗医生
+
+
+
+
+
+
+
+ 加载中...
+ 暂无{{ currentType === 'treatment' ? '权益记录' : '治疗明细' }}
+
+
+
+
+
+
+
+
+
+
+
+
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 cab762f..0723ee9 100644
--- a/pages/case/components/archive-detail/follow-up-manage-tab.vue
+++ b/pages/case/components/archive-detail/follow-up-manage-tab.vue
@@ -1599,8 +1599,8 @@ watch(
display: flex;
align-items: center;
justify-content: center;
- box-shadow: 0 20rpx 36rpx rgba(79, 110, 247, 0.35);
- z-index: 20;
+ box-shadow: 0 10px 18px rgba(79, 110, 247, 0.35);
+ 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 3eaa824..0465428 100644
--- a/pages/case/components/archive-detail/health-profile-tab.vue
+++ b/pages/case/components/archive-detail/health-profile-tab.vue
@@ -915,7 +915,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 e84bef3..b52dcd9 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 {
diff --git a/pages/case/followup-detail.vue b/pages/case/followup-detail.vue
index 743978b..9d4f781 100644
--- a/pages/case/followup-detail.vue
+++ b/pages/case/followup-detail.vue
@@ -47,13 +47,8 @@
回访结果
-
+
@@ -191,8 +186,9 @@ const mobiles = computed(() => {
if (Array.isArray(cached.mobiles)) arr.push(...cached.mobiles.map(String));
}
const cleaned = arr.map((i) => String(i || '').trim()).filter(Boolean);
- if (!cleaned.includes('13800000000')) cleaned.push('13800000000');
- return Array.from(new Set(cleaned));
+ const { mobile, phone1, phone2, phone3 } = customer.value || {};
+ cleaned.push(mobile, phone1, phone2, phone3)
+ return Array.from(new Set(cleaned.filter(i => typeof i === 'string' && i.trim())));
});
function getUserId() {
@@ -319,7 +315,13 @@ async function getTodo() {
return;
}
todo.value = res.data && typeof res.data === 'object' ? res.data : null;
+ if (todo.value.customerId && !customer.value) {
+ getCustomer(todo.value.customerId)
+ }
await loadUserNameMap(String(todo.value?.executeTeamId || ''));
+ if (todo.value && todo.value.creatorUserId && !userNameMap.value[todo.value.creatorUserId]) {
+ getCorpMember(todo.value.creatorUserId)
+ }
const parsed = parseTodoMethod(todo.value?.todoMethod);
if (parsed.todoMethod) {
@@ -335,6 +337,14 @@ async function getTodo() {
form.result = String(todo.value?.result || '') || '';
}
+async function getCustomer(_id) {
+ const res = await api('getMemberInfo', { params: { _id } })
+ const [data] = res && Array.isArray(res.data) ? res.data : [];
+ if (data) {
+ customer.value = data
+ }
+}
+
function toggleMethod(v) {
if (!editable.value) return;
todoMethod.value = v;
@@ -368,6 +378,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);
@@ -410,6 +430,14 @@ async function save() {
setTimeout(() => uni.navigateBack(), 300);
}
+async function getCorpMember(userId) {
+ const res = await api('getCorpMemberByUserId', { userId });
+ const [data] = res && Array.isArray(res.data) ? res.data : [];
+ if (data && data.userid && data.anotherName) {
+ userNameMap.value[data.userid] = data.anotherName
+ }
+}
+
function remove() {
if (!canRemove.value) return;
uni.showModal({
@@ -435,13 +463,16 @@ function remove() {
height: 100vh;
background: #f6f7f8;
}
+
.scroll {
height: 100vh;
}
+
.section {
background: #fff;
padding: 24rpx 30rpx;
}
+
.border-top {
border-top: 1px solid #e5e7eb;
}
@@ -451,11 +482,13 @@ function remove() {
align-items: center;
justify-content: space-between;
}
+
.head-title {
font-size: 34rpx;
font-weight: 600;
color: #111827;
}
+
.head-tag {
flex-shrink: 0;
font-size: 26rpx;
@@ -464,23 +497,28 @@ function remove() {
background: #f3f4f6;
color: #6b7280;
}
+
.tag-processing {
background: #fee2e2;
color: #ef4444;
}
+
.tag-notStart {
background: #dbeafe;
color: #2563eb;
}
+
.tag-treated {
background: #dcfce7;
color: #16a34a;
}
+
.tag-cancelled,
.tag-expired {
background: #f3f4f6;
color: #6b7280;
}
+
.head-content {
margin-top: 24rpx;
font-size: 30rpx;
@@ -492,21 +530,25 @@ function remove() {
font-size: 30rpx;
color: #6b7280;
}
+
.sub-content {
margin-top: 24rpx;
font-size: 30rpx;
color: #6b7280;
line-height: 44rpx;
}
+
.file-line {
margin-top: 12rpx;
font-size: 30rpx;
line-height: 40rpx;
}
+
.file-type {
color: #111827;
margin-right: 12rpx;
}
+
.file-name {
color: #2563eb;
}
@@ -516,21 +558,25 @@ function remove() {
font-weight: 600;
color: #111827;
}
+
.method-row {
display: flex;
align-items: center;
margin-top: 24rpx;
}
+
.radio {
width: 32rpx;
height: 32rpx;
margin-right: 20rpx;
}
+
.method-label {
font-size: 30rpx;
color: #111827;
margin-right: 20rpx;
}
+
.method-select {
margin-left: auto;
width: 400rpx;
@@ -542,6 +588,7 @@ function remove() {
align-items: center;
justify-content: space-between;
}
+
.method-value {
font-size: 30rpx;
color: #111827;
@@ -550,6 +597,7 @@ function remove() {
text-overflow: ellipsis;
white-space: nowrap;
}
+
.method-value.muted {
color: #9ca3af;
}
@@ -559,10 +607,12 @@ function remove() {
align-items: center;
justify-content: space-between;
}
+
.kv-left {
font-size: 30rpx;
color: #6b7280;
}
+
.kv-right {
font-size: 30rpx;
color: #111827;
@@ -572,6 +622,7 @@ function remove() {
text-overflow: ellipsis;
white-space: nowrap;
}
+
.kv-right.link {
color: #2563eb;
text-decoration: underline;
@@ -580,12 +631,14 @@ function remove() {
.mt-20 {
margin-top: 20rpx;
}
+
.result-box {
margin-top: 24rpx;
padding: 20rpx;
border: 1px solid #e5e7eb;
border-radius: 16rpx;
}
+
.result-textarea {
width: 100%;
min-height: 160rpx;
@@ -594,19 +647,24 @@ function remove() {
color: #111827;
box-sizing: border-box;
}
+
.meta {
font-size: 30rpx;
}
+
.meta-row {
margin-top: 24rpx;
}
+
.meta-row:first-child {
margin-top: 0;
}
+
.meta-key {
color: #6b7280;
margin-right: 12rpx;
}
+
.meta-val {
color: #6b7280;
}
@@ -623,6 +681,7 @@ function remove() {
padding: 30rpx;
box-shadow: 0 -8rpx 24rpx rgba(0, 0, 0, 0.06);
}
+
.footer-btn {
flex: 0 0 auto;
min-width: 260rpx;
@@ -631,18 +690,22 @@ function remove() {
border-radius: 16rpx;
font-size: 30rpx;
}
+
.footer-btn::after {
border: none;
}
+
.footer-btn.plain {
background: #fff;
color: #2563eb;
border: 1px solid #2563eb;
}
+
.footer-btn.plain.danger {
color: #ef4444;
border-color: #ef4444;
}
+
.footer-btn.primary {
background: #2563eb;
color: #fff;
diff --git a/pages/case/new-followup-record.vue b/pages/case/new-followup-record.vue
index ee2fc13..3901b39 100644
--- a/pages/case/new-followup-record.vue
+++ b/pages/case/new-followup-record.vue
@@ -124,7 +124,6 @@ const eventTypeLabel = computed(() => getTodoEventTypeLabel(form.eventType));
const mobiles = computed(() => {
const arr = [];
if (archiveMobile.value) arr.push(String(archiveMobile.value));
- if (!arr.includes('13800000000')) arr.push('13800000000');
return arr;
});
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/pages/message/benefit-entry.vue b/pages/message/benefit-entry.vue
index 20cc06c..4771700 100644
--- a/pages/message/benefit-entry.vue
+++ b/pages/message/benefit-entry.vue
@@ -1,4 +1,5 @@
+
@@ -22,8 +23,106 @@
权益项目
+
+
+
+ 套餐名称
+ {{ entry.packageName }}
+
+ ¥{{ Number(entry.price || 0).toFixed(2) }}
+
+
+ 组合形式:{{ entry.packageType === "free" ? `${entry.projects.length}选${entry.projectNumber}` : "固定组合" }}
+ 必选项:{{ entry.requiredCount }}
+ 可选项:{{ entry.optionalSelectedCount }} / {{ entry.optionalCount }}
+
+
+
+ 数量
+
+
+
+ 折扣
+
+ {{ Number(entry.discount).toFixed(1) }}
+
+
+
+ 总价
+ ¥{{ Number(entry.totalPrice || 0).toFixed(2) }}
+
+
+
+
+ 数量
+
+
+
+
+
+
+
+
+
+ 必选
+ {{ projectEntry.project.projectName }}
+
+ ¥{{ Number(projectEntry.price || 0).toFixed(2) }} × {{ projectEntry.usageCount }},折扣 {{ Number(projectEntry.discount || 0).toFixed(1) }}
+
+ 治疗科室
+
+ {{ projectEntry.dept?.deptName || "请选择治疗科室" }}
+
+
+
+ 计划治疗医生
+
+ {{ projectEntry.treatmentDoctorName || "选择治疗医生" }}
+
+
+
+ 有效期
+
+
+
+
+ {{ projectEntry.validTime || "选择日期/长期" }}
+
+
+
+ 套餐有效期已锁定
+
+
+
+ 生成待办
+
+
+
+
+ 类型:{{ getTodoTypeLabel(projectEntry.todoConfig.eventType) }}
+ 回访日期{{ projectEntry.todoConfig.planDate }}截止日期{{ projectEntry.todoConfig.expireDate }}
+ {{ projectEntry.todoConfig.executorName || '请选择团队和处理人' }}
+ 完成关联核销权益
+
+
+ 删除套餐
+
+
项目名称
-
+
{{ entry.project?.projectName || "请选择权益项目" }}
@@ -44,8 +143,10 @@
折扣
-
-
+
+ {{ Number(entry.discount).toFixed(1) }}
+
+
总价
-
+
@@ -112,7 +213,7 @@
:disabled="!entry.project?._id || !getProjectDepts(entry).length"
@change="changeDept($event, entry)"
>
-
+
{{ entry.dept?.deptName || (entry.project ? "该项目未配置治疗科室" : "请先选择权益项目") }}
@@ -120,7 +221,6 @@
-
计划治疗医生
+
+ 生成待办
+
+
+
+
+ 类型:{{ getTodoTypeLabel(entry.todoConfig.eventType) }}
+ 回访日期{{ entry.todoConfig.planDate }}截止日期{{ entry.todoConfig.expireDate }}
+ {{ entry.todoConfig.executorName || '请选择团队和处理人' }}
+ 完成关联核销权益
+
+
删除此项目
+
@@ -145,18 +258,45 @@
添加权益项目
+
+
+
+
+
+
+
+
+
+ {{ team.name }}
+
+ {{ member.name }}已选择
+
+ 暂无团队成员
+
+ 暂无匹配的团队或处理人
+
+
+
+
-
+
-
+
- 单项目
+
{{ project.projectName }}
@@ -164,7 +304,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) }}
+
+ 暂无可用权益项目或套餐
加载中...
已加载全部权益项目
@@ -174,19 +319,52 @@
-
-
->>>>>>> dev-2.45hjf
diff --git a/pages/work/todo/todo-detail.vue b/pages/work/todo/todo-detail.vue
index d724fe2..830b2f6 100644
--- a/pages/work/todo/todo-detail.vue
+++ b/pages/work/todo/todo-detail.vue
@@ -239,6 +239,16 @@ async function completeTask() {
userId: doctorInfo.value.userid,
})
if (res && res.success) {
+ if (todo.value?.benefitDeductOnComplete && todo.value?.benefitRecordId) {
+ const deductRes = await api('completeBenefitTodo', {
+ corpId: account.value.corpId,
+ todoId: todo.value._id,
+ treatmentRecordId: todo.value.benefitRecordId,
+ executorUserId: doctorInfo.value.userid,
+ completedAt: Date.now(),
+ });
+ if (!deductRes?.success) return toast(deductRes?.message || '待办已完成,但权益自动核销失败');
+ }
await toast('操作成功');
uni.navigateBack();
} else {
@@ -310,4 +320,4 @@ useLoad(opts => {
.h-120 {
height: 240rpx;
}
-
\ No newline at end of file
+
diff --git a/utils/api.js b/utils/api.js
index 7ec7259..c6b57b3 100644
--- a/utils/api.js
+++ b/utils/api.js
@@ -12,6 +12,7 @@ const urlsConfig = {
getTeamData: 'getTeamData',
getTeamById: 'getTeamById',
getTeamBymember: 'getTeamBymember',
+ getAllTeamByCorp: 'getAllTeamByCorp',
getCurrentTemplate: 'getCurrentTemplate',
getTemplateGroup: 'getTemplateGroup',
getTemplateListByTemptype: 'getTemplateListByTemptype',
@@ -39,6 +40,7 @@ const urlsConfig = {
getHlwHospitalList: 'getHlwHospitalList',
updateAutoAcceptConsult: 'updateAutoAcceptConsult',
getAutoAcceptConsult: 'getAutoAcceptConsult',
+ getCorpMemberByUserId: 'getCorpMemberByUserId'
},
knowledgeBase: {
@@ -101,10 +103,16 @@ const urlsConfig = {
// 健康档案相关接口
addMedicalRecord: 'addMedicalRecord',
addTreatmentRecord: "addTreatmentRecord",
+ updateTreatmentRecord: "updateTreatmentRecord",
+ completeBenefitTodo: "completeBenefitTodo",
+ getProjectPackageList: "getProjectPackageList",
+ getTreatmentRecord: "getTreatmentRecord",
+ getDeductRecord: "getDeductRecord",
getMedicalRecordById: 'getMedicalRecordById',
updateMedicalRecord: 'updateMedicalRecord',
removeMedicalRecord: 'removeMedicalRecord',
getCustomerMedicalRecord: 'getCustomerMedicalRecord',
+ getMemberInfo: "getMemberInfo",
// 客户阶段
getCustomerType: 'getCustomerType',
},
@@ -151,7 +159,8 @@ const urlsConfig = {
customerTransferRecord: 'customerTransferRecord',
// sendConsultRejectedMessage: "sendConsultRejectedMessage"
getTeamTodos: 'getTeamTodos',
- updateTaskTodo: 'updateTaskTodo'
+ updateTaskTodo: 'updateTaskTodo',
+ createTodo: 'createTodo'
}
}
diff --git a/utils/todo-const.js b/utils/todo-const.js
index 26a63b2..942f793 100644
--- a/utils/todo-const.js
+++ b/utils/todo-const.js
@@ -1,20 +1,46 @@
export const TODO_EVENT_TYPE_LABELS = {
- 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 || '');