fix:修复已知问题
This commit is contained in:
parent
755608e569
commit
e37c2b1089
@ -2,18 +2,12 @@
|
|||||||
<view class="page">
|
<view class="page">
|
||||||
<view class="card">
|
<view class="card">
|
||||||
<view class="header">
|
<view class="header">
|
||||||
<view class="avatar">
|
|
||||||
<image v-if="archive.avatar" class="avatar-img" :src="archive.avatar" mode="aspectFill" />
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="header-main">
|
<view class="header-main">
|
||||||
<view class="name-row">
|
<view class="name-row">
|
||||||
<text class="name">{{ archive.name || '-' }}</text>
|
<text class="name">{{ archive.name || '-' }}</text>
|
||||||
<text v-if="sexOrAge" class="meta">{{ sexOrAge }}</text>
|
<text v-if="sexOrAge" class="meta">{{ sexOrAge }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="archive.mobile" class="sub-line">{{ archive.mobile }}</view>
|
|
||||||
|
|
||||||
<view v-if="idRows.length" class="id-rows">
|
<view v-if="idRows.length" class="id-rows">
|
||||||
<view v-for="row in idRows" :key="row.label" class="id-row">
|
<view v-for="row in idRows" :key="row.label" class="id-row">
|
||||||
<text class="id-label">{{ row.label }}:</text>
|
<text class="id-label">{{ row.label }}:</text>
|
||||||
@ -296,7 +290,7 @@ function normalizeArchiveFromApi(raw) {
|
|||||||
name: r.name || '',
|
name: r.name || '',
|
||||||
sex: r.sex || r.gender || '',
|
sex: r.sex || r.gender || '',
|
||||||
age: r.age ?? '',
|
age: r.age ?? '',
|
||||||
avatar: r.avatar || '',
|
avatar: r.avatar || r.avatarUrl || r.headImgUrl || r.headimgurl || r.headImageUrl || r.profilePhoto || r.photoUrl || r.photo || '',
|
||||||
mobile: r.mobile || r.phone1 || r.phone || '',
|
mobile: r.mobile || r.phone1 || r.phone || '',
|
||||||
outpatientNo: r.outpatientNo || '',
|
outpatientNo: r.outpatientNo || '',
|
||||||
inpatientNo: r.inpatientNo || '',
|
inpatientNo: r.inpatientNo || '',
|
||||||
@ -778,25 +772,10 @@ const saveAddGroup = async () => {
|
|||||||
border-bottom: 2rpx solid #f2f2f2;
|
border-bottom: 2rpx solid #f2f2f2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
|
||||||
width: 112rpx;
|
|
||||||
height: 112rpx;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
border: 2rpx solid #e8e8e8;
|
|
||||||
background: #fafafa;
|
|
||||||
overflow: hidden;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar-img {
|
|
||||||
width: 112rpx;
|
|
||||||
height: 112rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-main {
|
.header-main {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding: 0 20rpx;
|
padding: 0 20rpx 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name-row {
|
.name-row {
|
||||||
|
|||||||
@ -40,13 +40,6 @@
|
|||||||
<image class="pen" src="/static/icons/icon-pen.svg" />
|
<image class="pen" src="/static/icons/icon-pen.svg" />
|
||||||
</view>
|
</view>
|
||||||
<view class="rows">
|
<view class="rows">
|
||||||
<view class="row" @click="openTransferRecord">
|
|
||||||
<view class="label">院内来源</view>
|
|
||||||
<view class="val link">
|
|
||||||
{{ latestTransferRecord?.executeTeamName || '点击查看' }}
|
|
||||||
<uni-icons type="arrowright" size="14" color="#0877F1" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<form-template
|
<form-template
|
||||||
v-if="editing && effectiveInternalItems.length"
|
v-if="editing && effectiveInternalItems.length"
|
||||||
ref="internalFormRef"
|
ref="internalFormRef"
|
||||||
@ -148,7 +141,15 @@ const fallbackInternalItems = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const effectiveBaseItems = computed(() => (Array.isArray(props.baseItems) && props.baseItems.length ? props.baseItems : fallbackBaseItems));
|
const effectiveBaseItems = computed(() => (Array.isArray(props.baseItems) && props.baseItems.length ? props.baseItems : fallbackBaseItems));
|
||||||
const effectiveInternalItems = computed(() => (Array.isArray(props.internalItems) && props.internalItems.length ? props.internalItems : fallbackInternalItems));
|
function isInHospitalSourceItem(item) {
|
||||||
|
const title = String(item?.title || '');
|
||||||
|
const name = String(item?.name || '');
|
||||||
|
return title === 'inHospitalSource' || title === 'hospitalSource' || name.includes('院内来源');
|
||||||
|
}
|
||||||
|
const effectiveInternalItems = computed(() => {
|
||||||
|
const raw = Array.isArray(props.internalItems) && props.internalItems.length ? props.internalItems : fallbackInternalItems;
|
||||||
|
return raw.filter((i) => i && !isInHospitalSourceItem(i));
|
||||||
|
});
|
||||||
|
|
||||||
const filterRule = {
|
const filterRule = {
|
||||||
reference(formModel) {
|
reference(formModel) {
|
||||||
|
|||||||
@ -54,11 +54,11 @@
|
|||||||
mode="selector"
|
mode="selector"
|
||||||
:range="selectableTemplates"
|
:range="selectableTemplates"
|
||||||
range-key="name"
|
range-key="name"
|
||||||
:disabled="selectableTemplates.length === 0"
|
:disabled="fabPickerDisabled"
|
||||||
:style="{ bottom: `${floatingBottom}px` }"
|
:style="{ bottom: `${floatingBottom}px` }"
|
||||||
@change="pickAddType"
|
@change="pickAddType"
|
||||||
>
|
>
|
||||||
<view class="fab" :class="{ 'fab--disabled': selectableTemplates.length === 0 }">
|
<view class="fab" :class="{ 'fab--disabled': selectableTemplates.length === 0 }" @tap="onFabTap">
|
||||||
<uni-icons type="plusempty" size="24" color="#fff" />
|
<uni-icons type="plusempty" size="24" color="#fff" />
|
||||||
</view>
|
</view>
|
||||||
</picker>
|
</picker>
|
||||||
@ -81,6 +81,8 @@ const props = defineProps({
|
|||||||
const FALLBACK_TEMPLATE_TYPES = ['outpatient', 'inhospital', 'preConsultation', 'physicalExaminationTemplate'];
|
const FALLBACK_TEMPLATE_TYPES = ['outpatient', 'inhospital', 'preConsultation', 'physicalExaminationTemplate'];
|
||||||
const templates = ref([]);
|
const templates = ref([]);
|
||||||
const selectableTemplates = computed(() => templates.value.filter((i) => i && i.templateType && typeof i.name === 'string' && i.name.trim()));
|
const selectableTemplates = computed(() => templates.value.filter((i) => i && i.templateType && typeof i.name === 'string' && i.name.trim()));
|
||||||
|
const useActionSheet = computed(() => selectableTemplates.value.length > 0 && selectableTemplates.value.length <= 6);
|
||||||
|
const fabPickerDisabled = computed(() => selectableTemplates.value.length === 0 || useActionSheet.value);
|
||||||
const templateMap = computed(() => templates.value.reduce((m, t) => {
|
const templateMap = computed(() => templates.value.reduce((m, t) => {
|
||||||
if (t?.templateType) m[String(t.templateType)] = t;
|
if (t?.templateType) m[String(t.templateType)] = t;
|
||||||
return m;
|
return m;
|
||||||
@ -393,16 +395,58 @@ function previewFiles(r, idx) {
|
|||||||
uni.previewImage({ urls, current: urls[idx] });
|
uni.previewImage({ urls, current: urls[idx] });
|
||||||
}
|
}
|
||||||
|
|
||||||
function pickAddType(e) {
|
function goAdd(t) {
|
||||||
if (!props.archiveId) return toast('缺少档案信息');
|
|
||||||
const idx = Number(e?.detail?.value ?? -1);
|
|
||||||
const t = selectableTemplates.value[idx];
|
|
||||||
if (!t?.templateType) return;
|
if (!t?.templateType) return;
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/case/visit-record-detail?archiveId=${encodeURIComponent(props.archiveId)}&type=${encodeURIComponent(t.templateType)}&name=${encodeURIComponent(props.data?.name || '')}`,
|
url: `/pages/case/visit-record-detail?archiveId=${encodeURIComponent(props.archiveId)}&type=${encodeURIComponent(t.templateType)}&name=${encodeURIComponent(props.data?.name || '')}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pickAddType(e) {
|
||||||
|
if (!props.archiveId) return toast('缺少档案信息');
|
||||||
|
const idx = Number(e?.detail?.value ?? -1);
|
||||||
|
const t = selectableTemplates.value[idx];
|
||||||
|
if (!t) return;
|
||||||
|
goAdd(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showAddActionSheet() {
|
||||||
|
if (!props.archiveId) return toast('缺少档案信息');
|
||||||
|
const list = selectableTemplates.value;
|
||||||
|
if (!list.length) return toast('暂无可用病历模板');
|
||||||
|
uni.showActionSheet({
|
||||||
|
itemList: list.map((i) => i.name),
|
||||||
|
success: ({ tapIndex }) => {
|
||||||
|
const t = list[tapIndex];
|
||||||
|
if (!t) return;
|
||||||
|
goAdd(t);
|
||||||
|
},
|
||||||
|
fail: (e) => {
|
||||||
|
// 用户取消无需提示;其他错误忽略
|
||||||
|
const errMsg = String(e?.errMsg || '');
|
||||||
|
if (errMsg && errMsg.includes('cancel')) return;
|
||||||
|
if (errMsg) console.warn('[health-profile-tab] showActionSheet fail:', errMsg);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onFabTap() {
|
||||||
|
if (!props.archiveId) return toast('缺少档案信息');
|
||||||
|
|
||||||
|
// 模板可能尚未加载:先拉一次
|
||||||
|
if (!templates.value.length) {
|
||||||
|
loading('加载模板...');
|
||||||
|
try {
|
||||||
|
await loadVisitTemplates();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// <=6:用 actionSheet;>6:由 picker 自己弹(这里不做额外处理)
|
||||||
|
if (useActionSheet.value) showAddActionSheet();
|
||||||
|
}
|
||||||
|
|
||||||
function edit(record) {
|
function edit(record) {
|
||||||
const type = String(record?.medicalType || record?.templateType || '') || '';
|
const type = String(record?.medicalType || record?.templateType || '') || '';
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
@ -411,6 +455,8 @@ function edit(record) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
// 提前加载模板,避免首次点“+”时 picker 无法立即弹出
|
||||||
|
loadVisitTemplates();
|
||||||
// archiveId 可能后置赋值:这里保留一次兜底刷新,主逻辑交给 watch
|
// archiveId 可能后置赋值:这里保留一次兜底刷新,主逻辑交给 watch
|
||||||
refreshList();
|
refreshList();
|
||||||
uni.$on('archive-detail:visit-record-changed', refreshList);
|
uni.$on('archive-detail:visit-record-changed', refreshList);
|
||||||
|
|||||||
@ -40,8 +40,8 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="meta">
|
<view class="meta">
|
||||||
<view class="tag">{{ i.typeStr }}</view>
|
<view class="tag">{{ i.typeStr }}</view>
|
||||||
<view class="meta-text">{{ i.executorName }}</view>
|
<view class="meta-text">{{ executorText(i) }}</view>
|
||||||
<view class="meta-text truncate">{{ i.executeTeamName }}</view>
|
<view class="meta-text truncate">{{ executeTeamText(i) }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="body">
|
<view class="body">
|
||||||
<view class="content" :class="{ clamp: !expandMap[i._id] }">
|
<view class="content" :class="{ clamp: !expandMap[i._id] }">
|
||||||
@ -79,6 +79,31 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</uni-popup>
|
</uni-popup>
|
||||||
|
|
||||||
|
<!-- 编辑服务内容 -->
|
||||||
|
<uni-popup ref="editPopupRef" type="bottom" :mask-click="true" @maskClick="closeEditPopup">
|
||||||
|
<view class="edit-sheet">
|
||||||
|
<view class="edit-header">
|
||||||
|
<view class="edit-header-left" />
|
||||||
|
<view class="edit-title">修改服务内容</view>
|
||||||
|
<view class="edit-close" @click="closeEditPopup">
|
||||||
|
<uni-icons type="closeempty" size="18" color="#333" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="edit-body">
|
||||||
|
<textarea
|
||||||
|
v-model="editContent"
|
||||||
|
class="edit-textarea"
|
||||||
|
placeholder="请输入服务内容"
|
||||||
|
:maxlength="1000"
|
||||||
|
/>
|
||||||
|
<view class="counter">{{ (editContent || '').length }}/1000</view>
|
||||||
|
</view>
|
||||||
|
<view class="edit-footer">
|
||||||
|
<button class="btn primary" @click="saveEdit">保存</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -130,7 +155,8 @@ async function ensureDoctor() {
|
|||||||
function getUserId() {
|
function getUserId() {
|
||||||
const d = doctorInfo.value || {};
|
const d = doctorInfo.value || {};
|
||||||
const a = account.value || {};
|
const a = account.value || {};
|
||||||
return String(d.userid || d.userId || d.corpUserId || a.userid || a.userId || '') || '';
|
const t = uni.getStorageSync('ykt_case_current_team') || {};
|
||||||
|
return String(d.userid || d.userId || d.corpUserId || a.userid || a.userId || t.userId || t.userid || t.corpUserId || '') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCorpId() {
|
function getCorpId() {
|
||||||
@ -145,6 +171,58 @@ function getCurrentTeamId() {
|
|||||||
return String(t.teamId || '') || '';
|
return String(t.teamId || '') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeName(v) {
|
||||||
|
const s = v === 0 ? '0' : v ? String(v) : '';
|
||||||
|
const trimmed = s.trim();
|
||||||
|
if (!trimmed) return '';
|
||||||
|
if (['-', '—', '--'].includes(trimmed)) return '';
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExecutorId(r) {
|
||||||
|
const row = r && typeof r === 'object' ? r : {};
|
||||||
|
return String(
|
||||||
|
row.executorUserId ||
|
||||||
|
row.executorId ||
|
||||||
|
row.executor ||
|
||||||
|
row.creatorUserId ||
|
||||||
|
row.creator ||
|
||||||
|
row.updateUserId ||
|
||||||
|
''
|
||||||
|
) || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function executorText(r) {
|
||||||
|
const row = r && typeof r === 'object' ? r : {};
|
||||||
|
const fromRow = normalizeName(row.executorName || row.executorUserName || row.creatorName || row.updateUserName || '');
|
||||||
|
if (fromRow) return fromRow;
|
||||||
|
const uid = getExecutorId(row);
|
||||||
|
const mapped = normalizeName(resolveUserName(uid));
|
||||||
|
return mapped || (uid ? uid : '--');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExecuteTeamId(r) {
|
||||||
|
const row = r && typeof r === 'object' ? r : {};
|
||||||
|
return String(row.executeTeamId || row.teamId || row.teamID || '') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveTeamName(teamId) {
|
||||||
|
const tid = String(teamId || '') || '';
|
||||||
|
if (!tid) return '';
|
||||||
|
const list = teamList.value || [];
|
||||||
|
const hit = list.find((i) => i && i.value === tid);
|
||||||
|
return hit?.label ? String(hit.label) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeTeamText(r) {
|
||||||
|
const row = r && typeof r === 'object' ? r : {};
|
||||||
|
const fromRow = normalizeName(row.executeTeamName || row.teamName || '');
|
||||||
|
if (fromRow) return fromRow;
|
||||||
|
const tid = getExecuteTeamId(row) || getCurrentTeamId();
|
||||||
|
const mapped = normalizeName(resolveTeamName(tid));
|
||||||
|
return mapped || (tid ? tid : '--');
|
||||||
|
}
|
||||||
|
|
||||||
function resolveUserName(userId) {
|
function resolveUserName(userId) {
|
||||||
const id = String(userId || '');
|
const id = String(userId || '');
|
||||||
if (!id) return '';
|
if (!id) return '';
|
||||||
@ -181,9 +259,12 @@ function displayTaskContent(r) {
|
|||||||
return formatTaskContent(String(r?.taskContent || ''));
|
return formatTaskContent(String(r?.taskContent || ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadedTeamMemberIds = new Set();
|
||||||
async function loadTeamMembers(teamId) {
|
async function loadTeamMembers(teamId) {
|
||||||
const tid = String(teamId || '') || '';
|
const tid = String(teamId || '') || '';
|
||||||
if (!tid) return;
|
if (!tid) return;
|
||||||
|
if (loadedTeamMemberIds.has(tid)) return;
|
||||||
|
loadedTeamMemberIds.add(tid);
|
||||||
await ensureDoctor();
|
await ensureDoctor();
|
||||||
const corpId = getCorpId();
|
const corpId = getCorpId();
|
||||||
if (!corpId) return;
|
if (!corpId) return;
|
||||||
@ -216,6 +297,8 @@ function mapRow(i) {
|
|||||||
return {
|
return {
|
||||||
...i,
|
...i,
|
||||||
_id: String(i?._id || i?.id || ''),
|
_id: String(i?._id || i?.id || ''),
|
||||||
|
executorUserId: getExecutorId(i),
|
||||||
|
executeTeamId: getExecuteTeamId(i),
|
||||||
hasFile,
|
hasFile,
|
||||||
fileType,
|
fileType,
|
||||||
timeStr: i.executionTime ? dayjs(i.executionTime).format('YYYY-MM-DD HH:mm') : '--',
|
timeStr: i.executionTime ? dayjs(i.executionTime).format('YYYY-MM-DD HH:mm') : '--',
|
||||||
@ -288,6 +371,10 @@ async function getMore() {
|
|||||||
const mapped = arr.map(mapRow).filter((i) => i && i._id);
|
const mapped = arr.map(mapRow).filter((i) => i && i._id);
|
||||||
list.value = page.value === 1 ? mapped : [...list.value, ...mapped];
|
list.value = page.value === 1 ? mapped : [...list.value, ...mapped];
|
||||||
page.value += 1;
|
page.value += 1;
|
||||||
|
|
||||||
|
// 尽量加载记录所属团队成员,用于执行人展示
|
||||||
|
const teamIds = mapped.map((i) => i.executeTeamId).filter(Boolean);
|
||||||
|
Array.from(new Set(teamIds)).forEach((tid) => loadTeamMembers(tid));
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
@ -330,21 +417,10 @@ function add() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function edit(record) {
|
function edit(record) {
|
||||||
const archive = props.data || {};
|
if (!record?._id) return;
|
||||||
const customerUserId = String(archive.externalUserId || archive.customerUserId || '') || '';
|
editingRecord.value = record;
|
||||||
uni.setStorageSync('service-record-detail', {
|
editContent.value = String(record?.taskContent || '') || '';
|
||||||
customerId: String(props.archiveId),
|
editPopupRef.value?.open?.();
|
||||||
customerName: String(archive.name || ''),
|
|
||||||
customerUserId,
|
|
||||||
id: String(record?._id || ''),
|
|
||||||
executionTime: record?.executionTime || 0,
|
|
||||||
executeTeamId: String(record?.executeTeamId || ''),
|
|
||||||
executeTeamName: String(record?.executeTeamName || ''),
|
|
||||||
eventType: String(record?.eventType || ''),
|
|
||||||
taskContent: String(record?.taskContent || ''),
|
|
||||||
pannedEventSendFile: record?.pannedEventSendFile || null,
|
|
||||||
});
|
|
||||||
uni.navigateTo({ url: `/pages/case/service-record-detail?archiveId=${encodeURIComponent(props.archiveId)}&mode=edit&id=${encodeURIComponent(record._id)}` });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePopupRef = ref(null);
|
const filePopupRef = ref(null);
|
||||||
@ -380,6 +456,45 @@ function copyFile() {
|
|||||||
closeFilePopup();
|
closeFilePopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const editPopupRef = ref(null);
|
||||||
|
const editingRecord = ref(null);
|
||||||
|
const editContent = ref('');
|
||||||
|
|
||||||
|
function closeEditPopup() {
|
||||||
|
editPopupRef.value?.close?.();
|
||||||
|
editingRecord.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveEdit() {
|
||||||
|
const r = editingRecord.value;
|
||||||
|
if (!r?._id) return;
|
||||||
|
if (!String(editContent.value || '').trim()) return toast('请输入服务内容');
|
||||||
|
|
||||||
|
await ensureDoctor();
|
||||||
|
const corpId = getCorpId();
|
||||||
|
const userId = getUserId();
|
||||||
|
if (!corpId || !userId) return toast('缺少用户信息');
|
||||||
|
|
||||||
|
const res = await api('updateServiceRecord', {
|
||||||
|
corpId,
|
||||||
|
id: String(r._id),
|
||||||
|
params: {
|
||||||
|
taskContent: String(editContent.value || ''),
|
||||||
|
updateUserId: userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res?.success) return toast(res?.message || '修改失败');
|
||||||
|
|
||||||
|
// 本地同步,避免闪烁
|
||||||
|
const idx = list.value.findIndex((i) => i && i._id === String(r._id));
|
||||||
|
if (idx > -1) list.value[idx] = { ...list.value[idx], taskContent: String(editContent.value || '') };
|
||||||
|
|
||||||
|
uni.$emit('archive-detail:service-record-changed');
|
||||||
|
uni.showToast({ title: '保存成功', icon: 'success' });
|
||||||
|
closeEditPopup();
|
||||||
|
}
|
||||||
|
|
||||||
async function loadTeams() {
|
async function loadTeams() {
|
||||||
await ensureDoctor();
|
await ensureDoctor();
|
||||||
const corpId = getCorpId();
|
const corpId = getCorpId();
|
||||||
@ -640,4 +755,56 @@ watch(
|
|||||||
background: #0877F1;
|
background: #0877F1;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.edit-sheet {
|
||||||
|
background: #fff;
|
||||||
|
border-top-left-radius: 20rpx;
|
||||||
|
border-top-right-radius: 20rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
.edit-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 28rpx;
|
||||||
|
border-bottom: 2rpx solid #f0f0f0;
|
||||||
|
}
|
||||||
|
.edit-header-left {
|
||||||
|
width: 36rpx;
|
||||||
|
height: 36rpx;
|
||||||
|
}
|
||||||
|
.edit-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.edit-close {
|
||||||
|
width: 36rpx;
|
||||||
|
height: 36rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.edit-body {
|
||||||
|
padding: 28rpx 28rpx 0;
|
||||||
|
}
|
||||||
|
.edit-textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 260rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
border: 2rpx solid #e5e7eb;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.counter {
|
||||||
|
margin-top: 12rpx;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.edit-footer {
|
||||||
|
padding: 24rpx 28rpx 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -267,6 +267,12 @@ function isTagItem(i) {
|
|||||||
return title === 'tagIds' || title === 'tag' || type === 'tag' || name.includes('标签');
|
return title === 'tagIds' || title === 'tag' || type === 'tag' || name.includes('标签');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isInHospitalSourceItem(i) {
|
||||||
|
const title = String(i?.title || '');
|
||||||
|
const name = String(i?.name || '');
|
||||||
|
return title === 'inHospitalSource' || title === 'hospitalSource' || name.includes('院内来源');
|
||||||
|
}
|
||||||
|
|
||||||
async function loadInternalTemplate() {
|
async function loadInternalTemplate() {
|
||||||
const corpId = String(account.value?.corpId || doctorInfo.value?.corpId || '') || '';
|
const corpId = String(account.value?.corpId || doctorInfo.value?.corpId || '') || '';
|
||||||
if (!corpId) return;
|
if (!corpId) return;
|
||||||
@ -304,6 +310,7 @@ async function loadInternalTemplate() {
|
|||||||
items.value = list
|
items.value = list
|
||||||
.filter((i) => i && i.fieldStatus !== 'disable')
|
.filter((i) => i && i.fieldStatus !== 'disable')
|
||||||
.filter((i) => i.operateType !== 'onlyRead')
|
.filter((i) => i.operateType !== 'onlyRead')
|
||||||
|
.filter((i) => !isInHospitalSourceItem(i))
|
||||||
.map(normalizeTemplateItem);
|
.map(normalizeTemplateItem);
|
||||||
|
|
||||||
const debugStage = items.value.find(isStageItem);
|
const debugStage = items.value.find(isStageItem);
|
||||||
@ -392,6 +399,20 @@ function buildPayload(base, inner) {
|
|||||||
return { payload, team };
|
return { payload, team };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCreatedCustomerId(res) {
|
||||||
|
const root = res && typeof res === 'object' ? res : {};
|
||||||
|
const d = root.data && typeof root.data === 'object' ? root.data : {};
|
||||||
|
return String(
|
||||||
|
d._id ||
|
||||||
|
d.id ||
|
||||||
|
d.customerId ||
|
||||||
|
d.memberId ||
|
||||||
|
root.customerId ||
|
||||||
|
root.memberId ||
|
||||||
|
''
|
||||||
|
) || '';
|
||||||
|
}
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
if (formRef.value?.verify && !formRef.value.verify()) return;
|
if (formRef.value?.verify && !formRef.value.verify()) return;
|
||||||
|
|
||||||
@ -420,10 +441,23 @@ async function save() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toast('新增成功');
|
toast('新增成功');
|
||||||
|
const createdId = getCreatedCustomerId(res);
|
||||||
uni.removeStorageSync(BASE_KEY);
|
uni.removeStorageSync(BASE_KEY);
|
||||||
uni.removeStorageSync(INNER_KEY);
|
uni.removeStorageSync(INNER_KEY);
|
||||||
uni.setStorageSync(NEED_RELOAD_STORAGE_KEY, 1);
|
uni.setStorageSync(NEED_RELOAD_STORAGE_KEY, 1);
|
||||||
uni.navigateBack({ delta: 2 });
|
uni.navigateBack({
|
||||||
|
delta: 2,
|
||||||
|
success: () => {
|
||||||
|
if (!createdId) return;
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateTo({ url: `/pages/case/archive-detail?id=${encodeURIComponent(createdId)}` });
|
||||||
|
}, 30);
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
if (!createdId) return;
|
||||||
|
uni.redirectTo({ url: `/pages/case/archive-detail?id=${encodeURIComponent(createdId)}` });
|
||||||
|
},
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
toast('新增失败');
|
toast('新增失败');
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="page">
|
<view class="page">
|
||||||
<!-- Mobile 来源: ykt-management-mobile/src/pages/customer/service-record-detail/service-record-detail.vue -->
|
<!-- Mobile 来源: ykt-management-mobile/src/pages/customer/service-record-detail/service-record-detail.vue -->
|
||||||
<view class="body">
|
<view v-if="!recordId" class="body">
|
||||||
<scroll-view scroll-y class="scroll">
|
<scroll-view scroll-y class="scroll">
|
||||||
<view class="card">
|
<view class="card">
|
||||||
<view class="section-title">执行日期</view>
|
<view class="section-title">执行日期</view>
|
||||||
@ -31,12 +31,11 @@
|
|||||||
</picker>
|
</picker>
|
||||||
|
|
||||||
<view class="section-title">所属团队</view>
|
<view class="section-title">所属团队</view>
|
||||||
<picker mode="selector" :range="teamOptions" range-key="label" @change="pickTeam" :disabled="Boolean(recordId)">
|
<picker mode="selector" :range="teamOptions" range-key="label" :disabled="true">
|
||||||
<view class="picker-box between">
|
<view class="picker-box">
|
||||||
<view class="picker-text" :class="{ muted: !currentTeam?.value }">
|
<view class="picker-text" :class="{ muted: !currentTeam?.value }">
|
||||||
{{ currentTeam?.value ? currentTeam.label : '请选择所属团队' }}
|
{{ currentTeam?.value ? currentTeam.label : '请选择所属团队' }}
|
||||||
</view>
|
</view>
|
||||||
<uni-icons type="arrowright" size="16" color="#999" />
|
|
||||||
</view>
|
</view>
|
||||||
</picker>
|
</picker>
|
||||||
|
|
||||||
@ -55,14 +54,37 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="recordId" class="delete-fab" @click="remove">
|
<!-- 编辑:仅支持修改服务内容(底部弹层) -->
|
||||||
<uni-icons type="trash" size="22" color="#ff4d4f" />
|
<uni-popup v-else ref="editPopupRef" type="bottom" :mask-click="true" @maskClick="closeEdit">
|
||||||
</view>
|
<view class="sheet">
|
||||||
|
<view class="sheet-header">
|
||||||
|
<view class="sheet-header-left" />
|
||||||
|
<view class="sheet-title">修改服务内容</view>
|
||||||
|
<view class="sheet-close" @click="closeEdit">
|
||||||
|
<uni-icons type="closeempty" size="18" color="#333" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="sheet-body">
|
||||||
|
<textarea
|
||||||
|
v-model="form.taskContent"
|
||||||
|
class="sheet-textarea"
|
||||||
|
placeholder="请输入服务内容"
|
||||||
|
:maxlength="1000"
|
||||||
|
/>
|
||||||
|
<view class="counter">{{ (form.taskContent || '').length }}/1000</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="sheet-footer">
|
||||||
|
<button class="primary-btn" @click="saveEdit">保存</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, ref } from 'vue';
|
import { nextTick, reactive, ref } from 'vue';
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
@ -107,7 +129,8 @@ async function ensureDoctor() {
|
|||||||
function getUserId() {
|
function getUserId() {
|
||||||
const d = doctorInfo.value || {};
|
const d = doctorInfo.value || {};
|
||||||
const a = account.value || {};
|
const a = account.value || {};
|
||||||
return String(d.userid || d.userId || d.corpUserId || a.userid || a.userId || '') || '';
|
const t = uni.getStorageSync('ykt_case_current_team') || {};
|
||||||
|
return String(d.userid || d.userId || d.corpUserId || a.userid || a.userId || t.userId || t.userid || t.corpUserId || '') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCorpId() {
|
function getCorpId() {
|
||||||
@ -124,25 +147,6 @@ function getCurrentTeam() {
|
|||||||
return teamId ? { value: teamId, label: name || teamId } : null;
|
return teamId ? { value: teamId, label: name || teamId } : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadTeams() {
|
|
||||||
await ensureDoctor();
|
|
||||||
const corpId = getCorpId();
|
|
||||||
const userId = getUserId();
|
|
||||||
if (!corpId || !userId) return;
|
|
||||||
const res = await api('getTeamBymember', { corpId, corpUserId: userId });
|
|
||||||
if (!res?.success) return;
|
|
||||||
const list = Array.isArray(res?.data) ? res.data : Array.isArray(res?.data?.data) ? res.data.data : [];
|
|
||||||
teamOptions.value = list
|
|
||||||
.map((raw) => {
|
|
||||||
if (!raw || typeof raw !== 'object') return null;
|
|
||||||
const teamId = raw.teamId || raw.id || raw._id || '';
|
|
||||||
const name = raw.name || raw.teamName || raw.team || '';
|
|
||||||
if (!teamId) return null;
|
|
||||||
return { label: String(name || teamId), value: String(teamId) };
|
|
||||||
})
|
|
||||||
.filter(Boolean);
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
archiveId.value = options?.archiveId ? String(options.archiveId) : '';
|
archiveId.value = options?.archiveId ? String(options.archiveId) : '';
|
||||||
recordId.value = options?.id ? String(options.id) : '';
|
recordId.value = options?.id ? String(options.id) : '';
|
||||||
@ -162,26 +166,22 @@ onLoad((options) => {
|
|||||||
const seedType = String(seed?.eventType || '') || '';
|
const seedType = String(seed?.eventType || '') || '';
|
||||||
currentType.value = typeOptions.find((i) => i.value === seedType) || null;
|
currentType.value = typeOptions.find((i) => i.value === seedType) || null;
|
||||||
|
|
||||||
const seedTeamId = String(seed?.executeTeamId || '') || '';
|
// 新建:团队固定为当前团队,不支持切换
|
||||||
const seedTeamName = String(seed?.executeTeamName || '') || '';
|
const cur = getCurrentTeam();
|
||||||
if (seedTeamId) currentTeam.value = { value: seedTeamId, label: seedTeamName || seedTeamId };
|
currentTeam.value = cur;
|
||||||
else currentTeam.value = getCurrentTeam();
|
teamOptions.value = cur ? [cur] : [];
|
||||||
|
|
||||||
loadTeams().then(() => {
|
if (recordId.value) {
|
||||||
if (seedTeamId) currentTeam.value = teamOptions.value.find((t) => t.value === seedTeamId) || currentTeam.value;
|
uni.setNavigationBarTitle({ title: '修改服务内容' });
|
||||||
else {
|
nextTick(() => editPopupRef.value?.open?.());
|
||||||
const cur = getCurrentTeam();
|
} else {
|
||||||
if (cur) currentTeam.value = teamOptions.value.find((t) => t.value === cur.value) || cur;
|
uni.setNavigationBarTitle({ title: '新建服务记录' });
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function pickType(e) {
|
function pickType(e) {
|
||||||
currentType.value = typeOptions[e.detail.value] || null;
|
currentType.value = typeOptions[e.detail.value] || null;
|
||||||
}
|
}
|
||||||
function pickTeam(e) {
|
|
||||||
currentTeam.value = teamOptions.value[e.detail.value] || null;
|
|
||||||
}
|
|
||||||
function pickDate(e) {
|
function pickDate(e) {
|
||||||
date.value = e.detail.value || '';
|
date.value = e.detail.value || '';
|
||||||
}
|
}
|
||||||
@ -205,6 +205,45 @@ function save() {
|
|||||||
submit(executionTime);
|
submit(executionTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const editPopupRef = ref(null);
|
||||||
|
function closeEdit() {
|
||||||
|
editPopupRef.value?.close?.();
|
||||||
|
setTimeout(() => uni.navigateBack(), 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveEdit() {
|
||||||
|
if (!String(form.taskContent || '').trim()) return uni.showToast({ title: '请输入服务内容', icon: 'none' });
|
||||||
|
submitEdit();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitEdit() {
|
||||||
|
await ensureDoctor();
|
||||||
|
const corpId = getCorpId();
|
||||||
|
const userId = getUserId();
|
||||||
|
if (!corpId || !userId) {
|
||||||
|
toast('缺少用户/团队信息');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!recordId.value) return;
|
||||||
|
|
||||||
|
const res = await api('updateServiceRecord', {
|
||||||
|
corpId,
|
||||||
|
id: recordId.value,
|
||||||
|
params: {
|
||||||
|
taskContent: form.taskContent,
|
||||||
|
updateUserId: userId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '修改失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.$emit('archive-detail:service-record-changed');
|
||||||
|
uni.showToast({ title: '保存成功', icon: 'success' });
|
||||||
|
setTimeout(() => uni.navigateBack(), 300);
|
||||||
|
}
|
||||||
|
|
||||||
async function submit(executionTime) {
|
async function submit(executionTime) {
|
||||||
await ensureDoctor();
|
await ensureDoctor();
|
||||||
const corpId = getCorpId();
|
const corpId = getCorpId();
|
||||||
@ -252,27 +291,6 @@ async function submit(executionTime) {
|
|||||||
uni.showToast({ title: '保存成功', icon: 'success' });
|
uni.showToast({ title: '保存成功', icon: 'success' });
|
||||||
setTimeout(() => uni.navigateBack(), 300);
|
setTimeout(() => uni.navigateBack(), 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove() {
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '确定删除当前记录?',
|
|
||||||
success: async (res) => {
|
|
||||||
if (!res.confirm) return;
|
|
||||||
await ensureDoctor();
|
|
||||||
const corpId = getCorpId();
|
|
||||||
if (!corpId || !recordId.value) return;
|
|
||||||
const resp = await api('removeServiceRecord', { corpId, id: recordId.value });
|
|
||||||
if (!resp?.success) {
|
|
||||||
toast(resp?.message || '删除失败');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uni.$emit('archive-detail:service-record-changed');
|
|
||||||
uni.showToast({ title: '已删除', icon: 'success' });
|
|
||||||
setTimeout(() => uni.navigateBack(), 300);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@ -377,18 +395,60 @@ function remove() {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete-fab {
|
.sheet {
|
||||||
position: fixed;
|
|
||||||
right: 16px;
|
|
||||||
bottom: calc(96px + env(safe-area-inset-bottom));
|
|
||||||
width: 52px;
|
|
||||||
height: 52px;
|
|
||||||
border-radius: 26px;
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
border-top-left-radius: 14px;
|
||||||
|
border-top-right-radius: 14px;
|
||||||
|
padding-bottom: calc(14px + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
.sheet-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 14px 16px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
.sheet-header-left {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
.sheet-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.sheet-close {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
box-shadow: 0 10px 18px rgba(0, 0, 0, 0.12);
|
}
|
||||||
z-index: 30;
|
.sheet-body {
|
||||||
|
padding: 14px 16px 0;
|
||||||
|
}
|
||||||
|
.sheet-textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 180px;
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid #e6e6e6;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.sheet-footer {
|
||||||
|
padding: 12px 16px 0;
|
||||||
|
}
|
||||||
|
.primary-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 44px;
|
||||||
|
line-height: 44px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #0877F1;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.primary-btn::after {
|
||||||
|
border: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -3,10 +3,6 @@
|
|||||||
<!-- Mobile 来源: ykt-management-mobile/src/pages/customer/visit-record-detail/visit-record-detail.vue -->
|
<!-- Mobile 来源: ykt-management-mobile/src/pages/customer/visit-record-detail/visit-record-detail.vue -->
|
||||||
<view class="body">
|
<view class="body">
|
||||||
<scroll-view scroll-y class="scroll">
|
<scroll-view scroll-y class="scroll">
|
||||||
<view class="header">
|
|
||||||
<view class="header-title">{{ titleText || '健康档案' }}</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="form-wrap">
|
<view class="form-wrap">
|
||||||
<FormTemplate v-if="temp" ref="formRef" :items="showItems" :form="forms" @change="onChange" />
|
<FormTemplate v-if="temp" ref="formRef" :items="showItems" :form="forms" @change="onChange" />
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user