Compare commits

..

No commits in common. "main" and "dev-建档流程优化" have entirely different histories.

15 changed files with 98 additions and 470 deletions

View File

@ -2,18 +2,15 @@
import dbStore from "@/store/db"; import dbStore from "@/store/db";
import accountStore from "@/store/account"; import accountStore from "@/store/account";
import { globalUnreadListenerManager } from "@/utils/global-unread-listener.js"; import { globalUnreadListenerManager } from "@/utils/global-unread-listener.js";
import { initApiContextFromAppOptions } from "@/utils/api-base-config";
export default { export default {
async onLaunch(options) { async onLaunch() {
initApiContextFromAppOptions(options);
console.log("App Launch: "); console.log("App Launch: ");
// openId IM // openId IM
// await this.initIMOnLaunch(); // await this.initIMOnLaunch();
}, },
onShow: function (options) { onShow: function () {
initApiContextFromAppOptions(options);
const db = dbStore(); const db = dbStore();
if (db && typeof db.getJobs === "function") { if (db && typeof db.getJobs === "function") {
db.getJobs(); db.getJobs();

View File

@ -1,69 +0,0 @@
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}`;
}

View File

@ -8,7 +8,7 @@
<script setup> <script setup>
import { computed, provide, ref, watch } from 'vue'; import { computed, provide, ref, watch } from 'vue';
import verifyForm from './verify.js'; import verifyForm from './verify.js';
import { collectAutoFillChanges } from './auto-fill.js'; import { collectAutoFillChanges } from './auto-fill.mjs';
import FormCell from './form-cell/index.vue'; import FormCell from './form-cell/index.vue';
// import CustomCell from './custom-cell/index.vue'; // import CustomCell from './custom-cell/index.vue';

View File

@ -10,7 +10,7 @@
</view> </view>
</view> </view>
<template #footer> <template #footer>
<button-footer :showCancel="customerId ? true : false" cancelText="删除" :confirmText="healthTypes.length?'下一步':'保存'" @cancel="unBindArchive()" <button-footer :showCancel="customerId ? true : false" cancelText="删除" confirmText="保存" @cancel="unBindArchive()"
@confirm="confirm()" /> @confirm="confirm()" />
</template> </template>
</full-page> </full-page>
@ -57,7 +57,6 @@ const tempRef = ref(null);
const verifyVisible = ref(false); const verifyVisible = ref(false);
const visible = ref(false); const visible = ref(false);
const referenceCustomer = ref(null) const referenceCustomer = ref(null)
const healthTypes = ref([]);
const formData = computed(() => { const formData = computed(() => {
return { ...customer.value, ...form.value, mobile: account.value?.mobile } return { ...customer.value, ...form.value, mobile: account.value?.mobile }
@ -165,17 +164,7 @@ async function addArchive() {
set('home-invite-team-info', { teamId: teamId.value }) set('home-invite-team-info', { teamId: teamId.value })
if (res && res.success) { if (res && res.success) {
uni.$emit('reloadTeamCustomers') 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 { } else {
toast(res?.message || '新增档案失败'); toast(res?.message || '新增档案失败');
} }
@ -216,7 +205,6 @@ async function init() {
visible.value = true; visible.value = true;
} }
getExternalUserId(corpId.value); getExternalUserId(corpId.value);
getTeam(corpId.value, teamId.value)
} }
await getBaseForm(); await getBaseForm();
if (!customerId.value) { if (!customerId.value) {
@ -297,18 +285,18 @@ async function getTeam(corpId, teamId, customerId) {
const team = res.data; const team = res.data;
const qrcode = team && Array.isArray(team.qrcodes) ? team.qrcodes[0] : null; const qrcode = team && Array.isArray(team.qrcodes) ? team.qrcodes[0] : null;
const healthTempList = qrcode && Array.isArray(qrcode.healthTempList) ? qrcode.healthTempList : []; const healthTempList = qrcode && Array.isArray(qrcode.healthTempList) ? qrcode.healthTempList : [];
healthTypes.value = healthTempList.filter(i => typeof i.templateType === 'string' && i.templateType.trim() && i.archiveRecommend === true).map(i => i.templateType); const types = healthTempList.filter(i => typeof i.templateType === 'string' && i.templateType.trim() && i.archiveRecommend === true).map(i => i.templateType);
// if (types.length && customerId) { if (types.length && customerId) {
// const nextType = types[0]; const nextType = types[0];
// const nextTypes = types.slice(1); const nextTypes = types.slice(1);
// const url = `/pages/health/record?type=${nextType}&teamId=${teamId}&corpId=${corpId}&customerId=${customerId}&nextTypes=${nextTypes.join(',')}&source=afterArchive` const url = `/pages/health/record?type=${nextType}&teamId=${teamId}&corpId=${corpId}&customerId=${customerId}&nextTypes=${nextTypes.join(',')}&source=afterArchive`
// uni.redirectTo({ url }); uni.redirectTo({ url });
// return 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}`
})
} }

View File

@ -8,7 +8,7 @@
<view class="flex items-center py-12 px-15"> <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="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"> <view class="leading-normal text-base py-5 px-10 text-dark mr-5">
{{ selectedTypeLabel }} {{ tempType[type] || '全部' }}
</view> </view>
<uni-icons type="down" size="16" color="#666" /> <uni-icons type="down" size="16" color="#666" />
</view> </view>
@ -36,11 +36,12 @@
<view class="text-lg font-semibold text-dark mr-5"> <view class="text-lg font-semibold text-dark mr-5">
{{ i.date }} {{ i.date }}
</view> </view>
<view v-if="getTemplateLabel(i.medicalType)" <view v-if="i.medicalType === 'outpatient'"
class="mr-5 px-10 leading-normal text-white text-base rounded-full" class="mr-5 px-10 leading-normal text-white text-base bg-warning rounded-full">门诊信息</view>
:class="getTemplateTagClass(i.medicalType)"> <view v-else-if="i.medicalType === 'inhospital'"
{{ getTemplateLabel(i.medicalType) }} class="mr-5 px-10 leading-normal text-white text-base bg-success rounded-full">住院信息</view>
</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="i.corp === '其他'" class="px-10 leading-normal text-white text-base bg-danger rounded-full"> <view v-if="i.corp === '其他'" class="px-10 leading-normal text-white text-base bg-danger rounded-full">
外院 外院
</view> </view>
@ -80,25 +81,9 @@
</view> </view>
</view> </view>
<template #footer> <template #footer>
<button-footer v-if="enabledTemplateCount" confirmText="+新增健康档案" :showCancel="false" @confirm="addArchive()" /> <button-footer v-if="healthTempList.length" confirmText="+新增健康档案" :showCancel="false" @confirm="addArchive()" />
</template> </template>
</full-page> </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> </template>
<script setup> <script setup>
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
@ -111,7 +96,11 @@ import EmptyData from '@/components/empty-data.vue';
import FullPage from '@/components/full-page.vue'; import FullPage from '@/components/full-page.vue';
import { toast } from '../../utils/widget'; import { toast } from '../../utils/widget';
const templateTagClasses = ['bg-warning', 'bg-success', 'bg-danger', 'bg-primary']; const tempType = {
outpatient: '门诊信息',
inhospital: '住院信息',
physicalExaminationTemplate: '体检报告'
}
const empty = ref(false) const empty = ref(false)
const { useLoad, useShow } = useGuard(); const { useLoad, useShow } = useGuard();
const corpId = ref(''); const corpId = ref('');
@ -119,94 +108,43 @@ const customerId = ref('');
const dates = ref([]) const dates = ref([])
const list = ref([]); const list = ref([]);
const name = ref(''); const name = ref('');
const team = ref(null);
const type = ref('all'); const type = ref('all');
const teamId = ref(''); const teamId = ref('');
const page = ref(1); const page = ref(1);
const more = ref(false) const more = ref(false)
const loading = ref(false); const loading = ref(false);
const teamHealthTemplates = ref([]); const qrcode = computed(() => team.value && Array.isArray(team.value.qrcodes) ? team.value.qrcodes[0] : null)
const templatePopup = ref(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 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),
}
})
.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 tempShowField = ref(null);
const tempMeta = ref({});
function getTemplateLabel(templateType, config = {}) { const config = {
if (!templateType) return ''; outpatient: ["corp", "deptName", "doctor", "diagnosisName", "files"],
const meta = tempMeta.value && tempMeta.value[templateType] ? tempMeta.value[templateType] : {}; inhospital: ["corp", "diagnosisName", "operation", "operationDate", "outhosDate", "files"],
return config.name || config.templateName || config.templateTypeName || config.label || meta.name || ''; physicalExaminationTemplate: ['inspectPakageName']
} };
function getTemplateTagClass(templateType) { function addArchive() {
const index = healthTempList.value.findIndex(i => i.value === templateType); if (healthTempList.value.length > 1) {
return templateTagClasses[index >= 0 ? index % templateTagClasses.length : templateTagClasses.length - 1]; uni.showActionSheet({
title: '选择新增档案类型',
itemList: healthTempList.value.map(i => i.label),
success: function (res) {
toRecord(healthTempList.value[res.tapIndex].value)
} }
});
function getTemplateTitleList(templateType, data) { } else {
const template = healthTempList.value.find(i => i.value === templateType); toRecord(healthTempList.value[0].value)
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) { function getTempRows(type, data) {
if (tempShowField.value && tempShowField.value[type]) { if (config[type] && tempShowField.value && tempShowField.value[type]) {
const list = []; const list = [];
const titles = getTemplateTitleList(type, data); let titles = config[type];
if (data.corp === '其他') {
titles = ['corpName', 'diagnosisName', 'files']
}
titles.forEach(i => { titles.forEach(i => {
if (tempShowField.value[type][i]) { if (tempShowField.value[type][i]) {
list.push({ title: i, label: tempShowField.value[type][i], value: data[i], key: `${i}_${data._id}` }) list.push({ title: i, label: tempShowField.value[type][i], value: data[i], key: `${i}_${data._id}` })
@ -231,12 +169,26 @@ function preview(file) {
} }
} }
async function selectType() { function selectType() {
if (!teamHealthTemplates.value.length) {
await getTeamHealthTemps();
}
const itemList = [{ label: '全部', value: 'all' }, ...healthTempList.value] const itemList = [{ label: '全部', value: 'all' }, ...healthTempList.value]
openTemplateSelector('filter', itemList); 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 getList() { async function getList() {
@ -244,20 +196,12 @@ async function getList() {
await getTeamHealthTemps() await getTeamHealthTemps()
} }
if (loading.value) return; 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 = { const params = {
corpId: corpId.value, corpId: corpId.value,
memberId: customerId.value, memberId: customerId.value,
page: page.value, page: page.value,
pageSize: 20, pageSize: 20,
medicalType: medicalTypes medicalType: Object.keys(tempType)
} }
if (type.value !== 'all') { if (type.value !== 'all') {
params.medicalType = [type.value] params.medicalType = [type.value]
@ -284,11 +228,6 @@ async function getTeamHealthTemps() {
const res = await api('getTeamHealthTemps', { teamId: teamId.value, corpId: corpId.value }); const res = await api('getTeamHealthTemps', { teamId: teamId.value, corpId: corpId.value });
if (res && res.success) { if (res && res.success) {
const arr = res && Array.isArray(res.data) ? res.data : []; 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) => { tempShowField.value = arr.reduce((m, item) => {
const templateList = Array.isArray(item.templateList) ? item.templateList : []; const templateList = Array.isArray(item.templateList) ? item.templateList : [];
const data = {} const data = {}
@ -307,6 +246,7 @@ useLoad(options => {
teamId.value = options.teamId; teamId.value = options.teamId;
corpId.value = options.corpId; corpId.value = options.corpId;
customerId.value = options.id || ''; customerId.value = options.id || '';
getTeam()
// getTeamHealthTemps(); // getTeamHealthTemps();
}) })
@ -343,51 +283,4 @@ watch(dates, n => {
width: 80rpx; width: 80rpx;
height: 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> </style>

View File

@ -10,8 +10,7 @@
</view> </view>
<template #footer> <template #footer>
<button-footer v-if="canEdit" :confirmText="nextTypes.length ? '下一步' : '保存'" :showCancel="false" <button-footer v-if="canEdit" confirmText="保存" :showCancel="false" @confirm="confirm()" />
@confirm="confirm()" />
</template> </template>
</full-page> </full-page>
</template> </template>
@ -46,7 +45,6 @@ const timeTitle = ref('');
const canEdit = ref(false) const canEdit = ref(false)
const nextTypes = ref([]); const nextTypes = ref([]);
const source = ref(''); const source = ref('');
const templateName = ref('');
const formData = computed(() => ({ ...record.value, ...form.value })); const formData = computed(() => ({ ...record.value, ...form.value }));
const displayFormItems = computed(() => { const displayFormItems = computed(() => {
@ -86,8 +84,7 @@ async function addHealthRecord() {
// teamId: teamId.value, // teamId: teamId.value,
dataSource: 'customerReport', dataSource: 'customerReport',
miniAppId: account.value.openid, miniAppId: account.value.openid,
medicalType: type.value, medicalType: type.value
medicalTypeName: templateName.value
} }
if (timeTitle.value) { if (timeTitle.value) {
data.sortTime = data[timeTitle.value] && dayjs(data[timeTitle.value]).isValid() ? dayjs(data[timeTitle.value]).valueOf() : dayjs().valueOf(); data.sortTime = data[timeTitle.value] && dayjs(data[timeTitle.value]).isValid() ? dayjs(data[timeTitle.value]).valueOf() : dayjs().valueOf();
@ -131,8 +128,7 @@ async function updateHealthRecord() {
corpId: corpId.value, corpId: corpId.value,
memberId: customerId.value, memberId: customerId.value,
miniAppId: account.value.openid, miniAppId: account.value.openid,
medicalType: type.value, medicalType: type.value
medicalTypeName: templateName.value
} }
if (timeTitle.value) { if (timeTitle.value) {
data.sortTime = formData.value[timeTitle.value] && dayjs(formData.value[timeTitle.value]).isValid() ? dayjs(formData.value[timeTitle.value]).valueOf() : dayjs().valueOf(); data.sortTime = formData.value[timeTitle.value] && dayjs(formData.value[timeTitle.value]).isValid() ? dayjs(formData.value[timeTitle.value]).valueOf() : dayjs().valueOf();
@ -160,19 +156,12 @@ async function getBaseForm() {
if (res && res.success) { if (res && res.success) {
formItems.value = Array.isArray(res.data) ? res.data : []; formItems.value = Array.isArray(res.data) ? res.data : [];
timeTitle.value = typeof res.timeTitle === 'string' ? res.timeTitle : ''; timeTitle.value = typeof res.timeTitle === 'string' ? res.timeTitle : '';
templateName.value = typeof res.templateName === 'string' ? res.templateName : '';
setPageTitle();
} else { } else {
toast(res?.message || '查询失败'); toast(res?.message || '查询失败');
return Promise.reject() return Promise.reject()
} }
} }
function setPageTitle() {
const action = id.value ? '编辑' : '新增';
uni.setNavigationBarTitle({ title: `${action}${templateName.value || '健康档案'}` })
}
async function getRecord() { async function getRecord() {
const res = await api('getMedicalRecordById', { const res = await api('getMedicalRecordById', {
corpId: corpId.value, corpId: corpId.value,
@ -197,7 +186,7 @@ onLoad(options => {
source.value = options.source || ''; source.value = options.source || '';
const nextTypeStr = typeof options.nextTypes === 'string' ? options.nextTypes : ''; const nextTypeStr = typeof options.nextTypes === 'string' ? options.nextTypes : '';
nextTypes.value = nextTypeStr.split(','); nextTypes.value = nextTypeStr.split(',');
setPageTitle(); uni.setNavigationBarTitle({ title: id.value ? '编辑健康档案' : '新增健康档案' })
}) })
useLoad(options => { useLoad(options => {
init(); init();

View File

@ -83,8 +83,7 @@ const consultItems = ref([
]); ]);
const hideMenus = computed(() => { const hideMenus = computed(() => {
const result = {}; const result = {};
// if (!props.team || !props.team.creator) {
if (!(props.team && props.team.createSource === 'yzs')) {
result.chat = true; result.chat = true;
} }
return result; return result;
@ -93,7 +92,7 @@ const hideMenus = computed(() => {
function handleItemClick(item) { function handleItemClick(item) {
// //
if (item.needSelectConsultant) { if (item.needSelectConsultant) {
if (!(props.team && props.team.createSource === 'yzs')) { if (!props.team || !props.team.creator) {
return toast('该团队暂未开放咨询服务') return toast('该团队暂未开放咨询服务')
} }

View File

@ -146,7 +146,7 @@ const hasHealthTemp = computed(
() => () =>
qrcode.value && qrcode.value &&
Array.isArray(qrcode.value.healthTempList) && Array.isArray(qrcode.value.healthTempList) &&
qrcode.value.healthTempList.filter(i => i && i.enable).length > 0 qrcode.value.healthTempList.length > 0
); );
const baseInfo = computed(() => const baseInfo = computed(() =>
qrcode.value && qrcode.value &&

View File

@ -140,7 +140,7 @@ onLoad((options) => {
if (options.q) { if (options.q) {
opts.value = JSON.stringify(options) opts.value = JSON.stringify(options)
changeTeam(parseInviteOptions(options)); changeTeam(parseInviteOptions(options));
} else if (options.type === 'archive' || (options.teamId && options.corpId)) { } else if (options.type === 'archive') {
changeTeam(options); changeTeam(options);
} }

View File

@ -15,9 +15,7 @@
<script setup> <script setup>
import { computed, ref } from "vue"; import { computed, ref } from "vue";
import { storeToRefs } from 'pinia';
import { onLoad } from "@dcloudio/uni-app"; import { onLoad } from "@dcloudio/uni-app";
import useAccount from '@/store/account';
import api from "@/utils/api.js"; import api from "@/utils/api.js";
import { loading, toast, hideLoading } from "@/utils/widget"; import { loading, toast, hideLoading } from "@/utils/widget";
@ -26,8 +24,6 @@ import surveyCover from "./components/survey-cover.vue";
import surveyQuestion from "./components/survey-question.vue"; import surveyQuestion from "./components/survey-question.vue";
import surveyRecord from "./components/survey-record.vue"; import surveyRecord from "./components/survey-record.vue";
const env = __VITE_ENV__;
const appid = env.MP_WX_APP_ID;
const corpId = ref(''); const corpId = ref('');
const surveryId = ref(''); const surveryId = ref('');
const answerId = ref(''); const answerId = ref('');
@ -36,7 +32,7 @@ const survey = ref(null);
const emptyTxt = ref('') const emptyTxt = ref('')
const customerName = ref(''); const customerName = ref('');
const step = ref('cover'); const step = ref('cover');
const { login, getExternalUserId } = useAccount();
const readonly = computed(() => survey.value && survey.value.submitTime); const readonly = computed(() => survey.value && survey.value.submitTime);
const list = computed(() => survey.value && Array.isArray(survey.value.list) ? survey.value.list : []); const list = computed(() => survey.value && Array.isArray(survey.value.list) ? survey.value.list : []);
const showList = computed(() => { const showList = computed(() => {
@ -84,8 +80,7 @@ async function init() {
async function getAnswerRecord() { async function getAnswerRecord() {
const res = await api('getAnswer', { corpId: corpId.value, surveryId: surveryId.value, answerId: answerId.value, memberId: memberId.value }); const res = await api('getAnswer', { corpId: corpId.value, surveryId: surveryId.value, answerId: answerId.value, memberId: memberId.value });
if (res && res.success) { if (res && res.success) {
relateWxappp(res.record) return res.record
return res.record;
} }
return Promise.reject(); return Promise.reject();
} }
@ -113,34 +108,17 @@ 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 => { onLoad(opts => {
corpId.value = opts.corpId; corpId.value = opts.corpId;
surveryId.value = opts.surveryId; surveryId.value = opts.surveryId;
answerId.value = opts.answerId; answerId.value = opts.answerId;
memberId.value = opts.memberId; memberId.value = opts.memberId;
customerName.value = decodeURIComponent(decodeURIComponent(opts.name || '')); customerName.value = opts.name;
init(); init();
}) })
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -96,7 +96,6 @@ const teammate = computed(() => {
const friendlyMember = computed(() => { const friendlyMember = computed(() => {
const friendlyMembers = team.value && Array.isArray(team.value.friendlyMembers) ? team.value.friendlyMembers : []; const friendlyMembers = team.value && Array.isArray(team.value.friendlyMembers) ? team.value.friendlyMembers : [];
debugger
return friendlyMembers.reduce((data, item) => { return friendlyMembers.reduce((data, item) => {
data[item] = true; data[item] = true;
return data return data

View File

@ -157,7 +157,6 @@ export default defineStore("accountStore", () => {
const res = await api('getUnionidToExternalUserid', { unionid, openid, corpId }, false); const res = await api('getUnionidToExternalUserid', { unionid, openid, corpId }, false);
const id = res && res.success && typeof res.data === 'string' && res.data.trim() ? res.data.trim() : ''; const id = res && res.success && typeof res.data === 'string' && res.data.trim() ? res.data.trim() : '';
externalUserId.value = id; externalUserId.value = id;
return id;
} }
watch(hasImCorpId, n => { watch(hasImCorpId, n => {

View File

@ -1,137 +0,0 @@
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;
}

View File

@ -14,8 +14,7 @@ const urlsConfig = {
getWxappRelateTeams: 'getWxappRelateTeams', getWxappRelateTeams: 'getWxappRelateTeams',
getTeamMemberAvatarsAndName: "getTeamMemberAvatarsAndName", getTeamMemberAvatarsAndName: "getTeamMemberAvatarsAndName",
getMiniAppHomeStats: "getMiniAppHomeStats", getMiniAppHomeStats: "getMiniAppHomeStats",
getResponsiblePerson: 'getTeamResponsiblePerson', getResponsiblePerson: 'getTeamResponsiblePerson'
relateWxappTeamByExternalUserId: 'relateWxappTeamByExternalUserId'
}, },
knowledgeBase: { knowledgeBase: {

View File

@ -1,5 +1,6 @@
import { loading, hideLoading } from "./widget"; import { loading, hideLoading } from "./widget";
import { buildApiUrl, getDefaultUploadUrl, normalizeCorpId } from "./api-base-config"; const env = __VITE_ENV__;
const baseUrl = env.MP_API_BASE_URL;
const defaultOptions = { const defaultOptions = {
header: { header: {
@ -57,7 +58,7 @@ async function refreshAccessToken() {
try { try {
const res = await uni.request({ const res = await uni.request({
url: buildApiUrl("/auth/refresh"), url: `${baseUrl}/auth/refresh`,
method: "POST", method: "POST",
header: { header: {
"Content-Type": "application/json", "Content-Type": "application/json",
@ -96,17 +97,11 @@ async function refreshAccessToken() {
const request = async (options = {}, showLoading = true) => { const request = async (options = {}, showLoading = true) => {
// 合并用户传入的配置和默认配置 // 合并用户传入的配置和默认配置
if (!options.data) options.data = {}; if (!options.data) options.data = {};
if (options.data.corpId) {
options.data = {
...options.data,
corpId: normalizeCorpId(options.data.corpId),
};
}
const config = { const config = {
...defaultOptions, ...defaultOptions,
...options, ...options,
url: buildApiUrl(options.url, options.data.corpId), url: baseUrl + options.url,
}; };
// 添加 token 到请求头 // 添加 token 到请求头
@ -204,26 +199,24 @@ function removeTask(task) {
export default request; export default request;
export const uploadUrl = getDefaultUploadUrl(); export const uploadUrl = `${baseUrl}/upload`;
export function getFullPath(path, corpId) { export function getFullPath(path) {
return buildApiUrl(path, normalizeCorpId(corpId)); return `${baseUrl}/${path}`;
} }
export function upload(path, corpId) { export function upload(path) {
const normalizedCorpId = normalizeCorpId(corpId);
const currentUploadUrl = buildApiUrl("/upload", normalizedCorpId);
return new Promise((resolve) => { return new Promise((resolve) => {
uni.uploadFile({ uni.uploadFile({
url: currentUploadUrl, url: uploadUrl, // 替换为你的上传接口地址
filePath: path, filePath: path,
name: 'file', name: 'file',
fileType: 'image', fileType: 'image',
success: (res) => { success: (res) => {
try { try {
const url = JSON.parse(res.data).filePath; const url = JSON.parse(res.data).filePath;
resolve(url ? getFullPath(url, normalizedCorpId) : '') resolve(url ? getFullPath(url) : '')
} catch (e) { } catch (e) {
resolve() resolve()
} }