ykt-wxapp/pages/case/plan-list.vue

230 lines
5.5 KiB
Vue
Raw Permalink Normal View History

2026-01-22 17:39:23 +08:00
<template>
2026-01-26 15:39:14 +08:00
<!-- Mobile 来源: ykt-management-mobile/src/pages/manage-plan/plan-list/plan-list.vue -->
2026-01-22 17:39:23 +08:00
<view class="page">
2026-01-26 15:39:14 +08:00
<view v-if="loading" class="loading">加载中...</view>
<view v-else-if="list.length === 0" class="empty">
2026-01-22 17:39:23 +08:00
<image class="empty-img" src="/static/empty.svg" mode="aspectFit" />
<view class="empty-text">暂无回访计划</view>
</view>
<scroll-view v-else scroll-y class="scroll">
<view v-for="(p, idx) in list" :key="p.id" class="item">
<view class="left">
<view class="name-row">
<view class="name">{{ p.planName }}</view>
<view v-if="p.planType === 'corp'" class="tag corp">机构</view>
<view class="tag outline" @click.stop="preview(p)">详情</view>
</view>
<view class="desc">应用范围{{ p.planDetail }}</view>
</view>
<view class="btn" @click="select(p)">选择</view>
</view>
<view style="height: 24px;"></view>
</scroll-view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
2026-01-26 15:39:14 +08:00
import { storeToRefs } from 'pinia';
import api from '@/utils/api';
import useAccountStore from '@/store/account';
import { toast } from '@/utils/widget';
import { getTodoEventTypeLabel } from '@/utils/todo-const';
2026-01-22 17:39:23 +08:00
const archiveId = ref('');
2026-01-26 15:39:14 +08:00
const loading = ref(false);
2026-01-22 17:39:23 +08:00
2026-01-26 15:39:14 +08:00
const list = ref([]);
const accountStore = useAccountStore();
const { account, doctorInfo } = storeToRefs(accountStore);
const { getDoctorInfo } = accountStore;
2026-01-22 17:39:23 +08:00
onLoad((options) => {
archiveId.value = options?.archiveId ? String(options.archiveId) : '';
2026-01-26 15:39:14 +08:00
loadList();
2026-01-22 17:39:23 +08:00
});
2026-01-26 15:39:14 +08:00
async function ensureDoctor() {
if (doctorInfo.value) return;
if (!account.value?.openid) return;
try {
await getDoctorInfo();
} catch {
// ignore
}
}
function getUserId() {
const d = doctorInfo.value || {};
const a = account.value || {};
return String(d.userid || d.userId || d.corpUserId || a.userid || a.userId || '') || '';
}
function getCorpId() {
const t = uni.getStorageSync('ykt_case_current_team') || {};
const a = account.value || {};
const d = doctorInfo.value || {};
return String(t.corpId || a.corpId || d.corpId || '') || '';
}
function getTeamId() {
const t = uni.getStorageSync('ykt_case_current_team') || {};
return String(t.teamId || '') || '';
}
function normalizePlan(raw) {
if (!raw || typeof raw !== 'object') return null;
const id = String(raw.planId || raw._id || '');
if (!id) return null;
const taskList = Array.isArray(raw.taskList) ? raw.taskList : [];
const first = taskList[0] && typeof taskList[0] === 'object' ? taskList[0] : {};
const eventType = String(first.eventType || '');
const taskContent = String(first.taskContent || '');
return {
...raw,
id,
planName: String(raw.planName || ''),
planType: String(raw.planType || ''),
planDetail: String(raw.planDetail || ''),
firstEventType: eventType,
firstEventTypeLabel: eventType ? getTodoEventTypeLabel(eventType) : '',
taskContent,
taskCount: taskList.length,
taskList,
};
}
async function loadList() {
if (loading.value) return;
loading.value = true;
try {
await ensureDoctor();
const corpId = getCorpId();
const userId = getUserId();
const teamId = getTeamId();
if (!corpId || !userId || !teamId) {
list.value = [];
toast('缺少用户/团队信息');
return;
}
const res = await api('getManagementPlan', {
corpId,
userId,
planType: 'team',
teamId,
page: 1,
pageSize: 999,
});
if (!res?.success) {
list.value = [];
toast(res?.message || '获取回访计划失败');
return;
}
const arr = Array.isArray(res.data) ? res.data : [];
list.value = arr.filter((p) => p && p.planStatus === true).map(normalizePlan).filter(Boolean);
} finally {
loading.value = false;
}
}
2026-01-22 17:39:23 +08:00
function select(plan) {
uni.setStorageSync('select-mamagement-plan', plan);
2026-01-26 15:39:14 +08:00
uni.navigateTo({ url: `/pages/case/plan-execute?archiveId=${encodeURIComponent(archiveId.value)}` });
2026-01-22 17:39:23 +08:00
}
function preview(plan) {
2026-01-26 15:39:14 +08:00
uni.setStorageSync('preview-mamagement-plan', plan);
uni.navigateTo({ url: `/pages/case/plan-preview?archiveId=${encodeURIComponent(archiveId.value)}` });
2026-01-22 17:39:23 +08:00
}
</script>
<style scoped>
.page {
height: 100vh;
background: #fff;
}
.scroll {
height: 100vh;
}
2026-01-26 15:39:14 +08:00
.loading {
padding: 16px;
font-size: 13px;
color: #9aa0a6;
}
2026-01-22 17:39:23 +08:00
.item {
display: flex;
align-items: center;
padding: 12px 14px;
border-bottom: 1px solid #f2f2f2;
}
.left {
flex: 1;
min-width: 0;
margin-right: 10px;
}
.name-row {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 6px;
}
.name {
font-size: 14px;
font-weight: 600;
color: #333;
max-width: 220px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tag {
font-size: 12px;
padding: 4px 8px;
border-radius: 6px;
}
.tag.corp {
background: #4f6ef7;
color: #fff;
}
.tag.outline {
border: 1px solid #4f6ef7;
color: #4f6ef7;
background: #fff;
}
.desc {
font-size: 12px;
color: #999;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.btn {
flex-shrink: 0;
padding: 8px 12px;
border-radius: 999px;
border: 1px solid #4f6ef7;
color: #4f6ef7;
font-size: 13px;
}
.empty {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.empty-img {
width: 160px;
height: 160px;
opacity: 0.9;
}
.empty-text {
margin-top: 10px;
font-size: 13px;
color: #9aa0a6;
}
</style>