Compare commits
11 Commits
dev-建档流程优化
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f317e2960 | ||
|
|
196a67d6fd | ||
|
|
a3313064c0 | ||
|
|
ae2661ab26 | ||
|
|
c22f57b281 | ||
|
|
d25305aa0c | ||
|
|
289e697330 | ||
|
|
2c9be532dd | ||
|
|
0378c0523c | ||
|
|
9299bbac15 | ||
|
|
3696a8cf84 |
7
App.vue
7
App.vue
@ -2,15 +2,18 @@
|
||||
import dbStore from "@/store/db";
|
||||
import accountStore from "@/store/account";
|
||||
import { globalUnreadListenerManager } from "@/utils/global-unread-listener.js";
|
||||
import { initApiContextFromAppOptions } from "@/utils/api-base-config";
|
||||
|
||||
export default {
|
||||
async onLaunch() {
|
||||
async onLaunch(options) {
|
||||
initApiContextFromAppOptions(options);
|
||||
console.log("App Launch: ");
|
||||
|
||||
// 获取 openId 并初始化 IM
|
||||
// await this.initIMOnLaunch();
|
||||
},
|
||||
onShow: function () {
|
||||
onShow: function (options) {
|
||||
initApiContextFromAppOptions(options);
|
||||
const db = dbStore();
|
||||
if (db && typeof db.getJobs === "function") {
|
||||
db.getJobs();
|
||||
|
||||
69
components/form-template/auto-fill.js
Normal file
69
components/form-template/auto-fill.js
Normal file
@ -0,0 +1,69 @@
|
||||
const DATE_ONLY_RE = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
|
||||
|
||||
export function resolveAutoFillValue(item, form = {}) {
|
||||
const rule = item && item.autoFill;
|
||||
if (!rule || !rule.sourceField || !rule.type) return undefined;
|
||||
|
||||
const sourceValue = form ? form[rule.sourceField] : '';
|
||||
if (!sourceValue) return '';
|
||||
|
||||
if (rule.type === 'addDays') {
|
||||
const days = Number(rule.days);
|
||||
if (!Number.isFinite(days)) return '';
|
||||
return addDays(sourceValue, days);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function collectAutoFillChanges(items = [], form = {}) {
|
||||
if (!Array.isArray(items)) return [];
|
||||
|
||||
return items.reduce((changes, item) => {
|
||||
if (!item || !item.title) return changes;
|
||||
|
||||
const nextValue = resolveAutoFillValue(item, form);
|
||||
if (nextValue === undefined) return changes;
|
||||
|
||||
const currentValue = form && form[item.title] !== undefined && form[item.title] !== null
|
||||
? String(form[item.title])
|
||||
: '';
|
||||
if (currentValue !== nextValue) {
|
||||
changes.push({ title: item.title, value: nextValue });
|
||||
}
|
||||
return changes;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function addDays(value, days) {
|
||||
const date = parseDateOnly(value);
|
||||
if (!date) return '';
|
||||
date.setUTCDate(date.getUTCDate() + days);
|
||||
return formatDateOnly(date);
|
||||
}
|
||||
|
||||
function parseDateOnly(value) {
|
||||
const match = String(value || '').trim().match(DATE_ONLY_RE);
|
||||
if (!match) return null;
|
||||
|
||||
const year = Number(match[1]);
|
||||
const month = Number(match[2]);
|
||||
const day = Number(match[3]);
|
||||
const date = new Date(Date.UTC(year, month - 1, day));
|
||||
|
||||
if (
|
||||
date.getUTCFullYear() !== year ||
|
||||
date.getUTCMonth() !== month - 1 ||
|
||||
date.getUTCDate() !== day
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
function formatDateOnly(date) {
|
||||
const year = date.getUTCFullYear();
|
||||
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getUTCDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
@ -8,7 +8,7 @@
|
||||
<script setup>
|
||||
import { computed, provide, ref, watch } from 'vue';
|
||||
import verifyForm from './verify.js';
|
||||
import { collectAutoFillChanges } from './auto-fill.mjs';
|
||||
import { collectAutoFillChanges } from './auto-fill.js';
|
||||
|
||||
import FormCell from './form-cell/index.vue';
|
||||
// import CustomCell from './custom-cell/index.vue';
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<template #footer>
|
||||
<button-footer :showCancel="customerId ? true : false" cancelText="删除" confirmText="保存" @cancel="unBindArchive()"
|
||||
<button-footer :showCancel="customerId ? true : false" cancelText="删除" :confirmText="healthTypes.length?'下一步':'保存'" @cancel="unBindArchive()"
|
||||
@confirm="confirm()" />
|
||||
</template>
|
||||
</full-page>
|
||||
@ -57,6 +57,7 @@ const tempRef = ref(null);
|
||||
const verifyVisible = ref(false);
|
||||
const visible = ref(false);
|
||||
const referenceCustomer = ref(null)
|
||||
const healthTypes = ref([]);
|
||||
|
||||
const formData = computed(() => {
|
||||
return { ...customer.value, ...form.value, mobile: account.value?.mobile }
|
||||
@ -164,7 +165,17 @@ async function addArchive() {
|
||||
set('home-invite-team-info', { teamId: teamId.value })
|
||||
if (res && res.success) {
|
||||
uni.$emit('reloadTeamCustomers')
|
||||
getTeam(corpId.value, teamId.value, res.data.id);
|
||||
// getTeam(corpId.value, teamId.value, res.data.id);
|
||||
if (healthTypes.value.length) {
|
||||
const nextType = healthTypes.value[0];
|
||||
const nextTypes = healthTypes.value.slice(1);
|
||||
const url = `/pages/health/record?type=${nextType}&teamId=${teamId.value}&corpId=${corpId.value}&customerId=${res.data.id}&nextTypes=${nextTypes.join(',')}&source=afterArchive`
|
||||
uni.redirectTo({ url });
|
||||
} else {
|
||||
uni.redirectTo({
|
||||
url: `/pages/archive/archive-result?corpId=${corpId.value}&teamId=${teamId.value}&customerId=${res.data.id}`
|
||||
})
|
||||
}
|
||||
} else {
|
||||
toast(res?.message || '新增档案失败');
|
||||
}
|
||||
@ -205,6 +216,7 @@ async function init() {
|
||||
visible.value = true;
|
||||
}
|
||||
getExternalUserId(corpId.value);
|
||||
getTeam(corpId.value, teamId.value)
|
||||
}
|
||||
await getBaseForm();
|
||||
if (!customerId.value) {
|
||||
@ -285,18 +297,18 @@ async function getTeam(corpId, teamId, customerId) {
|
||||
const team = res.data;
|
||||
const qrcode = team && Array.isArray(team.qrcodes) ? team.qrcodes[0] : null;
|
||||
const healthTempList = qrcode && Array.isArray(qrcode.healthTempList) ? qrcode.healthTempList : [];
|
||||
const types = healthTempList.filter(i => typeof i.templateType === 'string' && i.templateType.trim() && i.archiveRecommend === true).map(i => i.templateType);
|
||||
if (types.length && customerId) {
|
||||
const nextType = types[0];
|
||||
const nextTypes = types.slice(1);
|
||||
const url = `/pages/health/record?type=${nextType}&teamId=${teamId}&corpId=${corpId}&customerId=${customerId}&nextTypes=${nextTypes.join(',')}&source=afterArchive`
|
||||
uni.redirectTo({ url });
|
||||
return
|
||||
}
|
||||
healthTypes.value = healthTempList.filter(i => typeof i.templateType === 'string' && i.templateType.trim() && i.archiveRecommend === true).map(i => i.templateType);
|
||||
// if (types.length && customerId) {
|
||||
// const nextType = types[0];
|
||||
// const nextTypes = types.slice(1);
|
||||
// const url = `/pages/health/record?type=${nextType}&teamId=${teamId}&corpId=${corpId}&customerId=${customerId}&nextTypes=${nextTypes.join(',')}&source=afterArchive`
|
||||
// uni.redirectTo({ url });
|
||||
// return
|
||||
// }
|
||||
}
|
||||
uni.redirectTo({
|
||||
url: `/pages/archive/archive-result?corpId=${corpId}&teamId=${teamId}&customerId=${customerId}`
|
||||
})
|
||||
// uni.redirectTo({
|
||||
// url: `/pages/archive/archive-result?corpId=${corpId}&teamId=${teamId}&customerId=${customerId}`
|
||||
// })
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<view class="flex items-center py-12 px-15">
|
||||
<view class="min-w-90 flex items-center bg-white rounded-sm px-10 mr-5" @click="selectType()">
|
||||
<view class="leading-normal text-base py-5 px-10 text-dark mr-5">
|
||||
{{ tempType[type] || '全部' }}
|
||||
{{ selectedTypeLabel }}
|
||||
</view>
|
||||
<uni-icons type="down" size="16" color="#666" />
|
||||
</view>
|
||||
@ -36,12 +36,11 @@
|
||||
<view class="text-lg font-semibold text-dark mr-5">
|
||||
{{ i.date }}
|
||||
</view>
|
||||
<view v-if="i.medicalType === 'outpatient'"
|
||||
class="mr-5 px-10 leading-normal text-white text-base bg-warning rounded-full">门诊信息</view>
|
||||
<view v-else-if="i.medicalType === 'inhospital'"
|
||||
class="mr-5 px-10 leading-normal text-white text-base bg-success rounded-full">住院信息</view>
|
||||
<view v-if="i.medicalType === 'physicalExaminationTemplate'"
|
||||
class="mr-5 px-10 leading-normal text-white text-base bg-danger rounded-full">体检报告</view>
|
||||
<view v-if="getTemplateLabel(i.medicalType)"
|
||||
class="mr-5 px-10 leading-normal text-white text-base rounded-full"
|
||||
:class="getTemplateTagClass(i.medicalType)">
|
||||
{{ getTemplateLabel(i.medicalType) }}
|
||||
</view>
|
||||
<view v-if="i.corp === '其他'" class="px-10 leading-normal text-white text-base bg-danger rounded-full">
|
||||
外院
|
||||
</view>
|
||||
@ -81,9 +80,25 @@
|
||||
</view>
|
||||
</view>
|
||||
<template #footer>
|
||||
<button-footer v-if="healthTempList.length" confirmText="+新增健康档案" :showCancel="false" @confirm="addArchive()" />
|
||||
<button-footer v-if="enabledTemplateCount" confirmText="+新增健康档案" :showCancel="false" @confirm="addArchive()" />
|
||||
</template>
|
||||
</full-page>
|
||||
<uni-popup ref="templatePopup" type="bottom" :safe-area="false">
|
||||
<view class="template-popup">
|
||||
<view class="template-popup-header">
|
||||
<view class="template-popup-title">{{ templateSelectorTitle }}</view>
|
||||
<view class="template-popup-close" @click="closeTemplateSelector()">取消</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="template-popup-list">
|
||||
<view v-for="item in templateSelectorItems" :key="item.value" class="template-popup-item"
|
||||
@click="selectTemplateItem(item)">
|
||||
<view class="template-popup-item-label">{{ item.label }}</view>
|
||||
<uni-icons v-if="templateSelectorMode === 'filter' && type === item.value" type="checkmarkempty" size="18"
|
||||
color="#0074ff" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed, ref, watch } from 'vue';
|
||||
@ -96,11 +111,7 @@ import EmptyData from '@/components/empty-data.vue';
|
||||
import FullPage from '@/components/full-page.vue';
|
||||
import { toast } from '../../utils/widget';
|
||||
|
||||
const tempType = {
|
||||
outpatient: '门诊信息',
|
||||
inhospital: '住院信息',
|
||||
physicalExaminationTemplate: '体检报告'
|
||||
}
|
||||
const templateTagClasses = ['bg-warning', 'bg-success', 'bg-danger', 'bg-primary'];
|
||||
const empty = ref(false)
|
||||
const { useLoad, useShow } = useGuard();
|
||||
const corpId = ref('');
|
||||
@ -108,43 +119,94 @@ const customerId = ref('');
|
||||
const dates = ref([])
|
||||
const list = ref([]);
|
||||
const name = ref('');
|
||||
const team = ref(null);
|
||||
const type = ref('all');
|
||||
const teamId = ref('');
|
||||
const page = ref(1);
|
||||
const more = ref(false)
|
||||
const loading = ref(false);
|
||||
const qrcode = computed(() => team.value && Array.isArray(team.value.qrcodes) ? team.value.qrcodes[0] : null)
|
||||
const healthTempList = computed(() => qrcode.value && Array.isArray(qrcode.value.healthTempList) ? qrcode.value.healthTempList.map(i => ({ enable: i.enable, label: tempType[i.templateType], value: i.templateType })).filter(i => i.label && i.enable) : [])
|
||||
const tempShowField = ref(null);
|
||||
|
||||
const config = {
|
||||
outpatient: ["corp", "deptName", "doctor", "diagnosisName", "files"],
|
||||
inhospital: ["corp", "diagnosisName", "operation", "operationDate", "outhosDate", "files"],
|
||||
physicalExaminationTemplate: ['inspectPakageName']
|
||||
};
|
||||
|
||||
function addArchive() {
|
||||
if (healthTempList.value.length > 1) {
|
||||
uni.showActionSheet({
|
||||
title: '选择新增档案类型',
|
||||
itemList: healthTempList.value.map(i => i.label),
|
||||
success: function (res) {
|
||||
toRecord(healthTempList.value[res.tapIndex].value)
|
||||
const teamHealthTemplates = ref([]);
|
||||
const templatePopup = ref(null);
|
||||
const templateSelectorItems = ref([]);
|
||||
const templateSelectorMode = ref('add');
|
||||
const healthTempList = computed(() => {
|
||||
return teamHealthTemplates.value
|
||||
.map(i => {
|
||||
const value = typeof i.templateType === 'string' ? i.templateType.trim() : '';
|
||||
return {
|
||||
...i,
|
||||
value,
|
||||
label: getTemplateLabel(value, i),
|
||||
}
|
||||
});
|
||||
} else {
|
||||
toRecord(healthTempList.value[0].value)
|
||||
})
|
||||
.filter(i => i.value && i.enable && i.label);
|
||||
})
|
||||
const enabledTemplateCount = computed(() => teamHealthTemplates.value.filter(i => i && i.enable && i.templateType).length);
|
||||
const selectedTypeLabel = computed(() => type.value === 'all' ? '全部' : getTemplateLabel(type.value) || '全部');
|
||||
const templateSelectorTitle = computed(() => templateSelectorMode.value === 'filter' ? '选择档案类型' : '选择新增档案类型');
|
||||
const tempShowField = ref(null);
|
||||
const tempMeta = ref({});
|
||||
|
||||
function getTemplateLabel(templateType, config = {}) {
|
||||
if (!templateType) return '';
|
||||
const meta = tempMeta.value && tempMeta.value[templateType] ? tempMeta.value[templateType] : {};
|
||||
return config.name || config.templateName || config.templateTypeName || config.label || meta.name || '';
|
||||
}
|
||||
|
||||
function getTemplateTagClass(templateType) {
|
||||
const index = healthTempList.value.findIndex(i => i.value === templateType);
|
||||
return templateTagClasses[index >= 0 ? index % templateTagClasses.length : templateTagClasses.length - 1];
|
||||
}
|
||||
|
||||
function getTemplateTitleList(templateType, data) {
|
||||
const template = healthTempList.value.find(i => i.value === templateType);
|
||||
const titleList = template && Array.isArray(template.titleList) ? template.titleList.filter(Boolean) : [];
|
||||
if (data.corp === '其他') {
|
||||
return ['corpName', ...titleList.filter(i => i !== 'corp' && i !== 'corpName')];
|
||||
}
|
||||
return titleList;
|
||||
}
|
||||
|
||||
async function addArchive() {
|
||||
if (!teamHealthTemplates.value.length) {
|
||||
await getTeamHealthTemps();
|
||||
}
|
||||
const templates = healthTempList.value;
|
||||
if (!templates.length) {
|
||||
toast('未查询到启用的健康档案模板名称');
|
||||
return;
|
||||
}
|
||||
if (templates.length === 1) {
|
||||
toRecord(templates[0].value)
|
||||
return;
|
||||
}
|
||||
openTemplateSelector('add', templates);
|
||||
}
|
||||
|
||||
function openTemplateSelector(mode, items) {
|
||||
templateSelectorMode.value = mode;
|
||||
templateSelectorItems.value = items;
|
||||
templatePopup.value && templatePopup.value.open();
|
||||
}
|
||||
|
||||
function closeTemplateSelector() {
|
||||
templatePopup.value && templatePopup.value.close();
|
||||
}
|
||||
|
||||
function selectTemplateItem(item) {
|
||||
closeTemplateSelector();
|
||||
if (templateSelectorMode.value === 'add') {
|
||||
toRecord(item.value);
|
||||
return;
|
||||
}
|
||||
type.value = item.value;
|
||||
page.value = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
function getTempRows(type, data) {
|
||||
if (config[type] && tempShowField.value && tempShowField.value[type]) {
|
||||
if (tempShowField.value && tempShowField.value[type]) {
|
||||
const list = [];
|
||||
let titles = config[type];
|
||||
if (data.corp === '其他') {
|
||||
titles = ['corpName', 'diagnosisName', 'files']
|
||||
}
|
||||
const titles = getTemplateTitleList(type, data);
|
||||
titles.forEach(i => {
|
||||
if (tempShowField.value[type][i]) {
|
||||
list.push({ title: i, label: tempShowField.value[type][i], value: data[i], key: `${i}_${data._id}` })
|
||||
@ -169,26 +231,12 @@ function preview(file) {
|
||||
}
|
||||
}
|
||||
|
||||
function selectType() {
|
||||
const itemList = [{ label: '全部', value: 'all' }, ...healthTempList.value]
|
||||
uni.showActionSheet({
|
||||
title: '选择新增档案类型',
|
||||
itemList: itemList.map(i => i.label),
|
||||
success: function (res) {
|
||||
type.value = itemList[res.tapIndex].value;
|
||||
page.value = 1;
|
||||
getList()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function getTeam() {
|
||||
const res = await api('getTeamData', { teamId: teamId.value, corpId: corpId.value });
|
||||
if (res && res.data) {
|
||||
team.value = res.data;
|
||||
} else {
|
||||
toast(res?.message || '获取团队信息失败')
|
||||
async function selectType() {
|
||||
if (!teamHealthTemplates.value.length) {
|
||||
await getTeamHealthTemps();
|
||||
}
|
||||
const itemList = [{ label: '全部', value: 'all' }, ...healthTempList.value]
|
||||
openTemplateSelector('filter', itemList);
|
||||
}
|
||||
|
||||
async function getList() {
|
||||
@ -196,12 +244,20 @@ async function getList() {
|
||||
await getTeamHealthTemps()
|
||||
}
|
||||
if (loading.value) return;
|
||||
const medicalTypes = teamHealthTemplates.value
|
||||
.map(i => typeof i.templateType === 'string' ? i.templateType.trim() : '')
|
||||
.filter(Boolean);
|
||||
if (!medicalTypes.length) {
|
||||
list.value = [];
|
||||
more.value = false;
|
||||
return;
|
||||
}
|
||||
const params = {
|
||||
corpId: corpId.value,
|
||||
memberId: customerId.value,
|
||||
page: page.value,
|
||||
pageSize: 20,
|
||||
medicalType: Object.keys(tempType)
|
||||
medicalType: medicalTypes
|
||||
}
|
||||
if (type.value !== 'all') {
|
||||
params.medicalType = [type.value]
|
||||
@ -228,6 +284,11 @@ async function getTeamHealthTemps() {
|
||||
const res = await api('getTeamHealthTemps', { teamId: teamId.value, corpId: corpId.value });
|
||||
if (res && res.success) {
|
||||
const arr = res && Array.isArray(res.data) ? res.data : [];
|
||||
teamHealthTemplates.value = arr;
|
||||
tempMeta.value = arr.reduce((m, item) => {
|
||||
m[item.templateType] = { name: item.name || '', service: item.service || {} };
|
||||
return m
|
||||
}, {});
|
||||
tempShowField.value = arr.reduce((m, item) => {
|
||||
const templateList = Array.isArray(item.templateList) ? item.templateList : [];
|
||||
const data = {}
|
||||
@ -246,7 +307,6 @@ useLoad(options => {
|
||||
teamId.value = options.teamId;
|
||||
corpId.value = options.corpId;
|
||||
customerId.value = options.id || '';
|
||||
getTeam()
|
||||
// getTeamHealthTemps();
|
||||
})
|
||||
|
||||
@ -283,4 +343,51 @@ watch(dates, n => {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.template-popup {
|
||||
background: #fff;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.template-popup-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 28rpx 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.template-popup-title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.template-popup-close {
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.template-popup-list {
|
||||
max-height: 640rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.template-popup-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 96rpx;
|
||||
padding: 0 32rpx;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
}
|
||||
|
||||
.template-popup-item-label {
|
||||
flex: 1;
|
||||
font-size: 30rpx;
|
||||
color: #222;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -10,7 +10,8 @@
|
||||
</view>
|
||||
|
||||
<template #footer>
|
||||
<button-footer v-if="canEdit" confirmText="保存" :showCancel="false" @confirm="confirm()" />
|
||||
<button-footer v-if="canEdit" :confirmText="nextTypes.length ? '下一步' : '保存'" :showCancel="false"
|
||||
@confirm="confirm()" />
|
||||
</template>
|
||||
</full-page>
|
||||
</template>
|
||||
@ -45,6 +46,7 @@ const timeTitle = ref('');
|
||||
const canEdit = ref(false)
|
||||
const nextTypes = ref([]);
|
||||
const source = ref('');
|
||||
const templateName = ref('');
|
||||
|
||||
const formData = computed(() => ({ ...record.value, ...form.value }));
|
||||
const displayFormItems = computed(() => {
|
||||
@ -84,7 +86,8 @@ async function addHealthRecord() {
|
||||
// teamId: teamId.value,
|
||||
dataSource: 'customerReport',
|
||||
miniAppId: account.value.openid,
|
||||
medicalType: type.value
|
||||
medicalType: type.value,
|
||||
medicalTypeName: templateName.value
|
||||
}
|
||||
if (timeTitle.value) {
|
||||
data.sortTime = data[timeTitle.value] && dayjs(data[timeTitle.value]).isValid() ? dayjs(data[timeTitle.value]).valueOf() : dayjs().valueOf();
|
||||
@ -128,7 +131,8 @@ async function updateHealthRecord() {
|
||||
corpId: corpId.value,
|
||||
memberId: customerId.value,
|
||||
miniAppId: account.value.openid,
|
||||
medicalType: type.value
|
||||
medicalType: type.value,
|
||||
medicalTypeName: templateName.value
|
||||
}
|
||||
if (timeTitle.value) {
|
||||
data.sortTime = formData.value[timeTitle.value] && dayjs(formData.value[timeTitle.value]).isValid() ? dayjs(formData.value[timeTitle.value]).valueOf() : dayjs().valueOf();
|
||||
@ -156,12 +160,19 @@ async function getBaseForm() {
|
||||
if (res && res.success) {
|
||||
formItems.value = Array.isArray(res.data) ? res.data : [];
|
||||
timeTitle.value = typeof res.timeTitle === 'string' ? res.timeTitle : '';
|
||||
templateName.value = typeof res.templateName === 'string' ? res.templateName : '';
|
||||
setPageTitle();
|
||||
} else {
|
||||
toast(res?.message || '查询失败');
|
||||
return Promise.reject()
|
||||
}
|
||||
}
|
||||
|
||||
function setPageTitle() {
|
||||
const action = id.value ? '编辑' : '新增';
|
||||
uni.setNavigationBarTitle({ title: `${action}${templateName.value || '健康档案'}` })
|
||||
}
|
||||
|
||||
async function getRecord() {
|
||||
const res = await api('getMedicalRecordById', {
|
||||
corpId: corpId.value,
|
||||
@ -186,7 +197,7 @@ onLoad(options => {
|
||||
source.value = options.source || '';
|
||||
const nextTypeStr = typeof options.nextTypes === 'string' ? options.nextTypes : '';
|
||||
nextTypes.value = nextTypeStr.split(',');
|
||||
uni.setNavigationBarTitle({ title: id.value ? '编辑健康档案' : '新增健康档案' })
|
||||
setPageTitle();
|
||||
})
|
||||
useLoad(options => {
|
||||
init();
|
||||
@ -197,4 +208,4 @@ useLoad(options => {
|
||||
.disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -83,7 +83,8 @@ const consultItems = ref([
|
||||
]);
|
||||
const hideMenus = computed(() => {
|
||||
const result = {};
|
||||
if (!props.team || !props.team.creator) {
|
||||
// 非医助手团队
|
||||
if (!(props.team && props.team.createSource === 'yzs')) {
|
||||
result.chat = true;
|
||||
}
|
||||
return result;
|
||||
@ -92,7 +93,7 @@ const hideMenus = computed(() => {
|
||||
function handleItemClick(item) {
|
||||
// 聊天咨询需要选择咨询人
|
||||
if (item.needSelectConsultant) {
|
||||
if (!props.team || !props.team.creator) {
|
||||
if (!(props.team && props.team.createSource === 'yzs')) {
|
||||
return toast('该团队暂未开放咨询服务')
|
||||
}
|
||||
|
||||
|
||||
@ -146,7 +146,7 @@ const hasHealthTemp = computed(
|
||||
() =>
|
||||
qrcode.value &&
|
||||
Array.isArray(qrcode.value.healthTempList) &&
|
||||
qrcode.value.healthTempList.length > 0
|
||||
qrcode.value.healthTempList.filter(i => i && i.enable).length > 0
|
||||
);
|
||||
const baseInfo = computed(() =>
|
||||
qrcode.value &&
|
||||
|
||||
@ -140,7 +140,7 @@ onLoad((options) => {
|
||||
if (options.q) {
|
||||
opts.value = JSON.stringify(options)
|
||||
changeTeam(parseInviteOptions(options));
|
||||
} else if (options.type === 'archive') {
|
||||
} else if (options.type === 'archive' || (options.teamId && options.corpId)) {
|
||||
changeTeam(options);
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,9 @@
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import useAccount from '@/store/account';
|
||||
import api from "@/utils/api.js";
|
||||
import { loading, toast, hideLoading } from "@/utils/widget";
|
||||
|
||||
@ -24,6 +26,8 @@ import surveyCover from "./components/survey-cover.vue";
|
||||
import surveyQuestion from "./components/survey-question.vue";
|
||||
import surveyRecord from "./components/survey-record.vue";
|
||||
|
||||
const env = __VITE_ENV__;
|
||||
const appid = env.MP_WX_APP_ID;
|
||||
const corpId = ref('');
|
||||
const surveryId = ref('');
|
||||
const answerId = ref('');
|
||||
@ -32,7 +36,7 @@ const survey = ref(null);
|
||||
const emptyTxt = ref('')
|
||||
const customerName = ref('');
|
||||
const step = ref('cover');
|
||||
|
||||
const { login, getExternalUserId } = useAccount();
|
||||
const readonly = computed(() => survey.value && survey.value.submitTime);
|
||||
const list = computed(() => survey.value && Array.isArray(survey.value.list) ? survey.value.list : []);
|
||||
const showList = computed(() => {
|
||||
@ -80,7 +84,8 @@ async function init() {
|
||||
async function getAnswerRecord() {
|
||||
const res = await api('getAnswer', { corpId: corpId.value, surveryId: surveryId.value, answerId: answerId.value, memberId: memberId.value });
|
||||
if (res && res.success) {
|
||||
return res.record
|
||||
relateWxappp(res.record)
|
||||
return res.record;
|
||||
}
|
||||
return Promise.reject();
|
||||
}
|
||||
@ -108,17 +113,34 @@ async function submit({ list, score }) {
|
||||
}
|
||||
}
|
||||
|
||||
async function relateWxappp(record) {
|
||||
const { teamId, corpId, memberId } = record || {};
|
||||
if (!(teamId && corpId && memberId)) return;
|
||||
const account = await login();
|
||||
const externalUserId = await getExternalUserId(corpId);
|
||||
if (!externalUserId) return;
|
||||
const res = await api('relateWxappTeamByExternalUserId', {
|
||||
appid,
|
||||
openid: account.openid,
|
||||
teamId: teamId,
|
||||
corpId: corpId,
|
||||
memberId: memberId,
|
||||
externalUserId: externalUserId,
|
||||
})
|
||||
console.clear()
|
||||
console.log(res)
|
||||
}
|
||||
|
||||
onLoad(opts => {
|
||||
corpId.value = opts.corpId;
|
||||
surveryId.value = opts.surveryId;
|
||||
answerId.value = opts.answerId;
|
||||
memberId.value = opts.memberId;
|
||||
customerName.value = opts.name;
|
||||
customerName.value = decodeURIComponent(decodeURIComponent(opts.name || ''));
|
||||
init();
|
||||
})
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@ -96,6 +96,7 @@ const teammate = computed(() => {
|
||||
|
||||
const friendlyMember = computed(() => {
|
||||
const friendlyMembers = team.value && Array.isArray(team.value.friendlyMembers) ? team.value.friendlyMembers : [];
|
||||
debugger
|
||||
return friendlyMembers.reduce((data, item) => {
|
||||
data[item] = true;
|
||||
return data
|
||||
|
||||
@ -157,6 +157,7 @@ export default defineStore("accountStore", () => {
|
||||
const res = await api('getUnionidToExternalUserid', { unionid, openid, corpId }, false);
|
||||
const id = res && res.success && typeof res.data === 'string' && res.data.trim() ? res.data.trim() : '';
|
||||
externalUserId.value = id;
|
||||
return id;
|
||||
}
|
||||
|
||||
watch(hasImCorpId, n => {
|
||||
|
||||
137
utils/api-base-config.js
Normal file
137
utils/api-base-config.js
Normal file
@ -0,0 +1,137 @@
|
||||
const env = __VITE_ENV__;
|
||||
|
||||
export const API_CONTEXT_CACHE_KEY = "ykt_team_api_context";
|
||||
|
||||
export const CORP_API_BASE_URL_MAP = {
|
||||
wwa54dfba0b5441ef1: "https://crm.gykqyy.com/ykt/",
|
||||
};
|
||||
|
||||
export const CORP_ID_ALIAS_MAP = {
|
||||
"wpLgjyawAAeRkCPQMp9-z5q-xEzK64nA": "wwa54dfba0b5441ef1",
|
||||
};
|
||||
|
||||
function normalizeBaseUrl(url) {
|
||||
return String(url || "").replace(/\/+$/, "");
|
||||
}
|
||||
|
||||
function getDefaultBaseUrl() {
|
||||
return normalizeBaseUrl(env.MP_API_BASE_URL);
|
||||
}
|
||||
|
||||
export function normalizeCorpId(corpId) {
|
||||
const normalizedCorpId = String(corpId || "").trim();
|
||||
return CORP_ID_ALIAS_MAP[normalizedCorpId] || normalizedCorpId;
|
||||
}
|
||||
|
||||
function readCachedContext() {
|
||||
if (typeof uni === "undefined" || typeof uni.getStorageSync !== "function") {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const cached = uni.getStorageSync(API_CONTEXT_CACHE_KEY);
|
||||
if (!cached || typeof cached !== "object" || !cached.baseUrl) return null;
|
||||
return {
|
||||
corpId: cached.corpId || "",
|
||||
baseUrl: normalizeBaseUrl(cached.baseUrl),
|
||||
};
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function writeCachedContext(context) {
|
||||
if (typeof uni === "undefined" || typeof uni.setStorageSync !== "function") {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
uni.setStorageSync(API_CONTEXT_CACHE_KEY, {
|
||||
corpId: context.corpId || "",
|
||||
baseUrl: normalizeBaseUrl(context.baseUrl),
|
||||
});
|
||||
} catch (error) {
|
||||
// 缓存失败不能阻断接口请求。
|
||||
}
|
||||
}
|
||||
|
||||
function createContext(corpId, baseUrl) {
|
||||
return {
|
||||
corpId: corpId || "",
|
||||
baseUrl: normalizeBaseUrl(baseUrl),
|
||||
};
|
||||
}
|
||||
|
||||
function safeDecode(value) {
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
} catch (error) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function parseQueryString(queryString) {
|
||||
return String(queryString || "")
|
||||
.replace(/^[^?]*\?/, "")
|
||||
.split("&")
|
||||
.reduce((acc, item) => {
|
||||
if (!item) return acc;
|
||||
const [key, ...valueParts] = item.split("=");
|
||||
if (!key) return acc;
|
||||
acc[safeDecode(key)] = safeDecode(valueParts.join("=") || "");
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
export function getCorpIdFromAppOptions(options = {}) {
|
||||
const query = options.query || options || {};
|
||||
const corpId = query.corpId || query.corpid || query.corp_id;
|
||||
if (corpId) return normalizeCorpId(corpId);
|
||||
|
||||
if (typeof query.q === "string") {
|
||||
const qParams = parseQueryString(safeDecode(query.q));
|
||||
const qCorpId = qParams.corpId || qParams.corpid || qParams.corp_id;
|
||||
if (qCorpId) return normalizeCorpId(qCorpId);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
export function initApiContextFromAppOptions(options = {}) {
|
||||
const corpId = getCorpIdFromAppOptions(options);
|
||||
if (!corpId) return null;
|
||||
return resolveApiContext(corpId);
|
||||
}
|
||||
|
||||
export function resolveApiContext(corpId) {
|
||||
const normalizedCorpId = normalizeCorpId(corpId);
|
||||
|
||||
if (normalizedCorpId) {
|
||||
const configuredBaseUrl = CORP_API_BASE_URL_MAP[normalizedCorpId];
|
||||
const context = createContext(
|
||||
normalizedCorpId,
|
||||
configuredBaseUrl || getDefaultBaseUrl()
|
||||
);
|
||||
writeCachedContext(context);
|
||||
return context;
|
||||
}
|
||||
|
||||
const cachedContext = readCachedContext();
|
||||
if (cachedContext) return cachedContext;
|
||||
|
||||
const context = createContext("", getDefaultBaseUrl());
|
||||
writeCachedContext(context);
|
||||
return context;
|
||||
}
|
||||
|
||||
export function getApiBaseUrlByCorpId(corpId) {
|
||||
return resolveApiContext(corpId).baseUrl;
|
||||
}
|
||||
|
||||
export function getDefaultUploadUrl() {
|
||||
return `${getDefaultBaseUrl()}/upload`;
|
||||
}
|
||||
|
||||
export function buildApiUrl(path, corpId) {
|
||||
const { baseUrl } = resolveApiContext(corpId);
|
||||
const normalizedPath = String(path || "").replace(/^\/+/, "");
|
||||
return normalizedPath ? `${baseUrl}/${normalizedPath}` : baseUrl;
|
||||
}
|
||||
@ -14,7 +14,8 @@ const urlsConfig = {
|
||||
getWxappRelateTeams: 'getWxappRelateTeams',
|
||||
getTeamMemberAvatarsAndName: "getTeamMemberAvatarsAndName",
|
||||
getMiniAppHomeStats: "getMiniAppHomeStats",
|
||||
getResponsiblePerson: 'getTeamResponsiblePerson'
|
||||
getResponsiblePerson: 'getTeamResponsiblePerson',
|
||||
relateWxappTeamByExternalUserId: 'relateWxappTeamByExternalUserId'
|
||||
},
|
||||
|
||||
knowledgeBase: {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { loading, hideLoading } from "./widget";
|
||||
const env = __VITE_ENV__;
|
||||
const baseUrl = env.MP_API_BASE_URL;
|
||||
import { buildApiUrl, getDefaultUploadUrl, normalizeCorpId } from "./api-base-config";
|
||||
|
||||
const defaultOptions = {
|
||||
header: {
|
||||
@ -58,7 +57,7 @@ async function refreshAccessToken() {
|
||||
|
||||
try {
|
||||
const res = await uni.request({
|
||||
url: `${baseUrl}/auth/refresh`,
|
||||
url: buildApiUrl("/auth/refresh"),
|
||||
method: "POST",
|
||||
header: {
|
||||
"Content-Type": "application/json",
|
||||
@ -97,11 +96,17 @@ async function refreshAccessToken() {
|
||||
const request = async (options = {}, showLoading = true) => {
|
||||
// 合并用户传入的配置和默认配置
|
||||
if (!options.data) options.data = {};
|
||||
if (options.data.corpId) {
|
||||
options.data = {
|
||||
...options.data,
|
||||
corpId: normalizeCorpId(options.data.corpId),
|
||||
};
|
||||
}
|
||||
|
||||
const config = {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
url: baseUrl + options.url,
|
||||
url: buildApiUrl(options.url, options.data.corpId),
|
||||
};
|
||||
|
||||
// 添加 token 到请求头
|
||||
@ -199,24 +204,26 @@ function removeTask(task) {
|
||||
|
||||
export default request;
|
||||
|
||||
export const uploadUrl = `${baseUrl}/upload`;
|
||||
export const uploadUrl = getDefaultUploadUrl();
|
||||
|
||||
export function getFullPath(path) {
|
||||
return `${baseUrl}/${path}`;
|
||||
export function getFullPath(path, corpId) {
|
||||
return buildApiUrl(path, normalizeCorpId(corpId));
|
||||
}
|
||||
|
||||
|
||||
export function upload(path) {
|
||||
export function upload(path, corpId) {
|
||||
const normalizedCorpId = normalizeCorpId(corpId);
|
||||
const currentUploadUrl = buildApiUrl("/upload", normalizedCorpId);
|
||||
return new Promise((resolve) => {
|
||||
uni.uploadFile({
|
||||
url: uploadUrl, // 替换为你的上传接口地址
|
||||
url: currentUploadUrl,
|
||||
filePath: path,
|
||||
name: 'file',
|
||||
fileType: 'image',
|
||||
success: (res) => {
|
||||
try {
|
||||
const url = JSON.parse(res.data).filePath;
|
||||
resolve(url ? getFullPath(url) : '')
|
||||
resolve(url ? getFullPath(url, normalizedCorpId) : '')
|
||||
} catch (e) {
|
||||
resolve()
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user