feat: 2.3版本内容开发

1. 健康档案新增体检报告
2. 文件是上传支持pdf
This commit is contained in:
huxuejian 2026-04-10 16:16:25 +08:00
parent acfd0fddbd
commit f8ff13639d
7 changed files with 164 additions and 13 deletions

View File

@ -196,6 +196,10 @@ page {
padding-top: 10rpx;
}
.pt-12 {
padding-top: 24rpx;
}
.pt-15 {
padding-top: 30rpx;
}
@ -251,6 +255,10 @@ page {
margin-bottom: 20rpx;
}
.mt-5 {
margin-top: 10rpx;
}
.mt-10 {
margin-top: 20rpx;
}

View File

@ -0,0 +1,89 @@
<template>
<view class="textarea-row py-12 px-15">
<view class="flex justify-between items-center" @click="addRow()">
<view class="form-row__label text-base">
{{ name || '阳性发现' }}<text v-if="required" class="form-cell--required"></text>
</view>
<view class="pl-5">
<uni-icons type="plus" size="20" color="#0074ff"></uni-icons>
</view>
</view>
<view v-for="(i, idx) in value" :key="idx" class="pt-12" :class="idx > 0 ? 'mt-12 border-t' : ''">
<view class="flex justify-between items-center">
<view class="text-base text-dark">{{ idx + 1 }}阳性发现</view>
<view class="pl-5" @click="remove(idx)">
<uni-icons type="minus" size="20" color="#f87171"></uni-icons>
</view>
</view>
<view class="border p-10 mt-12 rounded-sm">
<textarea v-model="i.category" :auto-height="true" class="w-full h-full"></textarea>
</view>
<view class="text-base mt-12 text-dark">{{ idx + 1 }}处理意见</view>
<view class="border p-10 mt-12 rounded-sm">
<textarea v-model="i.opinion" :auto-height="true" class="w-full h-full"></textarea>
</view>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue';
const emits = defineEmits(['change']);
const props = defineProps({
form: {
type: Object,
default: () => ({})
},
name: {
default: ''
},
required: {
type: Boolean,
default: false
},
title: {
default: ''
},
disableChange: {
type: Boolean,
default: false
}
})
const value = computed(() => Array.isArray(props.form[props.title]) ? props.form[props.title] : [])
function addRow() {
if (props.disableChange) return;
const len = value.value.length;
if (len === 0) {
return change([{ category: '', opinion: '' }])
}
const last = value.value[len - 1];
const category = last.category || '';
const opinion = last.opinion || '';
if (category === '' && opinion === '') {
return;
}
change([...value.value, { category: '', opinion: '' }])
}
function remove(idx) {
if (props.disableChange) return;
change(value.value.filter((i, j) => j !== idx));
}
function change(e) {
emits('change', {
title: props.title,
value: e
})
}
</script>
<style>
@import '../cell-style.css';
.border-t {
border-top: 1px solid #eee;
}
</style>

View File

@ -6,11 +6,12 @@
<view class="flex flex-wrap">
<view v-for="(file, idx) in files" :key="idx" class="upload-item mt-10">
<image v-if="file.isImage" :src="file.url" class="w-full h-full"></image>
<image v-else-if="file.isPdf" src="/static/pdf.svg" class="w-full h-full"></image>
<image v-else src="/static/file.svg" class="w-full h-full"></image>
<uni-icons type="close" :size="32" color="red" class="remove-icon" @click="remove(idx)"></uni-icons>
</view>
<view v-if="value.length < 3"
class="upload-item border-primary mt-10 flex items-center justify-center text-primary" @click="addImage()">
<view v-if="value.length < 10"
class="upload-item border-primary mt-10 flex items-center justify-center text-primary" @click="addFile()">
<uni-icons type="camera" :size="40" color="#0074ff"></uni-icons>
</view>
</view>
@ -48,26 +49,72 @@ const files = computed(() => value.value.map(i => {
url: i.url,
name: i.name,
type: i.type,
isImage: /image/i.test(i.type)
isImage: /image/i.test(i.type),
isPdf: /application\/pdf/i.test(i.type),
}
}))
function addImage() {
uni.chooseImage({
count: 1,
function addFile() {
wx.chooseMessageFile({
count: 1, // 1
type: 'all', //
success: async (res) => {
const file = res.tempFiles[0];
const { path, name, size } = file;
const type = checkFileValid(name, size);
//
if (!type) return;
loading();
const result = await upload(res.tempFilePaths[0]);
const result = await upload(path);
hideLoading();
if (result) {
change([...value.value, { url: result, type: 'image/png' }])
change([...value.value, { url: result, type }])
} else {
toast('上传失败')
}
},
fail: (err) => {
toast('上传失败')
}
})
}
function checkFileValid(fileName, fileSize) {
//
const ext = fileName.split('.').pop().toLowerCase();
// (10MB)
const maxSize = 10 * 1024 * 1024;
if (fileSize > maxSize) {
toast('文件大小不能超过10MB')
return false;
}
if (['jpg', 'jpeg', 'png'].includes(ext)) {
return 'image/png'
}
if (ext === 'pdf') {
return 'application/pdf'
}
toast('仅支持图片或PDF')
return false;
}
// function addImage() {
// uni.chooseImage({
// count: 1,
// success: async (res) => {
// loading();
// const result = await upload(res.tempFilePaths[0]);
// hideLoading();
// if (result) {
// change([...value.value, { url: result, type: 'image/png' }])
// } else {
// toast('')
// }
// }
// })
// }
function change(value) {
emits('change', {
title: props.title,

View File

@ -1,5 +1,5 @@
<template>
<!-- <view class="px-10">{{ attrs.name }} {{ attrs.title }} {{ attrs.type }}</view> -->
<!-- <view class="text-danger px-10">{{ attrs.name }} {{ attrs.title }} {{ attrs.type }}</view> -->
<form-datepicker v-if="attrs.type === 'date'" v-bind="attrs" :form="form" :disableChange="disableChange"
@change="change" />
<form-input v-else-if="attrs.type === 'input'" v-bind="attrs" :form="form" :disableChange="disableChange"
@ -18,6 +18,7 @@
@addRule="addRule"></form-mult-disease>
<form-upload v-else-if="attrs.type === 'files'" v-bind="attrs" :form="form" @change="change" />
<form-mult-other v-else-if="attrs.type === 'multiSelectAndOther'" v-bind="attrs" :form="form" @change="change" />
<form-positive-find v-else-if="attrs.type === 'positiveFind'" v-bind="attrs" :form="form" @change="change" />
<!--
<form-operation v-else-if="attrs.title === 'surgicalHistory'" v-bind="attrs" :form="form" @change="change"
@addRule="addRule" />
@ -39,6 +40,7 @@ import formTextarea from './form-textarea.vue';
import formMultDisease from './form-multiple-diseases.vue';
import formUpload from './form-upload.vue';
import formMultOther from './form-mult-select-and-other.vue';
import formPositiveFind from './form-positive-find.vue';
defineProps({
form: {

View File

@ -32,7 +32,7 @@ const props = defineProps({
}
})
const formCellType = ['input', 'select', 'date', 'radio', 'region', 'textarea', 'multiSelectAndOther', 'selfMultipleDiseases', 'files','diagnosis'];
const formCellType = ['input', 'select', 'date', 'radio', 'region', 'textarea', 'multiSelectAndOther', 'selfMultipleDiseases', 'files','diagnosis','positiveFind'];
const formCellTitle = ['surgicalHistory'];
const customCellType = ['BMI', 'bloodPressure'];
const disabledMap = computed(() => props.disableTitles.reduce((m, i) => {

View File

@ -40,6 +40,8 @@
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="i.corp === '其他'" class="px-10 leading-normal text-white text-base bg-danger rounded-full">
外院
</view>
@ -51,7 +53,7 @@
</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 w-90 text-base text-gray">{{ row.label }}</view>
<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>
@ -96,7 +98,8 @@ import { toast } from '../../utils/widget';
const tempType = {
outpatient: '门诊信息',
inhospital: '住院信息'
inhospital: '住院信息',
physicalExaminationTemplate: '体检报告'
}
const empty = ref(false)
const { useLoad, useShow } = useGuard();
@ -118,6 +121,7 @@ const tempShowField = ref(null);
const config = {
outpatient: ["corp", "deptName", "doctor", "diagnosisName", "files"],
inhospital: ["corp", "diagnosisName", "operation", "operationDate", "outhosDate", "files"],
physicalExaminationTemplate: ['inspectPakageName']
};
function addArchive() {
@ -197,7 +201,7 @@ async function getList() {
memberId: customerId.value,
page: page.value,
pageSize: 20,
medicalType: ['outpatient', 'inhospital']
medicalType: Object.keys(tempType)
}
if (type.value !== 'all') {
params.medicalType = [type.value]

1
static/pdf.svg Normal file
View File

@ -0,0 +1 @@
<svg t="1713431721970" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1534" width="200" height="200"><path d="M910.2336 1024H113.7664C51.2 1024 0 972.8 0 910.2336V113.7664C0 51.2 51.2 0 113.7664 0h796.4672C972.8 0 1024 51.2 1024 113.7664v796.4672C1024 972.8 972.8 1024 910.2336 1024zM155.2128 555.4432h44.672c35.9936 1.2032 66.0224-8.704 89.984-29.6704 24.0128-20.9664 36.0192-48.3328 36.0192-82.1248 0-33.28-10.24-58.9568-30.7712-76.8768-20.5312-17.92-49.3568-26.88-86.5536-26.88h-97.792v344.2432h44.4416v-128.6912z m0-176.4352h45.3376c52.48 0 78.6688 22.1184 78.6688 66.432 0 22.8096-7.04 40.3456-21.12 52.5824-14.08 12.1856-34.6624 18.304-61.7728 18.304H155.2128v-137.3184z m234.0352 305.1008h94.6432c54.528 0 99.072-16.0768 133.6576-48.2048 34.6112-32.1536 51.8912-74.9056 51.8912-128.256 0-51.0976-17.28-91.8528-51.8912-122.2144-34.56-30.336-77.952-45.568-130.0992-45.568h-98.2016v344.2432z m44.416-304.6656h51.9936c41.0624 0 74.1632 10.8032 99.328 32.4608 25.216 21.6064 37.7856 53.888 37.7856 96.8704 0 43.008-12.2368 76.3392-36.7872 100.224-24.5248 23.8592-58.624 35.7632-102.3232 35.7632H433.664V379.4432z m479.5648 0v-39.5776h-177.3312v344.2432h44.4416v-150.4512h123.1104V494.592h-123.136v-115.1232h132.9152z" fill="#D93838" p-id="1535"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB