ykt-wxapp/pages/case/plan-list.vue
2026-01-26 15:39:14 +08:00

230 lines
5.5 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- Mobile 来源: ykt-management-mobile/src/pages/manage-plan/plan-list/plan-list.vue -->
<view class="page">
<view v-if="loading" class="loading">加载中...</view>
<view v-else-if="list.length === 0" class="empty">
<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';
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';
const archiveId = ref('');
const loading = ref(false);
const list = ref([]);
const accountStore = useAccountStore();
const { account, doctorInfo } = storeToRefs(accountStore);
const { getDoctorInfo } = accountStore;
onLoad((options) => {
archiveId.value = options?.archiveId ? String(options.archiveId) : '';
loadList();
});
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;
}
}
function select(plan) {
uni.setStorageSync('select-mamagement-plan', plan);
uni.navigateTo({ url: `/pages/case/plan-execute?archiveId=${encodeURIComponent(archiveId.value)}` });
}
function preview(plan) {
uni.setStorageSync('preview-mamagement-plan', plan);
uni.navigateTo({ url: `/pages/case/plan-preview?archiveId=${encodeURIComponent(archiveId.value)}` });
}
</script>
<style scoped>
.page {
height: 100vh;
background: #fff;
}
.scroll {
height: 100vh;
}
.loading {
padding: 16px;
font-size: 13px;
color: #9aa0a6;
}
.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>