From de468c1acb7df22b7609dae64cbc15d8de20269d Mon Sep 17 00:00:00 2001 From: Jafeng <2998840497@qq.com> Date: Fri, 6 Feb 2026 14:12:56 +0800 Subject: [PATCH 1/6] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E7=97=85=E5=8E=86?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/home/case-home.vue | 154 +++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 71 deletions(-) diff --git a/pages/home/case-home.vue b/pages/home/case-home.vue index 3941d0a..6b255a7 100644 --- a/pages/home/case-home.vue +++ b/pages/home/case-home.vue @@ -30,13 +30,8 @@ - + {{ tab.label }} @@ -47,32 +42,24 @@ - + {{ group.letter }} - - + + - + {{ patient.name }} - {{ patient.gender }}/{{ patient.age }}岁 + {{ patient.gender }}{{ patient.age ? '/' + patient.age + '岁' : '' }} @@ -80,12 +67,21 @@ - - + + + + + {{ patient.record.type }} / {{ patient.record.date }} / {{ patient.record.diagnosis }} + + 暂无病历记录 + + + - - diff --git a/pages/case/utils/template.js b/pages/case/utils/template.js new file mode 100644 index 0000000..5af00f9 --- /dev/null +++ b/pages/case/utils/template.js @@ -0,0 +1,95 @@ +function normalizeOptions(options) { + if (!Array.isArray(options)) return []; + if (!options.length) return []; + if (typeof options[0] === 'string') return options.filter((i) => typeof i === 'string'); + if (typeof options[0] === 'object') { + return options + .map((i) => { + const label = i?.label ?? i?.name ?? i?.text ?? i?.title ?? ''; + const value = i?.value ?? i?.id ?? i?.key ?? label; + if (!label && (value === undefined || value === null || value === '')) return null; + return { label: String(label || value), value: String(value) }; + }) + .filter(Boolean); + } + return []; +} + +export function normalizeTemplateItem(item) { + const next = { ...(item || {}) }; + + if (next.operateType === 'custom') next.operateType = 'formCell'; + + const originalType = next.type; + const customTypeMap = { + customerSource: 'select', + customerStage: 'select', + tag: 'multiSelectAndOther', + reference: 'input', + selectWwuser: 'select', + files: 'files', + corpProject: 'select', + diagnosis: 'textarea', + BMI: 'input', + bloodPressure: 'textarea', + selfMultipleDiseases: 'textarea', + }; + if (originalType && customTypeMap[originalType]) { + next.__originType = originalType; + next.type = customTypeMap[originalType]; + } + + const aliasTypeMap = { + text: 'input', + string: 'input', + number: 'input', + integer: 'input', + int: 'input', + }; + if (next.type && aliasTypeMap[next.type]) { + next.type = aliasTypeMap[next.type]; + if (!next.inputType && (originalType === 'number' || originalType === 'integer' || originalType === 'int')) next.inputType = 'number'; + } + + const rawRange = next.range || next.options || next.optionList || next.values || []; + const range = normalizeOptions(rawRange); + + if (next.type === 'select' || next.type === 'selectAndOther' || next.type === 'selectAndImage') { + next.range = range; + } else if (next.type === 'radio') { + // wxapp 目前 radio 组件只支持字符串列表;模板如为对象选项则降级为 select + if (range.length && typeof range[0] === 'object') { + next.type = 'select'; + next.range = range; + } else { + next.range = Array.isArray(rawRange) ? rawRange : []; + } + } + + if (!next.operateType) next.operateType = 'formCell'; + next.required = Boolean(next.required); + + if (next.type === 'input' && (next.wordLimit === undefined || next.wordLimit === null || next.wordLimit === '')) next.wordLimit = 20; + if (next.type === 'textarea' && (next.wordLimit === undefined || next.wordLimit === null || next.wordLimit === '')) next.wordLimit = 200; + return next; +} + +export function unwrapTemplateResponse(res) { + const d = res?.data; + if (d && typeof d === 'object') { + if (d.data && typeof d.data === 'object') return d.data; + return d; + } + return res && typeof res === 'object' ? res : {}; +} + +export function normalizeTemplate(temp) { + const t = temp && typeof temp === 'object' ? { ...temp } : {}; + const list = Array.isArray(t.templateList) ? t.templateList : []; + t.templateList = list + .filter((i) => i && i.fieldStatus !== 'disable') + .filter((i) => i.operateType !== 'onlyRead') + .map(normalizeTemplateItem); + return t; +} + diff --git a/pages/case/utils/visit-record.js b/pages/case/utils/visit-record.js new file mode 100644 index 0000000..721c1ef --- /dev/null +++ b/pages/case/utils/visit-record.js @@ -0,0 +1,40 @@ +function isEmpty(v) { + if (v === null || v === undefined) return true; + if (Array.isArray(v)) return v.length === 0; + if (typeof v === 'string') return v.trim() === ''; + return false; +} + +const ALIAS_MAP = { + outpatient: { + diagnosisName: 'diagnosis', + medicalHistorySummary: 'medicalHistory', + }, + inhospital: { + diagnosisName: 'diagnosis', + medicalHistorySummary: 'medicalHistory', + operationDate: 'surgeryDate', + operation: 'surgeryName', + }, + physicalExaminationTemplate: { + inspectTime: 'inspectDate', + inspectSummary: 'summary', + }, + preConsultation: { + presentIllnessHistory: 'presentIllness', + pastMedicalHistory: 'pastHistory', + }, +}; + +export function normalizeVisitRecordFormData(templateType, raw) { + const input = raw && typeof raw === 'object' ? raw : {}; + const out = { ...input }; + const map = ALIAS_MAP[String(templateType || '')] || {}; + + Object.entries(map).forEach(([from, to]) => { + if (isEmpty(out[to]) && !isEmpty(out[from])) out[to] = out[from]; + }); + + return out; +} + diff --git a/pages/case/visit-record-detail.vue b/pages/case/visit-record-detail.vue index 0c283cd..d90669c 100644 --- a/pages/case/visit-record-detail.vue +++ b/pages/case/visit-record-detail.vue @@ -4,11 +4,11 @@ - {{ template?.templateName || '健康档案' }} + {{ titleText || '健康档案' }} - + @@ -19,7 +19,8 @@ - + + PDF × @@ -49,10 +50,12 @@ import { onLoad } from '@dcloudio/uni-app'; import dayjs from 'dayjs'; import { storeToRefs } from 'pinia'; import FormTemplate from '@/components/form-template/index.vue'; -import { getVisitRecordTemplate } from './components/archive-detail/templates'; import api from '@/utils/api'; +import { uploadFile } from '@/utils/file'; import useAccountStore from '@/store/account'; import { toast, confirm, loading as uniLoading, hideLoading } from '@/utils/widget'; +import { normalizeVisitRecordFormData } from './utils/visit-record'; +import { normalizeTemplate, unwrapTemplateResponse } from './utils/template'; const accountStore = useAccountStore(); const { account, doctorInfo } = storeToRefs(accountStore); @@ -84,14 +87,17 @@ function getCorpId() { const memberId = ref(''); const recordId = ref(''); const templateType = ref(''); -const customerName = ref(''); -const template = computed(() => getVisitRecordTemplate(templateType.value)); +const temp = ref(null); +const titleText = computed(() => { + const t = temp.value || {}; + return String(t.name || t.templateName || t.templateTypeName || '').trim(); +}); const detail = ref({}); const form = reactive({}); const forms = computed(() => ({ ...detail.value, ...form })); const showItems = computed(() => { - const list = template.value?.templateList || []; + const list = temp.value?.templateList || []; // referenceField 兼容(与 mobile 一致) return list.filter((i) => { if (i?.type === 'files') return false; @@ -103,7 +109,7 @@ const showItems = computed(() => { }); const hasFilesField = computed(() => { - const list = template.value?.templateList || []; + const list = temp.value?.templateList || []; return list.some((i) => i && (i.type === 'files' || i.title === 'files')); }); @@ -119,30 +125,43 @@ function ensureFilesField() { form.files = []; } +async function loadTemplate(t) { + const corpId = getCorpId(); + if (!corpId) return null; + try { + const res = await api('getCurrentTemplate', { corpId, templateType: t }); + if (!res?.success) { + toast(res?.message || '获取模板失败'); + return null; + } + const raw = unwrapTemplateResponse(res); + return normalizeTemplate(raw); + } catch (e) { + console.error('loadTemplate error:', e); + toast('获取模板失败'); + return null; + } +} + onLoad(async (options) => { memberId.value = options?.memberId || options?.archiveId || ''; recordId.value = options?.id || ''; templateType.value = options?.type || ''; - customerName.value = decodeURIComponent(options?.customerName || ''); if (recordId.value) { await getDetail(); } else { if (!templateType.value) templateType.value = 'outpatient'; + temp.value = await loadTemplate(templateType.value); + if (temp.value?.templateType) templateType.value = String(temp.value.templateType); ensureFilesField(); - // 门诊记录默认今日日期 - if (templateType.value === 'outpatient') { - form.visitTime = dayjs().format('YYYY-MM-DD'); - } - // 住院记录默认今日日期 - if (templateType.value === 'inhospital') { - form.inhosDate = dayjs().format('YYYY-MM-DD'); - } - // 体检记录默认今日日期 - if (templateType.value === 'physicalExaminationTemplate') { - form.inspectDate = dayjs().format('YYYY-MM-DD'); - } + + // 默认填充模板时间字段 + const timeKey = temp.value?.service?.timeTitle || ''; + if (timeKey && !form[timeKey]) form[timeKey] = dayjs().format('YYYY-MM-DD'); } + + if (titleText.value) uni.setNavigationBarTitle({ title: titleText.value }); }); async function getDetail() { @@ -162,14 +181,14 @@ async function getDetail() { const record = res?.record || res?.data?.record || null; if (res?.success && record) { templateType.value = record.templateType || record.medicalType || templateType.value; - - // 兼容模板字段:wxapp 使用 diagnosis,但接口通常返回 diagnosisName - if ((record.medicalType === 'outpatient' || record.medicalType === 'inhospital') && !record.diagnosis && record.diagnosisName) { - record.diagnosis = record.diagnosisName; - } - - detail.value = record; + detail.value = normalizeVisitRecordFormData(templateType.value, record); ensureFilesField(); + // 详情可能返回真实 templateType:与模板保持一致 + if (!temp.value || temp.value?.templateType !== templateType.value) { + temp.value = await loadTemplate(templateType.value); + if (temp.value?.templateType) templateType.value = String(temp.value.templateType); + if (titleText.value) uni.setNavigationBarTitle({ title: titleText.value }); + } } else { toast(res.message || '加载失败'); } @@ -185,7 +204,7 @@ function onChange({ title, value }) { const item = showItems.value.find((i) => i.title === title); if (!item) return; // 关联字段变化时清理被关联字段(与 mobile 行为一致) - const relat = (template.value?.templateList || []).filter((i) => i.referenceField === title); + const relat = (temp.value?.templateList || []).filter((i) => i.referenceField === title); relat.forEach((i) => (form[i.title] = '')); } @@ -224,7 +243,7 @@ async function save() { } // sortTime:使用模板中的时间字段 - const sortTimeKey = template.value?.service?.timeTitle || ''; + const sortTimeKey = temp.value?.service?.timeTitle || ''; if (sortTimeKey && form[sortTimeKey] && dayjs(form[sortTimeKey]).isValid()) { params.sortTime = dayjs(form[sortTimeKey]).valueOf(); } else { @@ -252,65 +271,84 @@ async function save() { } } -function remove() { - confirm('确定删除当前记录?', async () => { - if (!memberId.value || !recordId.value) return toast('缺少必要信息'); - await ensureDoctor(); - const corpId = getCorpId(); - if (!corpId) return toast('缺少必要信息'); - uniLoading('删除中...'); - try { - const res = await api('removeMedicalRecord', { - corpId, - memberId: memberId.value, - medicalType: templateType.value, - _id: recordId.value, - }); - hideLoading(); - if (res.success) { - uni.$emit('archive-detail:visit-record-changed'); - toast(res.message || '已删除'); - setTimeout(() => uni.navigateBack(), 300); - } else { - toast(res.message || '删除失败'); - } - } catch (error) { - hideLoading(); - console.error('remove error:', error); - toast('删除失败'); +async function remove() { + try { + await confirm('确定删除当前记录?'); + } catch { + return; + } + if (!memberId.value || !recordId.value) return toast('缺少必要信息'); + await ensureDoctor(); + const corpId = getCorpId(); + if (!corpId) return toast('缺少必要信息'); + uniLoading('删除中...'); + try { + const res = await api('removeMedicalRecord', { + corpId, + memberId: memberId.value, + medicalType: templateType.value, + _id: recordId.value, + }); + hideLoading(); + if (res.success) { + uni.$emit('archive-detail:visit-record-changed'); + toast(res.message || '已删除'); + setTimeout(() => uni.navigateBack(), 300); + } else { + toast(res.message || '删除失败'); } - }); + } catch (error) { + hideLoading(); + console.error('remove error:', error); + toast('删除失败'); + } } -function addFiles() { - const fileConfig = template.value?.templateList?.find(i => i.type === 'files'); - const maxSize = fileConfig?.maxSize || 5; // MB - const accept = fileConfig?.accept || 'pdf'; +function isPdfUrl(url) { + const u = String(url || '').toLowerCase(); + return u.includes('.pdf') || u.startsWith('data:application/pdf'); +} - uni.chooseMessageFile({ - count: 9, - type: 'file', - extension: [accept], - success: (res) => { - const files = Array.isArray(res.tempFiles) ? res.tempFiles : []; - const maxBytes = maxSize * 1024 * 1024; - - // 验证文件大小 - const invalidFiles = files.filter(f => f.size > maxBytes); - if (invalidFiles.length > 0) { - toast(`文件大小不能超过${maxSize}M`); - return; - } +async function addFiles() { + const fileConfig = temp.value?.templateList?.find((i) => i && (i.type === 'files' || i.title === 'files')) || {}; + const maxSize = Number(fileConfig?.maxSize || 5) || 5; // MB + const accept = String(fileConfig?.accept || 'pdf') || 'pdf'; - const next = files.map((f) => ({ - url: f.path, - name: f.name || '', - size: f.size - })); - const cur = Array.isArray(forms.value.files) ? forms.value.files : []; - form.files = [...cur, ...next]; - }, + const chooseRes = await new Promise((resolve) => { + uni.chooseMessageFile({ + count: 9, + type: 'file', + extension: accept ? [accept] : undefined, + success: (res) => resolve(res), + fail: () => resolve(null), + }); }); + const files = Array.isArray(chooseRes?.tempFiles) ? chooseRes.tempFiles : []; + if (!files.length) return; + + const maxBytes = maxSize * 1024 * 1024; + const invalidFiles = files.filter((f) => f && f.size > maxBytes); + if (invalidFiles.length > 0) { + toast(`文件大小不能超过${maxSize}M`); + return; + } + + const cur = Array.isArray(forms.value.files) ? forms.value.files : []; + uniLoading('上传中...'); + try { + const uploaded = []; + for (const f of files) { + const url = await uploadFile(f.path); + if (!url) { + toast('上传失败'); + continue; + } + uploaded.push({ url, name: f.name || '', size: f.size }); + } + form.files = [...cur, ...uploaded]; + } finally { + hideLoading(); + } } function removeFile(idx) { @@ -319,8 +357,32 @@ function removeFile(idx) { } function previewFile(idx) { - const urls = fileList.value.map((i) => i.url); - uni.previewImage({ urls, current: urls[idx] }); + const f = fileList.value[idx]; + const url = f?.url ? String(f.url) : ''; + if (!url) return; + if (!isPdfUrl(url)) { + const urls = fileList.value.map((i) => i.url); + uni.previewImage({ urls, current: url }); + return; + } + uniLoading('打开中...'); + uni.downloadFile({ + url, + success: (res) => { + hideLoading(); + const filePath = res?.tempFilePath; + if (!filePath) return toast('打开失败'); + uni.openDocument({ + filePath, + showMenu: true, + fail: () => toast('打开失败'), + }); + }, + fail: () => { + hideLoading(); + toast('打开失败'); + }, + }); } @@ -393,6 +455,17 @@ function previewFile(idx) { width: 100%; height: 100%; } +.upload-pdf { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + font-size: 34rpx; + font-weight: 700; + color: #0877F1; + background: #eef6ff; +} .upload-remove { position: absolute; right: 0; diff --git a/utils/api.js b/utils/api.js index dd29c2e..687381f 100644 --- a/utils/api.js +++ b/utils/api.js @@ -10,6 +10,8 @@ const urlsConfig = { getTeamData: 'getTeamData', getTeamBymember: 'getTeamBymember', getCurrentTemplate: 'getCurrentTemplate', + getTemplateGroup: 'getTemplateGroup', + getTemplateListByTemptype: 'getTemplateListByTemptype', wxAppLogin: 'wxAppLogin', getDeptList: 'getRealDeptList', getHospitalList: 'getRealHospital', From e37c2b1089ba1cdc03b96fcef2eb88e16ede1d37 Mon Sep 17 00:00:00 2001 From: Jafeng <2998840497@qq.com> Date: Fri, 6 Feb 2026 18:04:34 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E5=B7=B2=E7=9F=A5?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/case/archive-detail.vue | 25 +-- .../archive-detail/customer-profile-tab.vue | 17 +- .../archive-detail/health-profile-tab.vue | 58 ++++- .../archive-detail/service-info-tab.vue | 203 +++++++++++++++-- pages/case/patient-inner-info.vue | 36 +++- pages/case/service-record-detail.vue | 204 +++++++++++------- pages/case/visit-record-detail.vue | 4 - 7 files changed, 415 insertions(+), 132 deletions(-) diff --git a/pages/case/archive-detail.vue b/pages/case/archive-detail.vue index e5766e8..628ef24 100644 --- a/pages/case/archive-detail.vue +++ b/pages/case/archive-detail.vue @@ -2,18 +2,12 @@ - - - - {{ archive.name || '-' }} {{ sexOrAge }} - {{ archive.mobile }} - {{ row.label }}: @@ -296,7 +290,7 @@ function normalizeArchiveFromApi(raw) { name: r.name || '', sex: r.sex || r.gender || '', 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 || '', outpatientNo: r.outpatientNo || '', inpatientNo: r.inpatientNo || '', @@ -778,25 +772,10 @@ const saveAddGroup = async () => { 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 { flex: 1; min-width: 0; - padding: 0 20rpx; + padding: 0 20rpx 0 0; } .name-row { diff --git a/pages/case/components/archive-detail/customer-profile-tab.vue b/pages/case/components/archive-detail/customer-profile-tab.vue index a3f0609..3e6472e 100644 --- a/pages/case/components/archive-detail/customer-profile-tab.vue +++ b/pages/case/components/archive-detail/customer-profile-tab.vue @@ -40,13 +40,6 @@ - - 院内来源 - - {{ latestTransferRecord?.executeTeamName || '点击查看' }} - - - (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 = { reference(formModel) { diff --git a/pages/case/components/archive-detail/health-profile-tab.vue b/pages/case/components/archive-detail/health-profile-tab.vue index 3342079..a26a5c4 100644 --- a/pages/case/components/archive-detail/health-profile-tab.vue +++ b/pages/case/components/archive-detail/health-profile-tab.vue @@ -54,11 +54,11 @@ mode="selector" :range="selectableTemplates" range-key="name" - :disabled="selectableTemplates.length === 0" + :disabled="fabPickerDisabled" :style="{ bottom: `${floatingBottom}px` }" @change="pickAddType" > - + @@ -81,6 +81,8 @@ const props = defineProps({ const FALLBACK_TEMPLATE_TYPES = ['outpatient', 'inhospital', 'preConsultation', 'physicalExaminationTemplate']; const templates = ref([]); 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) => { if (t?.templateType) m[String(t.templateType)] = t; return m; @@ -393,16 +395,58 @@ function previewFiles(r, idx) { uni.previewImage({ urls, current: urls[idx] }); } -function pickAddType(e) { - if (!props.archiveId) return toast('缺少档案信息'); - const idx = Number(e?.detail?.value ?? -1); - const t = selectableTemplates.value[idx]; +function goAdd(t) { if (!t?.templateType) return; uni.navigateTo({ 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) { const type = String(record?.medicalType || record?.templateType || '') || ''; uni.navigateTo({ @@ -411,6 +455,8 @@ function edit(record) { } onMounted(() => { + // 提前加载模板,避免首次点“+”时 picker 无法立即弹出 + loadVisitTemplates(); // archiveId 可能后置赋值:这里保留一次兜底刷新,主逻辑交给 watch refreshList(); uni.$on('archive-detail:visit-record-changed', refreshList); diff --git a/pages/case/components/archive-detail/service-info-tab.vue b/pages/case/components/archive-detail/service-info-tab.vue index ea575c8..d351882 100644 --- a/pages/case/components/archive-detail/service-info-tab.vue +++ b/pages/case/components/archive-detail/service-info-tab.vue @@ -40,8 +40,8 @@ {{ i.typeStr }} - {{ i.executorName }} - {{ i.executeTeamName }} + {{ executorText(i) }} + {{ executeTeamText(i) }} @@ -79,6 +79,31 @@ + + + + + + + 修改服务内容 + + + + + +