feat: 添加客户流转记录接口,更新病案号显示逻辑

This commit is contained in:
Jafeng 2026-01-29 19:07:11 +08:00
parent 8842217b61
commit 6a16ce1bbb
3 changed files with 113 additions and 57 deletions

View File

@ -1,18 +1,6 @@
<template>
<!-- Mobile 来源: ykt-management-mobile/src/pages/customer/customer-detail/customer-profile.vue -->
<view class="wrap">
<view class="sub-tabs">
<view
v-for="t in anchors"
:key="t.value"
class="sub-tab"
:class="{ active: activeAnchor === t.value }"
@click="scrollToAnchor(t.value)"
>
{{ t.label }}
</view>
</view>
<view class="card">
<view id="anchor-base" class="section-title" @click="startEdit">
<text>基本信息</text>
@ -55,7 +43,7 @@
<view class="row" @click="openTransferRecord">
<view class="label">院内来源</view>
<view class="val link">
{{ forms.creator || '点击查看' }}
{{ latestTransferRecord?.executeTeamName || '点击查看' }}
<uni-icons type="arrowright" size="14" color="#4f6ef7" />
</view>
</view>
@ -88,26 +76,33 @@
<uni-popup ref="transferPopupRef" type="bottom" :mask-click="true">
<view class="popup">
<view class="popup-title">
<view class="popup-title-text">院内流转记录mock</view>
<view class="popup-title-text">院内流转记录</view>
<view class="popup-close" @click="closeTransferRecord">
<uni-icons type="closeempty" size="18" color="#666" />
</view>
</view>
<scroll-view scroll-y class="popup-body">
<view class="timeline">
<view v-if="transferRecords.length" class="timeline">
<view class="line"></view>
<view v-for="r in transferRecords" :key="r._id" class="item">
<view class="dot"></view>
<view class="content">
<view class="time">{{ r.time }}</view>
<view class="time">{{ r.createTime }}</view>
<view class="card2">
<view class="trow"><text class="tlabel">转入团队:</text>{{ r.team }}</view>
<view class="trow"><text class="tlabel">转入方式:</text>{{ r.type }}</view>
<view class="trow"><text class="tlabel">操作人:</text>{{ r.user }}</view>
<view v-if="r.executeTeamName" class="trow"><text class="tlabel">转入团队:</text>{{ r.executeTeamName }}</view>
<view v-if="r.eventTypeName" class="trow"><text class="tlabel">转入方式:</text>{{ r.eventTypeName }}</view>
<view v-if="r.creatorUserId" class="trow">
<text class="tlabel">操作人:</text>
<text v-if="r.creatorUserId === 'system'">系统自动建档</text>
<text v-else>{{ r.creatorUserId }}</text>
</view>
</view>
</view>
</view>
</view>
<view v-else class="empty-state">
<text class="empty-text">暂无流转记录</text>
</view>
</scroll-view>
</view>
</uni-popup>
@ -115,9 +110,13 @@
</template>
<script setup>
import { computed, reactive, ref, watch } from 'vue';
import { computed, reactive, ref, watch, onMounted } from 'vue';
import { storeToRefs } from 'pinia';
import dayjs from 'dayjs';
import FormTemplate from '@/components/form-template/index.vue';
import api from '@/utils/api';
import useAccountStore from '@/store/account';
import useTeamStore from '@/store/team';
const props = defineProps({
data: { type: Object, default: () => ({}) },
@ -127,11 +126,10 @@ const props = defineProps({
});
const emit = defineEmits(['save']);
const anchors = [
{ label: '基本信息', value: 'base' },
{ label: '内部信息', value: 'internal' },
];
const activeAnchor = ref('base');
const accountStore = useAccountStore();
const teamStore = useTeamStore();
const { account, doctorInfo } = storeToRefs(accountStore);
const { teams } = storeToRefs(teamStore);
const editing = ref(false);
const baseFormRef = ref(null);
@ -224,7 +222,21 @@ function displayValue(item) {
return list.length ? `已上传${list.length}` : '-';
}
if (Array.isArray(v)) return v.filter(Boolean).join('、') || '-';
if (Array.isArray(v)) {
// rangelabel
if (type === 'select' || type === 'radio' || type === 'selectAndImage' || type === 'tagPicker' || item.__originType === 'tag') {
const range = Array.isArray(item?.range) ? item.range : [];
if (range.length && typeof range[0] === 'object') {
const labels = v.map((val) => {
const found = range.find((i) => String(i?.value) === String(val));
return found ? String(found.label || found.value || val) : String(val);
}).filter(Boolean);
return labels.length ? labels.join('、') : '-';
}
}
return v.filter(Boolean).join('、') || '-';
}
if (typeof v === 'object') {
if ('label' in v) return String(v.label || '-');
if ('name' in v) return String(v.name || '-');
@ -258,18 +270,69 @@ function scrollToAnchor(key) {
const transferPopupRef = ref(null);
const transferRecords = ref([]);
const latestTransferRecord = computed(() => transferRecords.value[0]);
function openTransferRecord() {
transferRecords.value = [
{ _id: 't1', time: dayjs().subtract(120, 'day').format('YYYY-MM-DD HH:mm'), team: '口腔一科(示例)', type: '系统建档', user: '系统' },
{ _id: 't2', time: dayjs().subtract(30, 'day').format('YYYY-MM-DD HH:mm'), team: '正畸团队(示例)', type: '团队流转', user: '管理员A' },
];
const CURRENT_TEAM_STORAGE_KEY = 'ykt_case_current_team';
function getCorpId() {
const d = doctorInfo.value || {};
const a = account.value || {};
const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
return String(d.corpId || a.corpId || team.corpId || '') || '';
}
const ServiceType = {
remindFiling: '自主开拓',
adminTransferTeams: '团队流转',
adminRemoveTeams: '移出团队',
systemAutoDistribute: '系统分配',
bindWechatCustomer: '绑定企业微信',
};
async function fetchTransferRecords() {
const customerId = props.data?._id;
if (!customerId) return;
try {
const res = await api('customerTransferRecord', { customerId });
if (res?.success && res.list) {
const allTeams = Array.isArray(teams.value) ? teams.value : [];
transferRecords.value = res.list.map((item) => {
const record = { ...item };
record.createTime = dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss');
record.executeTeamName = allTeams.find((team) => team.teamId === item.executeTeamId)?.name || item.executeTeamName;
record.eventTypeName = ServiceType[item.eventType] || item.eventType;
if (item.transferToTeamIds && Array.isArray(item.transferToTeamIds)) {
record.teamName = item.transferToTeamIds.map((teamId) => allTeams.find((team) => team.teamId === teamId)?.name).join('、');
}
if (item.removeTeamIds && Array.isArray(item.removeTeamIds)) {
record.teamName = item.removeTeamIds.map((teamId) => allTeams.find((team) => team.teamId === teamId)?.name).join('、');
}
if (item.eventType === 'remindFiling') record.eventTypeName = '自主开拓';
return record;
});
}
} catch (e) {
console.error('获取流转记录失败', e);
}
}
async function openTransferRecord() {
await fetchTransferRecords();
transferPopupRef.value?.open?.();
}
function closeTransferRecord() {
transferPopupRef.value?.close?.();
}
onMounted(() => {
fetchTransferRecords();
});
watch(() => props.data?._id, () => {
if (props.data?._id) fetchTransferRecords();
});
</script>
<style scoped>
@ -277,24 +340,6 @@ function closeTransferRecord() {
padding: 12px 0 96px;
}
.sub-tabs {
display: flex;
background: #f5f6f8;
border-bottom: 1px solid #f2f2f2;
}
.sub-tab {
flex: 1;
text-align: center;
height: 40px;
line-height: 40px;
font-size: 13px;
color: #666;
}
.sub-tab.active {
color: #4f6ef7;
font-weight: 600;
}
.card {
background: #fff;
margin-top: 10px;
@ -455,4 +500,14 @@ function closeTransferRecord() {
color: #666;
margin-right: 6px;
}
.empty-state {
padding: 40px 20px;
text-align: center;
}
.empty-text {
font-size: 14px;
color: #999;
}
</style>

View File

@ -249,11 +249,7 @@ function switchTab(key) {
currentTab.value = key;
// tab tab
nextTick(() => {
// tabs
measureTabsTop();
setTimeout(() => {
uni.pageScrollTo({ scrollTop: tabsScrollTop.value || 0, duration: 0 });
}, 0);
uni.pageScrollTo({ scrollTop: tabsScrollTop.value || 0, duration: 300 });
});
}
@ -303,6 +299,9 @@ function normalizeArchiveFromApi(raw) {
outpatientNo: r.outpatientNo || '',
inpatientNo: r.inpatientNo || '',
medicalRecordNo: r.medicalRecordNo || '',
customerNumber: r.customerNumber || '',
customerProfileNo2: r.customerProfileNo2 || '',
customerProfileNo3: r.customerProfileNo3 || '',
createTime: r.createTime || '',
creator: r.creator || '',
notes: r.notes || r.remark || '',
@ -548,9 +547,9 @@ const sexOrAge = computed(() => {
const idRows = computed(() => {
const rows = [];
if (archive.value.outpatientNo) rows.push({ label: '门诊号', value: String(archive.value.outpatientNo) });
if (archive.value.inpatientNo) rows.push({ label: '住院号', value: String(archive.value.inpatientNo) });
if (archive.value.medicalRecordNo) rows.push({ label: '病案号', value: String(archive.value.medicalRecordNo) });
if (archive.value.customerNumber) rows.push({ label: '病案号1', value: String(archive.value.customerNumber) });
if (archive.value.customerProfileNo2) rows.push({ label: '病案号2', value: String(archive.value.customerProfileNo2) });
if (archive.value.customerProfileNo3) rows.push({ label: '病案号3', value: String(archive.value.customerProfileNo3) });
return rows;
});

View File

@ -116,6 +116,8 @@ const urlsConfig = {
addServiceRecord: 'addServiceRecord',
updateServiceRecord: 'updateServiceRecord',
removeServiceRecord: 'removeServiceRecord',
// 客户流转记录
customerTransferRecord: 'customerTransferRecord',
// sendConsultRejectedMessage: "sendConsultRejectedMessage"
}