Merge remote-tracking branch 'origin/dev-hjf' into dev-wdb
This commit is contained in:
commit
fbd51dc0d7
@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<CustomerProfileTab
|
||||
:data="archive"
|
||||
:baseItems="baseItems"
|
||||
:internalItems="internalItems"
|
||||
:floatingBottom="16"
|
||||
@save="savePatch"
|
||||
/>
|
||||
<scroll-view scroll-y class="scroll" :style="{ height: scrollHeight + 'px' }">
|
||||
<CustomerProfileTab
|
||||
:data="archive"
|
||||
:baseItems="baseItems"
|
||||
:internalItems="internalItems"
|
||||
:floatingBottom="16"
|
||||
@save="savePatch"
|
||||
/>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -44,6 +46,7 @@ const archive = ref({
|
||||
|
||||
const baseItems = ref([]);
|
||||
const internalItems = ref([]);
|
||||
const scrollHeight = ref(0);
|
||||
|
||||
const accountStore = useAccountStore();
|
||||
const { account, doctorInfo } = storeToRefs(accountStore);
|
||||
@ -336,6 +339,7 @@ async function savePatch(patch) {
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
scrollHeight.value = Number(uni.getSystemInfoSync()?.windowHeight || 0) || 0;
|
||||
archiveId.value = options?.archiveId ? String(options.archiveId) : '';
|
||||
loadFromStorage();
|
||||
ensureDoctor().then(async () => {
|
||||
@ -351,7 +355,12 @@ onShow(() => {
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: #f5f6f8;
|
||||
}
|
||||
|
||||
.scroll {
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,57 +1,61 @@
|
||||
<template>
|
||||
<!-- Mobile 来源: ykt-management-mobile/src/pages/customer/new-followup-record/new-followup-record.vue(简化移植:去除 pinia/接口) -->
|
||||
<view class="page">
|
||||
<view class="card">
|
||||
<picker mode="date" :value="form.plannedExecutionTime" @change="changeDate">
|
||||
<view class="row clickable">
|
||||
<view class="label">回访日期</view>
|
||||
<scroll-view scroll-y class="scroll" :style="{ height: scrollHeight + 'px' }">
|
||||
<view class="card">
|
||||
<picker mode="date" :value="form.plannedExecutionTime" @change="changeDate">
|
||||
<view class="row clickable">
|
||||
<view class="label">回访日期</view>
|
||||
<view class="right">
|
||||
<view class="value" :class="{ muted: !form.plannedExecutionTime }">{{ form.plannedExecutionTime || '请选择回访日期' }}</view>
|
||||
<uni-icons type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
|
||||
<view class="block">
|
||||
<view class="block-title">回访方式</view>
|
||||
<view class="method-row">
|
||||
<view class="method" @click="selectMethod('phone')">
|
||||
<image class="radio" :src="`/static/circle${form.todoMethod === 'phone' ? 'd' : ''}.svg`" />
|
||||
<view class="m-label">电话</view>
|
||||
<view v-if="form.todoMethod === 'phone'" class="m-value" :class="{ muted: !form.phoneNumber }">{{ form.phoneNumber || '请选择电话号码' }}</view>
|
||||
<uni-icons v-if="form.todoMethod === 'phone'" type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
<view class="method" @click="selectMethod('wechat')">
|
||||
<image class="radio" :src="`/static/circle${form.todoMethod === 'wechat' ? 'd' : ''}.svg`" />
|
||||
<view class="m-label">微信</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="row clickable" @click="selectType">
|
||||
<view class="label">回访类型</view>
|
||||
<view class="right">
|
||||
<view class="value" :class="{ muted: !form.plannedExecutionTime }">{{ form.plannedExecutionTime || '请选择回访日期' }}</view>
|
||||
<view class="value" :class="{ muted: !form.eventType }">{{ eventTypeLabel || '请选择回访类型' }}</view>
|
||||
<uni-icons type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
|
||||
<view class="block">
|
||||
<view class="block-title">回访方式</view>
|
||||
<view class="method-row">
|
||||
<view class="method" @click="selectMethod('phone')">
|
||||
<image class="radio" :src="`/static/circle${form.todoMethod === 'phone' ? 'd' : ''}.svg`" />
|
||||
<view class="m-label">电话</view>
|
||||
<view v-if="form.todoMethod === 'phone'" class="m-value" :class="{ muted: !form.phoneNumber }">{{ form.phoneNumber || '请选择电话号码' }}</view>
|
||||
<uni-icons v-if="form.todoMethod === 'phone'" type="arrowright" size="16" color="#999" />
|
||||
<view class="row clickable" @click="selectTeam">
|
||||
<view class="label">所在团队</view>
|
||||
<view class="right">
|
||||
<view class="value" :class="{ muted: !form.teamId }">{{ form.teamName || '请选择团队' }}</view>
|
||||
<uni-icons type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
<view class="method" @click="selectMethod('wechat')">
|
||||
<image class="radio" :src="`/static/circle${form.todoMethod === 'wechat' ? 'd' : ''}.svg`" />
|
||||
<view class="m-label">微信</view>
|
||||
</view>
|
||||
|
||||
<view class="block">
|
||||
<view class="block-title">回访结果</view>
|
||||
<view class="textarea-box">
|
||||
<textarea v-model="form.result" class="textarea tall" placeholder="请输入回访结果" maxlength="500" />
|
||||
<view class="counter">{{ (form.result || '').length }}/500</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="row clickable" @click="selectType">
|
||||
<view class="label">回访类型</view>
|
||||
<view class="right">
|
||||
<view class="value" :class="{ muted: !form.eventType }">{{ eventTypeLabel || '请选择回访类型' }}</view>
|
||||
<uni-icons type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="row clickable" @click="selectTeam">
|
||||
<view class="label">所在团队</view>
|
||||
<view class="right">
|
||||
<view class="value" :class="{ muted: !form.teamId }">{{ form.teamName || '请选择团队' }}</view>
|
||||
<uni-icons type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="block">
|
||||
<view class="block-title">回访结果</view>
|
||||
<view class="textarea-box">
|
||||
<textarea v-model="form.result" class="textarea tall" placeholder="请输入回访结果" maxlength="500" />
|
||||
<view class="counter">{{ (form.result || '').length }}/500</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="scroll-spacer" />
|
||||
</scroll-view>
|
||||
|
||||
<view class="footer">
|
||||
<button class="btn plain" @click="cancel">取消</button>
|
||||
@ -91,6 +95,8 @@ import useAccountStore from '@/store/account';
|
||||
import { toast } from '@/utils/widget';
|
||||
import { getTodoEventTypeLabel, getTodoEventTypeOptions } from '@/utils/todo-const';
|
||||
|
||||
const scrollHeight = ref(0);
|
||||
|
||||
const archiveId = ref('');
|
||||
const archiveName = ref('');
|
||||
const archiveMobile = ref('');
|
||||
@ -123,6 +129,13 @@ const mobiles = computed(() => {
|
||||
});
|
||||
|
||||
onLoad((options) => {
|
||||
try {
|
||||
const { windowHeight } = uni.getSystemInfoSync();
|
||||
scrollHeight.value = windowHeight || 0;
|
||||
} catch {
|
||||
scrollHeight.value = 0;
|
||||
}
|
||||
|
||||
archiveId.value = options?.archiveId ? String(options.archiveId) : '';
|
||||
const c = uni.getStorageSync('new-followup-record-customer');
|
||||
if (c && typeof c === 'object') {
|
||||
@ -322,9 +335,12 @@ function closeTypePicker() {
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: #f5f6f8;
|
||||
padding-bottom: calc(76px + env(safe-area-inset-bottom));
|
||||
}
|
||||
.scroll {
|
||||
width: 100%;
|
||||
}
|
||||
.card {
|
||||
background: #fff;
|
||||
@ -333,6 +349,9 @@ function closeTypePicker() {
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.scroll-spacer {
|
||||
height: calc(76px + env(safe-area-inset-bottom));
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -1,79 +1,82 @@
|
||||
<template>
|
||||
<!-- Mobile 来源: ykt-management-mobile/src/pages/customer/new-followup/new-followup.vue(wxapp:仅新增“待办”任务) -->
|
||||
<view class="page">
|
||||
<view class="card">
|
||||
<picker mode="date" :value="form.planExecutionTime" @change="changeDate">
|
||||
<view class="row clickable">
|
||||
<scroll-view scroll-y class="scroll" :style="{ height: scrollHeight + 'px' }">
|
||||
<view class="card">
|
||||
<picker mode="date" :value="form.planExecutionTime" @change="changeDate">
|
||||
<view class="row clickable">
|
||||
<view class="left">
|
||||
<view class="label">回访日期</view>
|
||||
<view class="req">*</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="value" :class="{ muted: !form.planExecutionTime }">{{ form.planExecutionTime || '请选择回访日期' }}</view>
|
||||
<uni-icons type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
|
||||
<view class="row clickable" @click="selectExecutor">
|
||||
<view class="left">
|
||||
<view class="label">回访日期</view>
|
||||
<view class="label">处理人</view>
|
||||
<view class="req">*</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="value" :class="{ muted: !form.planExecutionTime }">{{ form.planExecutionTime || '请选择回访日期' }}</view>
|
||||
<view class="value" :class="{ muted: !form.executorName }">
|
||||
{{ form.executorName ? `${form.executorName}${form.executeTeamName ? `(${form.executeTeamName})` : ''}` : '请选择处理人' }}
|
||||
</view>
|
||||
<uni-icons type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
|
||||
<view class="row clickable" @click="selectExecutor">
|
||||
<view class="left">
|
||||
<view class="label">处理人</view>
|
||||
<view class="req">*</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="value" :class="{ muted: !form.executorName }">
|
||||
{{ form.executorName ? `${form.executorName}${form.executeTeamName ? `(${form.executeTeamName})` : ''}` : '请选择处理人' }}
|
||||
<view class="row clickable" @click="selectType">
|
||||
<view class="left">
|
||||
<view class="label">类型</view>
|
||||
<view class="req">*</view>
|
||||
</view>
|
||||
<uni-icons type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="row clickable" @click="selectType">
|
||||
<view class="left">
|
||||
<view class="label">类型</view>
|
||||
<view class="req">*</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<view class="value" :class="{ muted: !form.eventType }">{{ eventTypeLabel || '请选择类型' }}</view>
|
||||
<uni-icons type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="block">
|
||||
<view class="block-title">目的</view>
|
||||
<view class="textarea-box">
|
||||
<textarea v-model="form.taskContent" class="textarea" placeholder="请输入文字提醒" maxlength="200" />
|
||||
<view class="counter">{{ (form.taskContent || '').length }}/200</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="block">
|
||||
<view class="block-title">向患者发送</view>
|
||||
<view class="textarea-box">
|
||||
<textarea v-model="form.sendContent" class="textarea" placeholder="请输入要发送给患者的内容" maxlength="200" />
|
||||
<view class="counter">{{ (form.sendContent || '').length }}/200</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="row clickable" @click="chooseFile">
|
||||
<view class="left">
|
||||
<view class="label">添加附件</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<uni-icons type="plusempty" size="16" color="#0877F1" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="showFileList.length" class="file-list">
|
||||
<view v-for="(i, index) in showFileList" :key="String(i._k || index)" class="file-item">
|
||||
<view class="file-main">
|
||||
<view v-if="i.typeStr" class="file-type">{{ i.typeStr }}</view>
|
||||
<view class="file-name">{{ i.fileName }}</view>
|
||||
<view class="right">
|
||||
<view class="value" :class="{ muted: !form.eventType }">{{ eventTypeLabel || '请选择类型' }}</view>
|
||||
<uni-icons type="arrowright" size="16" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="block">
|
||||
<view class="block-title">目的</view>
|
||||
<view class="textarea-box">
|
||||
<textarea v-model="form.taskContent" class="textarea" placeholder="请输入文字提醒" maxlength="200" />
|
||||
<view class="counter">{{ (form.taskContent || '').length }}/200</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="block">
|
||||
<view class="block-title">向患者发送</view>
|
||||
<view class="textarea-box">
|
||||
<textarea v-model="form.sendContent" class="textarea" placeholder="请输入要发送给患者的内容" maxlength="200" />
|
||||
<view class="counter">{{ (form.sendContent || '').length }}/200</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="row clickable" @click="chooseFile">
|
||||
<view class="left">
|
||||
<view class="label">添加附件</view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<uni-icons type="plusempty" size="16" color="#0877F1" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="showFileList.length" class="file-list">
|
||||
<view v-for="(i, index) in showFileList" :key="String(i._k || index)" class="file-item">
|
||||
<view class="file-main">
|
||||
<view v-if="i.typeStr" class="file-type">{{ i.typeStr }}</view>
|
||||
<view class="file-name">{{ i.fileName }}</view>
|
||||
</view>
|
||||
<uni-icons type="closeempty" size="18" color="#999" @click="removeFile(index)" />
|
||||
</view>
|
||||
<uni-icons type="closeempty" size="18" color="#999" @click="removeFile(index)" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="scroll-spacer" />
|
||||
</scroll-view>
|
||||
|
||||
<view class="footer">
|
||||
<button class="btn plain" @click="cancel">取消</button>
|
||||
@ -138,8 +141,26 @@ import { chooseAndUploadImage } from '@/utils/file';
|
||||
const archiveId = ref('');
|
||||
const archiveName = ref('');
|
||||
const customerData = ref({});
|
||||
const scrollHeight = ref(0);
|
||||
|
||||
const eventTypeList = getTodoEventTypeOptions();
|
||||
// 新增回访任务:仅展示以下 6 种类型
|
||||
// 诊后回访、术后回访、就诊提醒、用药提醒、未到院回访、其他
|
||||
// 其余类型不删除,仅在该页面隐藏(仍保留在 utils/todo-const.js):
|
||||
// followUpNoDeal(未成交回访)、followUpPostTreatment(治疗后回访)、followUpReminder(复诊提醒)、
|
||||
// serviceSummary(咨询服务)、eventNotification(活动通知)、ContentReminder(宣教发送)、
|
||||
// questionnaire(问卷调查)、followUpComplaint(投诉回访)、followUpActivity(活动回访)
|
||||
const __ALL_TODO_EVENT_TYPE_OPTIONS__ = getTodoEventTypeOptions();
|
||||
const __NEW_FOLLOWUP_EVENT_TYPE_VALUES__ = [
|
||||
'followUp',
|
||||
'followUpPostSurgery',
|
||||
'appointmentReminder',
|
||||
'medicationReminder',
|
||||
'followUpNoShow',
|
||||
'other',
|
||||
];
|
||||
const eventTypeList = __NEW_FOLLOWUP_EVENT_TYPE_VALUES__
|
||||
.map((v) => __ALL_TODO_EVENT_TYPE_OPTIONS__.find((i) => i.value === v))
|
||||
.filter(Boolean);
|
||||
|
||||
const accountStore = useAccountStore();
|
||||
const { account, doctorInfo } = storeToRefs(accountStore);
|
||||
@ -163,6 +184,7 @@ const eventTypeLabel = computed(() => getTodoEventTypeLabel(form.eventType));
|
||||
|
||||
onLoad((options) => {
|
||||
resetForm();
|
||||
scrollHeight.value = Number(uni.getSystemInfoSync()?.windowHeight || 0) || 0;
|
||||
archiveId.value = options?.archiveId ? String(options.archiveId) : '';
|
||||
const c = uni.getStorageSync('new-followup-customer');
|
||||
if (c && typeof c === 'object') {
|
||||
@ -319,7 +341,6 @@ async function save() {
|
||||
if (!form.executeTeamId) return uni.showToast({ title: '请选择处理人', icon: 'none' });
|
||||
if (!form.executorUserId) return uni.showToast({ title: '请选择处理人', icon: 'none' });
|
||||
if (!form.eventType) return uni.showToast({ title: '请选择类型', icon: 'none' });
|
||||
if (!String(form.taskContent || '').trim()) return uni.showToast({ title: '请输入目的', icon: 'none' });
|
||||
|
||||
await ensureDoctor();
|
||||
const corpId = getCorpId();
|
||||
@ -467,9 +488,13 @@ function chooseQuestionnaire() {
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
background: #f5f6f8;
|
||||
padding-bottom: calc(76px + env(safe-area-inset-bottom));
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.scroll-spacer {
|
||||
height: calc(76px + env(safe-area-inset-bottom));
|
||||
}
|
||||
.card {
|
||||
background: #fff;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<view class="page">
|
||||
<!-- Mobile 来源: ykt-management-mobile/src/pages/customer/service-record-detail/service-record-detail.vue -->
|
||||
<view v-if="!recordId" class="body">
|
||||
<scroll-view scroll-y class="scroll">
|
||||
<scroll-view scroll-y class="scroll" :style="{ height: scrollHeight + 'px' }">
|
||||
<view class="card">
|
||||
<view class="section-title">执行日期</view>
|
||||
<picker mode="date" @change="pickDate" :disabled="true">
|
||||
@ -93,6 +93,8 @@ import useAccountStore from '@/store/account';
|
||||
import { toast } from '@/utils/widget';
|
||||
import { getServiceTypeOptions } from '@/utils/service-type-const';
|
||||
|
||||
const scrollHeight = ref(0);
|
||||
|
||||
const archiveId = ref('');
|
||||
const mode = ref('add');
|
||||
const recordId = ref('');
|
||||
@ -148,6 +150,13 @@ function getCurrentTeam() {
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
try {
|
||||
const { windowHeight } = uni.getSystemInfoSync();
|
||||
scrollHeight.value = windowHeight || 0;
|
||||
} catch {
|
||||
scrollHeight.value = 0;
|
||||
}
|
||||
|
||||
archiveId.value = options?.archiveId ? String(options.archiveId) : '';
|
||||
recordId.value = options?.id ? String(options.id) : '';
|
||||
|
||||
@ -295,9 +304,10 @@ async function submit(executionTime) {
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: #f5f6f8;
|
||||
padding-bottom: calc(76px + env(safe-area-inset-bottom));
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.body {
|
||||
height: 100vh;
|
||||
@ -305,7 +315,7 @@ async function submit(executionTime) {
|
||||
flex-direction: column;
|
||||
}
|
||||
.scroll {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
.card {
|
||||
background: #fff;
|
||||
|
||||
@ -1,45 +1,49 @@
|
||||
<template>
|
||||
<!-- 详情页参考截图:顶部蓝条显示创建信息,支持编辑/删除;黄底提示不渲染 -->
|
||||
<view class="page">
|
||||
<view class="topbar">
|
||||
<view class="topbar-text">{{ topText }}</view>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
<view class="section">
|
||||
<view class="row">
|
||||
<view class="label">病历类型</view>
|
||||
<view class="value">{{ typeLabel }}</view>
|
||||
</view>
|
||||
<view class="row">
|
||||
<view class="label">{{ visitDateLabel }}</view>
|
||||
<view class="value">{{ visitDate || '--' }}</view>
|
||||
</view>
|
||||
<view v-if="showDiagnosisRow" class="row">
|
||||
<view class="label">诊断</view>
|
||||
<view class="value">{{ diagnosisText }}</view>
|
||||
</view>
|
||||
<view v-if="templateType === 'inhospital' && record.surgeryName" class="row">
|
||||
<view class="label">手术名称</view>
|
||||
<view class="value">{{ record.surgeryName }}</view>
|
||||
</view>
|
||||
<scroll-view scroll-y class="scroll" :style="{ height: scrollHeight + 'px' }">
|
||||
<view class="topbar">
|
||||
<view class="topbar-text">{{ topText }}</view>
|
||||
</view>
|
||||
|
||||
<view v-for="(s, idx) in sections" :key="idx" class="section">
|
||||
<view class="h2">{{ s.title }}</view>
|
||||
<view class="p">{{ s.value }}</view>
|
||||
</view>
|
||||
|
||||
<view v-if="showFilesSection" class="section">
|
||||
<view class="h2">文件上传</view>
|
||||
<view v-if="files.length" class="files">
|
||||
<view v-for="(f, idx) in files" :key="idx" class="file" @click="preview(idx)">
|
||||
<image class="thumb" :src="f.url" mode="aspectFill" />
|
||||
<view class="content">
|
||||
<view class="section">
|
||||
<view class="row">
|
||||
<view class="label">病历类型</view>
|
||||
<view class="value">{{ typeLabel }}</view>
|
||||
</view>
|
||||
<view class="row">
|
||||
<view class="label">{{ visitDateLabel }}</view>
|
||||
<view class="value">{{ visitDate || '--' }}</view>
|
||||
</view>
|
||||
<view v-if="showDiagnosisRow" class="row">
|
||||
<view class="label">诊断</view>
|
||||
<view class="value">{{ diagnosisText }}</view>
|
||||
</view>
|
||||
<view v-if="templateType === 'inhospital' && record.surgeryName" class="row">
|
||||
<view class="label">手术名称</view>
|
||||
<view class="value">{{ record.surgeryName }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="files-empty">暂无附件</view>
|
||||
|
||||
<view v-for="(s, idx) in sections" :key="idx" class="section">
|
||||
<view class="h2">{{ s.title }}</view>
|
||||
<view class="p">{{ s.value }}</view>
|
||||
</view>
|
||||
|
||||
<view v-if="showFilesSection" class="section">
|
||||
<view class="h2">文件上传</view>
|
||||
<view v-if="files.length" class="files">
|
||||
<view v-for="(f, idx) in files" :key="idx" class="file" @click="preview(idx)">
|
||||
<image class="thumb" :src="f.url" mode="aspectFill" />
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="files-empty">暂无附件</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="scroll-spacer" />
|
||||
</scroll-view>
|
||||
|
||||
<view class="footer">
|
||||
<button class="btn danger" @click="remove">删除</button>
|
||||
@ -59,6 +63,8 @@ import { normalizeVisitRecordFormData } from './utils/visit-record';
|
||||
import { normalizeTemplate, unwrapTemplateResponse } from './utils/template';
|
||||
import { normalizeFileUrl } from '@/utils/file';
|
||||
|
||||
const scrollHeight = ref(0);
|
||||
|
||||
const archiveId = ref('');
|
||||
const id = ref('');
|
||||
const medicalType = ref('');
|
||||
@ -68,6 +74,9 @@ const temp = ref(null);
|
||||
const needReload = ref(false);
|
||||
let recordChangedHandler = null;
|
||||
|
||||
const userNameMap = ref({});
|
||||
const loadedMembersTeamId = ref('');
|
||||
|
||||
const files = computed(() => {
|
||||
const arr = record.value?.files;
|
||||
return Array.isArray(arr)
|
||||
@ -151,6 +160,73 @@ function getCorpId() {
|
||||
return team?.corpId ? String(team.corpId) : '';
|
||||
}
|
||||
|
||||
function getTeamId() {
|
||||
const team = uni.getStorageSync('ykt_case_current_team') || {};
|
||||
return team?.teamId ? String(team.teamId) : '';
|
||||
}
|
||||
|
||||
function normalizeUserId(value) {
|
||||
if (value === null || value === undefined) return '';
|
||||
if (typeof value === 'object') {
|
||||
const obj = value;
|
||||
const picked =
|
||||
obj.userid ||
|
||||
obj.userId ||
|
||||
obj.userID ||
|
||||
obj.corpUserId ||
|
||||
obj.corpUserID ||
|
||||
obj._id ||
|
||||
obj.id ||
|
||||
'';
|
||||
return String(picked || '').trim();
|
||||
}
|
||||
return String(value || '').trim();
|
||||
}
|
||||
|
||||
function isLikelyUserId(value) {
|
||||
const id = normalizeUserId(value);
|
||||
if (!id) return false;
|
||||
if (/[-—]{1,2}/.test(id) && ['-', '—', '--'].includes(id.trim())) return false;
|
||||
if (/\s/.test(id)) return false;
|
||||
if (/[\u4e00-\u9fa5]/.test(id)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
async function loadTeamMembers() {
|
||||
const corpId = getCorpId();
|
||||
const teamId = getTeamId();
|
||||
if (!corpId || !teamId) return;
|
||||
if (loadedMembersTeamId.value === teamId && Object.keys(userNameMap.value || {}).length > 0) return;
|
||||
|
||||
try {
|
||||
const res = await api('getTeamData', { corpId, teamId });
|
||||
if (!res?.success) return;
|
||||
const t = res?.data && typeof res.data === 'object' ? res.data : {};
|
||||
const members = Array.isArray(t.memberList) ? t.memberList : [];
|
||||
const nextMap = {};
|
||||
members.forEach((m) => {
|
||||
if (!m || typeof m !== 'object') return;
|
||||
const display = String(m?.anotherName || m?.name || m?.userid || m?.userId || m?.corpUserId || '').trim();
|
||||
const keys = [m?.userid, m?.userId, m?.corpUserId].map(normalizeUserId).filter(Boolean);
|
||||
keys.forEach((k) => {
|
||||
nextMap[k] = display || nextMap[k] || k;
|
||||
nextMap[String(k).toLowerCase()] = display || nextMap[String(k).toLowerCase()] || k;
|
||||
});
|
||||
});
|
||||
userNameMap.value = nextMap;
|
||||
loadedMembersTeamId.value = teamId;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function resolveUserName(userId) {
|
||||
const id = normalizeUserId(userId);
|
||||
if (!id) return '';
|
||||
const map = userNameMap.value || {};
|
||||
return String(map[id] || map[id.toLowerCase()] || id);
|
||||
}
|
||||
|
||||
function parseAnyTimeMs(v) {
|
||||
if (v === null || v === undefined) return 0;
|
||||
if (typeof v === 'number') {
|
||||
@ -288,10 +364,26 @@ async function loadTemplate(t) {
|
||||
|
||||
const topText = computed(() => {
|
||||
const time = record.value?.createTime ? dayjs(record.value.createTime).format('YYYY-MM-DD HH:mm') : '';
|
||||
const rawName = record.value?.creatorName ? String(record.value.creatorName) : '';
|
||||
const cleanName = ['-', '—', '--'].includes(rawName.trim()) ? '' : rawName.trim();
|
||||
const byCustomer = record.value?.ignore === 'checkIn';
|
||||
const suffix = byCustomer ? '患者自建' : cleanName ? `${cleanName}代建` : record.value?.creator ? '员工代建' : '';
|
||||
if (byCustomer) return `${time || '--'} 患者自建`;
|
||||
|
||||
const nameFromApiRaw = record.value?.creatorName ? String(record.value.creatorName).trim() : '';
|
||||
const nameFromApi = ['-', '—', '--'].includes(nameFromApiRaw) ? '' : nameFromApiRaw;
|
||||
if (nameFromApi && !isLikelyUserId(nameFromApi)) {
|
||||
return `${time || '--'} ${nameFromApi}代建`;
|
||||
}
|
||||
|
||||
const creatorId = normalizeUserId(
|
||||
record.value?.creator ||
|
||||
record.value?.creatorUserId ||
|
||||
record.value?.createUserId ||
|
||||
record.value?.executor ||
|
||||
record.value?.executorUserId ||
|
||||
''
|
||||
);
|
||||
const fallbackId = !creatorId && nameFromApi && isLikelyUserId(nameFromApi) ? nameFromApi : '';
|
||||
const display = (creatorId || fallbackId) ? resolveUserName(creatorId || fallbackId) : '';
|
||||
const suffix = display ? `${display}代建` : '';
|
||||
return suffix ? `${time || '--'} ${suffix}` : `${time || '--'}`;
|
||||
});
|
||||
|
||||
@ -331,6 +423,13 @@ async function fetchRecord({ silent = false } = {}) {
|
||||
}
|
||||
|
||||
onLoad(async (opt) => {
|
||||
try {
|
||||
const { windowHeight } = uni.getSystemInfoSync();
|
||||
scrollHeight.value = windowHeight || 0;
|
||||
} catch {
|
||||
scrollHeight.value = 0;
|
||||
}
|
||||
|
||||
archiveId.value = opt?.archiveId ? String(opt.archiveId) : '';
|
||||
id.value = opt?.id ? String(opt.id) : '';
|
||||
medicalType.value = opt?.type ? String(opt.type) : '';
|
||||
@ -339,6 +438,10 @@ onLoad(async (opt) => {
|
||||
setTimeout(() => uni.navigateBack(), 300);
|
||||
return;
|
||||
}
|
||||
|
||||
// 异步加载团队成员映射,用于展示“xx代建”的真实姓名
|
||||
void loadTeamMembers();
|
||||
|
||||
const ok = await fetchRecord();
|
||||
if (!ok) {
|
||||
toast('记录不存在');
|
||||
@ -408,9 +511,12 @@ function remove() {
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
padding-bottom: calc(152rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
.scroll {
|
||||
width: 100%;
|
||||
}
|
||||
.topbar {
|
||||
background: #5d6df0;
|
||||
@ -454,6 +560,8 @@ function remove() {
|
||||
color: #111827;
|
||||
line-height: 40rpx;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.files {
|
||||
display: flex;
|
||||
@ -475,6 +583,9 @@ function remove() {
|
||||
color: #9aa0a6;
|
||||
padding: 16rpx 0;
|
||||
}
|
||||
.scroll-spacer {
|
||||
height: calc(152rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
.footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user