bug修复2

This commit is contained in:
zhanchao 2026-09-10 16:40:45 +08:00
parent 7d9f8d6522
commit 77ddd4899a
2 changed files with 223 additions and 14 deletions

View File

@ -821,16 +821,16 @@ async function getMore() {
return;
}
// { success, data: { data: [], total } }
// { success, data: [], total } { data: { data: [], total } }
const payload = res?.data;
const arr = payload && Array.isArray(payload.data)
const arr = Array.isArray(payload?.data)
? payload.data
: Array.isArray(payload)
? payload
: [];
const next = arr.map(formatTodo);
total.value = payload && typeof payload.total === "number" ? payload.total : 0;
total.value = Number(payload?.total ?? res?.total ?? arr.length) || 0;
pages.value = Math.ceil(total.value / pageSize) || 0;
list.value = page.value === 1 ? next : [...list.value, ...next];
page.value += 1;

View File

@ -1,7 +1,7 @@
<template>
<page-meta
:page-style="projectPickerVisible || todoExecutorPickerVisible || billDeptPickerVisible ? 'overflow: hidden;' : ''"></page-meta>
<full-page ref="pageRef" pageStyle="background:#f5f6f8" pageClass="benefit-page-shell">
<full-page ref="pageRef" pageClass="benefit-page-shell">
<view class="benefit-page">
<view class="patient-card">
<view class="patient-card-accent"></view>
@ -42,7 +42,12 @@
</picker>
</view>
<view class="section-title">权益项目</view>
<view class="section-title-row">
<view class="section-title">权益项目</view>
<view class="batch-operation-button" @tap="openBatchTodoPicker">
<text>批量操作</text>
</view>
</view>
<view v-for="(entry, index) in entries" :id="`entry-${entry.key}`" :key="entry.key" class="entry-card">
<template v-if="entry.isPackage">
<view class="package-card-head">
@ -54,10 +59,10 @@
</view>
<view class="package-summary">
<text>组合形式{{ entry.packageType === "free" ? `${entry.projects.length}${entry.projectNumber}` : "固定组合"
}}</text>
}}</text>
<text>必选项{{ entry.requiredCount }}</text>
<text v-if="entry.packageType === 'free'">可选项{{ entry.optionalSelectedCount }} / {{ entry.optionalCount
}}</text>
}}</text>
</view>
<view v-if="showBenefitAmount" class="field-row">
<view class="field-block">
@ -105,7 +110,7 @@
:disabled="!getProjectDepts(projectEntry).length" @change="changeDept($event, projectEntry)">
<view class="project-input" :class="{ 'required-select': !projectEntry.dept }"><text
:class="projectEntry.dept ? 'value-text' : 'placeholder-text'">{{ projectEntry.dept?.deptName ||
"请选择治疗科室" }}</text><uni-icons type="right" size="18" color="#999" /></view>
"请选择治疗科室" }}</text><uni-icons type="right" size="18" color="#999" /></view>
</picker>
</view>
<view v-if="projectEntry.selected" class="field-group">
@ -141,7 +146,7 @@
<input v-model="projectEntry.todoConfig.taskContent" class="todo-input" placeholder="任务内容" />
<picker :range="todoTypeOptions" range-key="label" @change="changeTodoType($event, projectEntry)">
<view class="project-input"><text>类型{{ getTodoTypeLabel(projectEntry.todoConfig.eventType)
}}</text><uni-icons type="right" size="16" color="#999" /></view>
}}</text><uni-icons type="right" size="16" color="#999" /></view>
</picker>
<view class="field-row">
<view class="field-block">
@ -330,6 +335,38 @@
<text>添加权益项目</text>
</view>
<view v-if="batchTodoVisible" class="picker-mask" @tap="closeBatchTodoPicker">
<view class="batch-todo-picker" @tap.stop>
<view class="picker-header">
<text class="picker-title">生成待办批量操作</text>
<uni-icons type="closeempty" size="22" color="#666" @tap="closeBatchTodoPicker" />
</view>
<view class="batch-todo-row" @tap.stop>
<text>批量生成待办</text>
<switch :checked="batchTodoConfig.todoEnabled" color="#0877f1"
@change="batchTodoConfig.todoEnabled = $event.detail.value" />
</view>
<template v-if="batchTodoConfig.todoEnabled">
<view class="batch-todo-row">
<text>待办完成后关联核销权益</text>
<switch :checked="batchTodoConfig.deductBenefit" color="#0877f1"
@change="batchTodoConfig.deductBenefit = $event.detail.value" />
</view>
<view class="batch-todo-field" @tap="openBatchExecutorPicker">
<text>处理人</text>
<text :class="batchTodoConfig.executorUserId ? 'value-text' : 'placeholder-text'">
{{ batchTodoConfig.executorName || "请选择待办处理人" }}
</text>
<uni-icons type="right" size="16" color="#999" />
</view>
</template>
<view class="batch-todo-actions">
<button class="batch-todo-cancel" @tap="closeBatchTodoPicker">取消</button>
<button class="batch-todo-confirm" @tap="applyBatchTodoConfig">确定</button>
</view>
</view>
</view>
<view v-if="todoExecutorPickerVisible" class="picker-mask" @click="closeTodoExecutorPicker">
<view class="todo-executor-picker" :style="{ '--keyboard-height': `${keyboardHeight}px` }" @click.stop>
<view class="picker-header"><text class="picker-title">请选择团队和处理人</text><uni-icons type="closeempty" size="22"
@ -383,10 +420,10 @@
<view class="project-depts">{{ packageItem.packageType === "free" ?
`自由组合:${packageItem.projects.length}${packageItem.projectNumber}` : "固定组合" }} · {{
(packageItem.projects ||
[]).map((item) => item.projectName).join("、") }}</view>
[]).map((item) => item.projectName).join("、")}}</view>
</view>
<view v-if="showBenefitAmount" class="project-price">¥{{ Number(packageItem.packagePrice || 0).toFixed(2)
}}
}}
</view>
</view>
<view v-if="!projectLoading && !projectList.length && !packageList.length" class="empty-text">暂无可用权益项目或套餐
@ -424,7 +461,8 @@
</view>
<template #footer>
<view class="footer-bar">
<view v-if="!batchTodoVisible && !todoExecutorPickerVisible && !projectPickerVisible && !billDeptPickerVisible"
class="footer-bar">
<view v-if="showBenefitAmount" class="footer-summary">
<view class="total-summary" @tap="toggleBenefitDetail">
<text class="summary-label">总金额</text>
@ -513,6 +551,16 @@ const todoExecutorPickerVisible = ref(false);
const todoExecutorTarget = ref(null);
const todoExecutorKeyword = ref("");
const todoExecutorRefreshing = ref(false);
const batchTodoVisible = ref(false);
const batchTodoConfig = ref({
todoEnabled: false,
deductBenefit: false,
executorUserId: "",
executorName: "",
executeTeamId: "",
executeTeamName: "",
});
const batchExecutorTarget = ref(null);
const benefitDetailVisible = ref(false);
const todoTypeOptions = Object.entries(TODO_EVENT_TYPE_LABELS).map(([value, label]) => ({ value, label }));
let searchTimer = null;
@ -1247,6 +1295,51 @@ function toggleTodo(event, entry) {
if (entry.todoEnabled) entry.todoConfig = entry.todoConfig || getDefaultTodoConfig(entry);
}
function openBatchTodoPicker() {
batchTodoVisible.value = true;
}
function closeBatchTodoPicker() {
batchTodoVisible.value = false;
}
function openBatchExecutorPicker() {
batchExecutorTarget.value = { todoConfig: batchTodoConfig.value };
todoExecutorTarget.value = batchExecutorTarget.value;
todoExecutorKeyword.value = "";
todoExecutorPickerVisible.value = true;
if (!todoTeams.value.length) refreshTodoExecutors();
}
function applyBatchTodoConfig() {
const applyConfig = (entry) => {
if (!entry?.project?._id) return;
entry.todoEnabled = Boolean(batchTodoConfig.value.todoEnabled);
if (!entry.todoEnabled) {
entry.todoConfig = null;
return;
}
entry.todoConfig = entry.todoConfig || getDefaultTodoConfig(entry);
entry.todoConfig.deductBenefit = Boolean(batchTodoConfig.value.deductBenefit);
if (batchTodoConfig.value.executorUserId) {
Object.assign(entry.todoConfig, {
executorUserId: batchTodoConfig.value.executorUserId,
executorName: batchTodoConfig.value.executorName,
executeTeamId: batchTodoConfig.value.executeTeamId,
executeTeamName: batchTodoConfig.value.executeTeamName,
});
}
};
entries.value.forEach((entry) => {
if (entry.isPackage) {
entry.projects.filter((project) => project.selected).forEach(applyConfig);
} else {
applyConfig(entry);
}
});
}
function getTodoTypeLabel(value) {
return TODO_EVENT_TYPE_LABELS[value] || "请选择类型";
}
@ -1658,6 +1751,10 @@ async function submitEntries() {
background: #f5f6f8;
}
.benefit-page-shell :global(.safeareaBottom) {
background: #fff;
}
.benefit-page {
min-height: 100%;
padding: 20rpx 24rpx 32rpx;
@ -1774,6 +1871,18 @@ async function submitEntries() {
font-weight: 700;
}
.section-title-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
}
.section-title-row .section-title {
flex: 1;
min-width: 0;
}
.entry-card {
background: #fff;
border-radius: 18rpx;
@ -2015,6 +2124,105 @@ async function submitEntries() {
font-weight: 600;
}
.project-name-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
}
.project-name-row .field-label {
margin-bottom: 12rpx;
}
.batch-operation-button {
flex-shrink: 0;
padding: 8rpx 16rpx;
border: 1rpx solid #0877f1;
border-radius: 8rpx;
color: #0877f1;
background: #f5f9ff;
font-size: 24rpx;
line-height: 1.3;
}
.batch-todo-picker {
position: fixed;
right: 0;
bottom: var(--keyboard-height);
left: 0;
z-index: 10001;
box-sizing: border-box;
padding: 28rpx 28rpx 32rpx;
border-radius: 24rpx 24rpx 0 0;
background: #fff;
}
.batch-todo-picker .picker-header {
padding-bottom: 20rpx;
border-bottom: 1rpx solid #eef2f7;
}
.batch-todo-row,
.batch-todo-field {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
min-height: 76rpx;
padding: 0 4rpx;
color: #374151;
font-size: 28rpx;
}
.batch-todo-row+.batch-todo-row {
margin-top: 8rpx;
}
.batch-todo-field {
min-height: 82rpx;
margin-top: 12rpx;
padding: 0 20rpx;
border: 1rpx solid #d1d5db;
border-radius: 12rpx;
background: #fff;
}
.batch-todo-field text:nth-child(2) {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: right;
}
.batch-todo-actions {
display: flex;
gap: 20rpx;
margin-top: 28rpx;
}
.batch-todo-actions button {
flex: 1;
height: 76rpx;
line-height: 76rpx;
border-radius: 12rpx;
font-size: 28rpx;
}
.batch-todo-cancel {
color: #606266;
border: 1rpx solid #d1d5db;
background: #fff;
}
.batch-todo-confirm {
color: #fff;
background: #0877f1;
box-shadow: 0 8rpx 18rpx rgba(8, 119, 241, 0.2);
}
.bill-dept-picker {
display: block;
min-height: 76rpx;
@ -2264,7 +2472,7 @@ async function submitEntries() {
border-top: 1rpx solid #eef2f7;
box-shadow: 0 -4rpx 16rpx rgba(15, 23, 42, 0.04);
box-sizing: border-box;
z-index: 1;
z-index: 0;
}
.footer-summary {
@ -2431,10 +2639,11 @@ async function submitEntries() {
.picker-mask {
position: fixed;
inset: 0;
z-index: 10000;
z-index: 99999;
background: rgba(0, 0, 0, 0.4);
display: flex;
align-items: flex-end;
margin-bottom: env(safe-area-inset-bottom);
box-sizing: border-box;
}