2026-06-03 18:47:12 +08:00

394 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<full-page :customScroll="empty">
<template #header>
<view class="flex items-center bg-white text-base px-15 py-12">
<view class="flex-shrink-0 mr-5 text-gray">档案所属人</view>
<view class="text-dark">{{ name }}</view>
</view>
<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">
{{ selectedTypeLabel }}
</view>
<uni-icons type="down" size="16" color="#666" />
</view>
<view class="w-100 flex items-center bg-white rounded-sm mr-5">
<uni-datetime-picker v-model="dates" type="daterange">
<view class="flex items-center rounded-sm mr-5 px-10 bg-white">
<view class="flex-grow w-0 text-dark truncate leading-normal text-base py-5 mr-5">
{{ dates.length ? dates.join(' ~ ') : '时间筛选' }}
</view>
<uni-icons type="down" size="16" color="#666" />
</view>
</uni-datetime-picker>
</view>
<view class="flex-grow"></view>
</view>
</template>
<view v-if="list.length === 0" class="flex items-center justify-center h-full">
<empty-data />
</view>
<view v-else class="px-15 pb-15">
<!-- v-for="customer in list" :key="customer._id" -->
<view v-for="i in list" :key="i._id" class="bg-white rounded shadow-lg mb-10"
@click="toRecord(i.medicalType, i._id)">
<view class="flex items-center py-12 px-15">
<view class="text-lg font-semibold text-dark mr-5">
{{ i.date }}
</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>
<view class="flex-grow"></view>
<view class="flex items-center text-base text-primary">
<view class="mr-5">查看详情</view>
<uni-icons type="right" :size="14" color="#0074ff" />
</view>
</view>
<view v-if="i.rows.length" class="px-15 border-b">
<view v-for="row in i.rows" :key="row.key" class="flex leading-normal mb-10">
<view class="flex-shrink-0 mr-5 min-w-90 text-base text-gray">{{ row.label }}</view>
<view v-if="row.title === 'diagnosisName'" class="w-0 flex-grow text-base text-dark">
{{ row.value && row.value.join ? row.value.join(', ') : '' }}
</view>
<view v-else-if="row.title === 'files'" class="w-0 flex-grow text-base text-dark">
<view v-if="row.value && row.value.length" class="w-full flex flex-wrap">
<image v-for="file in row.value" :src="file.url" class="file-icon" @click.stop="preview(file)" />
</view>
</view>
<view v-else class="w-0 flex-grow text-base text-dark">
{{ row.value }}
</view>
</view>
<!-- <view class="flex leading-normal mb-10">
<view class="flex-shrink-0 mr-5 w-90 text-base text-gray">临床诊断</view>
<view class="w-0 flex-grow text-base text-dark">龋齿</view>
</view>
<view class="flex leading-normal mb-10">
<view class="flex-shrink-0 mr-5 w-90 text-base text-gray">临床诊断</view>
<view class="w-0 flex-grow text-base text-dark">龋齿</view>
</view> -->
</view>
<view v-if="i.dataSource === 'customerReport'" class="px-15 py-12 text-base text-dark">
记录时间{{ i.createTime }} 记录人自己
</view>
</view>
</view>
<template #footer>
<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';
import dayjs from 'dayjs';
import useGuard from '@/hooks/useGuard';
import api from '@/utils/api';
import ButtonFooter from '@/components/button-footer.vue';
import EmptyData from '@/components/empty-data.vue';
import FullPage from '@/components/full-page.vue';
import { toast } from '../../utils/widget';
const templateTagClasses = ['bg-warning', 'bg-success', 'bg-danger', 'bg-primary'];
const empty = ref(false)
const { useLoad, useShow } = useGuard();
const corpId = ref('');
const customerId = ref('');
const dates = ref([])
const list = ref([]);
const name = ref('');
const type = ref('all');
const teamId = ref('');
const page = ref(1);
const more = ref(false)
const loading = ref(false);
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),
}
})
.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 (tempShowField.value && tempShowField.value[type]) {
const list = [];
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}` })
}
})
return list;
}
return []
}
function toRecord(type, id = '') {
uni.navigateTo({
url: `/pages/health/record?type=${type}&teamId=${teamId.value}&corpId=${corpId.value}&id=${id}&customerId=${customerId.value}`
})
}
function preview(file) {
if (/image/i.test(file.type)) {
uni.previewImage({
urls: [file.url]
})
}
}
async function selectType() {
if (!teamHealthTemplates.value.length) {
await getTeamHealthTemps();
}
const itemList = [{ label: '全部', value: 'all' }, ...healthTempList.value]
openTemplateSelector('filter', itemList);
}
async function getList() {
if (!tempShowField.value) {
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: medicalTypes
}
if (type.value !== 'all') {
params.medicalType = [type.value]
}
if (dates.value.length) {
params.startTime = dayjs(dates.value[0]).valueOf();
params.endTime = dayjs(dates.value[1]).valueOf();
}
loading.value = true;
const res = await api('getCustomerMedicalRecord', params);
loading.value = false;
const arr = res && Array.isArray(res.list) ? res.list.map(i => ({
...i,
date: i.sortTime && dayjs(i.sortTime).isValid ? dayjs(i.sortTime).format('YYYY-MM-DD') : '',
createTime: i.createTime && dayjs(i.createTime).isValid ? dayjs(i.createTime).format('YYYY-MM-DD HH:mm') : '',
rows: getTempRows(i.medicalType, i)
})) : [];
list.value = page.value === 1 ? arr : [...list.value, ...arr];
more.value = page.value < res.pages;
console.log(list.value)
}
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 = {}
templateList.forEach(i => (data[i.title] = i.name));
m[item.templateType] = data
return m
}, {})
} else {
toast(res?.message || '获取团队健康档案模板失败');
return Promise.reject()
}
}
useLoad(options => {
name.value = decodeURIComponent(options.name || '');
teamId.value = options.teamId;
corpId.value = options.corpId;
customerId.value = options.id || '';
// getTeamHealthTemps();
})
useShow(() => {
page.value = 1;
getList()
})
watch(dates, n => {
page.value = 1;
getList()
})
</script>
<style>
.min-w-90 {
min-width: 180rpx;
}
.w-90 {
width: 160rpx;
}
.w-100 {
width: 240rpx;
}
.whitespace-nowrap {
white-space: nowrap;
}
.file-icon {
margin-right: 10rpx;
margin-bottom: 10rpx;
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>