Compare commits

..

No commits in common. "fbd51dc0d7653a5193ee0d232f699c4ba2a542fb" and "efe1b2994e3ef218f7bd10a9c4c058e1e2db2277" have entirely different histories.

5 changed files with 158 additions and 332 deletions

View File

@ -1,6 +1,5 @@
<template>
<view class="page">
<scroll-view scroll-y class="scroll" :style="{ height: scrollHeight + 'px' }">
<CustomerProfileTab
:data="archive"
:baseItems="baseItems"
@ -8,7 +7,6 @@
:floatingBottom="16"
@save="savePatch"
/>
</scroll-view>
</view>
</template>
@ -46,7 +44,6 @@ const archive = ref({
const baseItems = ref([]);
const internalItems = ref([]);
const scrollHeight = ref(0);
const accountStore = useAccountStore();
const { account, doctorInfo } = storeToRefs(accountStore);
@ -339,7 +336,6 @@ 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 () => {
@ -355,12 +351,7 @@ onShow(() => {
<style scoped>
.page {
height: 100vh;
overflow: hidden;
min-height: 100vh;
background: #f5f6f8;
}
.scroll {
height: 100vh;
}
</style>

View File

@ -1,7 +1,6 @@
<template>
<!-- Mobile 来源: ykt-management-mobile/src/pages/customer/new-followup-record/new-followup-record.vue简化移植去除 pinia/接口 -->
<view class="page">
<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">
@ -54,9 +53,6 @@
</view>
</view>
<view class="scroll-spacer" />
</scroll-view>
<view class="footer">
<button class="btn plain" @click="cancel">取消</button>
<button class="btn primary" @click="save">保存</button>
@ -95,8 +91,6 @@ 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('');
@ -129,13 +123,6 @@ 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') {
@ -335,12 +322,9 @@ function closeTypePicker() {
<style scoped>
.page {
height: 100vh;
overflow: hidden;
min-height: 100vh;
background: #f5f6f8;
}
.scroll {
width: 100%;
padding-bottom: calc(76px + env(safe-area-inset-bottom));
}
.card {
background: #fff;
@ -349,9 +333,6 @@ 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;

View File

@ -1,7 +1,6 @@
<template>
<!-- Mobile 来源: ykt-management-mobile/src/pages/customer/new-followup/new-followup.vuewxapp仅新增待办任务 -->
<view class="page">
<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">
@ -75,8 +74,6 @@
</view>
</view>
</view>
<view class="scroll-spacer" />
</scroll-view>
<view class="footer">
<button class="btn plain" @click="cancel">取消</button>
@ -141,26 +138,8 @@ import { chooseAndUploadImage } from '@/utils/file';
const archiveId = ref('');
const archiveName = ref('');
const customerData = ref({});
const scrollHeight = ref(0);
// 访 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 eventTypeList = getTodoEventTypeOptions();
const accountStore = useAccountStore();
const { account, doctorInfo } = storeToRefs(accountStore);
@ -184,7 +163,6 @@ 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') {
@ -341,6 +319,7 @@ 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();
@ -488,13 +467,9 @@ function chooseQuestionnaire() {
<style scoped>
.page {
height: 100vh;
min-height: 100vh;
background: #f5f6f8;
overflow: hidden;
}
.scroll-spacer {
height: calc(76px + env(safe-area-inset-bottom));
padding-bottom: calc(76px + env(safe-area-inset-bottom));
}
.card {
background: #fff;

View File

@ -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" :style="{ height: scrollHeight + 'px' }">
<scroll-view scroll-y class="scroll">
<view class="card">
<view class="section-title">执行日期</view>
<picker mode="date" @change="pickDate" :disabled="true">
@ -93,8 +93,6 @@ 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('');
@ -150,13 +148,6 @@ 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) : '';
@ -304,10 +295,9 @@ async function submit(executionTime) {
<style scoped>
.page {
height: 100vh;
overflow: hidden;
min-height: 100vh;
background: #f5f6f8;
padding-bottom: 0;
padding-bottom: calc(76px + env(safe-area-inset-bottom));
}
.body {
height: 100vh;
@ -315,7 +305,7 @@ async function submit(executionTime) {
flex-direction: column;
}
.scroll {
width: 100%;
flex: 1;
}
.card {
background: #fff;

View File

@ -1,7 +1,6 @@
<template>
<!-- 详情页参考截图顶部蓝条显示创建信息支持编辑/删除黄底提示不渲染 -->
<view class="page">
<scroll-view scroll-y class="scroll" :style="{ height: scrollHeight + 'px' }">
<view class="topbar">
<view class="topbar-text">{{ topText }}</view>
</view>
@ -42,9 +41,6 @@
</view>
</view>
<view class="scroll-spacer" />
</scroll-view>
<view class="footer">
<button class="btn danger" @click="remove">删除</button>
<button class="btn primary" @click="edit">编辑</button>
@ -63,8 +59,6 @@ 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('');
@ -74,9 +68,6 @@ 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)
@ -160,73 +151,6 @@ 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') {
@ -364,26 +288,10 @@ 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';
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}代建` : '';
const suffix = byCustomer ? '患者自建' : cleanName ? `${cleanName}代建` : record.value?.creator ? '员工代建' : '';
return suffix ? `${time || '--'} ${suffix}` : `${time || '--'}`;
});
@ -423,13 +331,6 @@ 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) : '';
@ -438,10 +339,6 @@ onLoad(async (opt) => {
setTimeout(() => uni.navigateBack(), 300);
return;
}
// xx
void loadTeamMembers();
const ok = await fetchRecord();
if (!ok) {
toast('记录不存在');
@ -511,12 +408,9 @@ function remove() {
<style scoped>
.page {
height: 100vh;
overflow: hidden;
min-height: 100vh;
background: #fff;
}
.scroll {
width: 100%;
padding-bottom: calc(152rpx + env(safe-area-inset-bottom));
}
.topbar {
background: #5d6df0;
@ -560,8 +454,6 @@ function remove() {
color: #111827;
line-height: 40rpx;
white-space: pre-wrap;
word-break: break-all;
word-wrap: break-word;
}
.files {
display: flex;
@ -583,9 +475,6 @@ function remove() {
color: #9aa0a6;
padding: 16rpx 0;
}
.scroll-spacer {
height: calc(152rpx + env(safe-area-inset-bottom));
}
.footer {
position: fixed;
left: 0;