|
@@ -1,650 +1,650 @@
|
|
|
-<script setup lang="ts">
|
|
|
|
|
-import type { TaskModel } from '@/model/follow.model';
|
|
|
|
|
-import { FillFollowContentMethod, UploadIFile, FollowContentMethod } from '@/request/api/follow.api';
|
|
|
|
|
-import { getDictionaryMethod } from '@/request/api/dictionary.api';
|
|
|
|
|
-import { useRequest } from 'alova/client';
|
|
|
|
|
-import { PlusOutlined } from '@ant-design/icons-vue';
|
|
|
|
|
-
|
|
|
|
|
-import { notification } from 'ant-design-vue';
|
|
|
|
|
-import type { UploadFile } from 'ant-design-vue/es/upload/interface';
|
|
|
|
|
-import { VxeUI } from 'vxe-pc-ui';
|
|
|
|
|
-type FormModel = Partial<TaskModel>;
|
|
|
|
|
-
|
|
|
|
|
-const props = defineProps<{ data: FormModel }>();
|
|
|
|
|
-
|
|
|
|
|
-const emits = defineEmits<{
|
|
|
|
|
- submit: [data?: TaskModel];
|
|
|
|
|
-}>();
|
|
|
|
|
-const {
|
|
|
|
|
- data: contentArr,
|
|
|
|
|
- loading,
|
|
|
|
|
- send: load,
|
|
|
|
|
-} = useRequest(() => FollowContentMethod(props.data), {
|
|
|
|
|
- initialData: [],
|
|
|
|
|
-}).onSuccess(({ data }) => {
|
|
|
|
|
- const index = data.findIndex((item) => item.id === props.data.id);
|
|
|
|
|
- if (index > -1) {
|
|
|
|
|
- changeTab(data[index], index);
|
|
|
|
|
- }
|
|
|
|
|
-});
|
|
|
|
|
-const statusList = ref<string[]>([]);
|
|
|
|
|
-onBeforeMount(() => {
|
|
|
|
|
- getDictionaryMethod('followup_syndrome_change').then((res) => {
|
|
|
|
|
- statusList.value = res;
|
|
|
|
|
- });
|
|
|
|
|
-});
|
|
|
|
|
-const activeKey = ref<number>();
|
|
|
|
|
-const activeIndex = ref<number>();
|
|
|
|
|
-const activeObj = ref<any>({ fillin: {}, symptomsData: [] });
|
|
|
|
|
-// 切换侧边栏任务
|
|
|
|
|
-const changeTab = (data: any, index: number) => {
|
|
|
|
|
- activeKey.value = data.id;
|
|
|
|
|
- activeObj.value = { ...data, fillin: { ...data.fillin } };
|
|
|
|
|
- activeIndex.value = index;
|
|
|
|
|
- activeObj.value.symptomsData = [];
|
|
|
|
|
- downImageList.value = [];
|
|
|
|
|
- const upImg = data.fillin?.upImg;
|
|
|
|
|
- const downImg = data.fillin?.downImg;
|
|
|
|
|
- const faceImg = data.fillin?.faceImg;
|
|
|
|
|
- if (activeObj.value?.syndromeList && activeObj.value.syndromeList.length > 0) {
|
|
|
|
|
- activeObj.value.syndromeList.forEach((syndrome) => {
|
|
|
|
|
- activeObj.value.symptomsData.push({ name: syndrome });
|
|
|
|
|
- });
|
|
|
|
|
- activeObj.value.symptomsData.forEach((item) => {
|
|
|
|
|
- item.child = statusList.value;
|
|
|
|
|
- item.selectedValue = '';
|
|
|
|
|
- item.selectedId = null;
|
|
|
|
|
- item.id = data.id;
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- symptomsValue.value.parent = '';
|
|
|
|
|
- upImgList.value = upImg
|
|
|
|
|
- ? [
|
|
|
|
|
- {
|
|
|
|
|
- uid: '-1',
|
|
|
|
|
- status: 'done',
|
|
|
|
|
- url: upImg,
|
|
|
|
|
- thumbUrl: upImg,
|
|
|
|
|
- response: { url: upImg },
|
|
|
|
|
- },
|
|
|
|
|
- ]
|
|
|
|
|
- : [];
|
|
|
|
|
- downImageList.value = downImg
|
|
|
|
|
- ? [
|
|
|
|
|
- {
|
|
|
|
|
- uid: '-1',
|
|
|
|
|
- status: 'done',
|
|
|
|
|
- url: downImg,
|
|
|
|
|
- thumbUrl: downImg,
|
|
|
|
|
- response: { url: downImg },
|
|
|
|
|
- },
|
|
|
|
|
- ]
|
|
|
|
|
- : [];
|
|
|
|
|
- faceImageList.value = faceImg
|
|
|
|
|
- ? [
|
|
|
|
|
- {
|
|
|
|
|
- uid: '-1',
|
|
|
|
|
- status: 'done',
|
|
|
|
|
- url: faceImg,
|
|
|
|
|
- thumbUrl: faceImg,
|
|
|
|
|
- response: { url: faceImg },
|
|
|
|
|
- },
|
|
|
|
|
- ]
|
|
|
|
|
- : [];
|
|
|
|
|
- uploadProps.showRemoveIcon = data.progress === '1';
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 存储所有选择的症状
|
|
|
|
|
-const selectedSymptomsList = ref<{ name: string; value: string }[]>([]);
|
|
|
|
|
-// 存储症状
|
|
|
|
|
-const symptomsList = ref<{ name: string; type: string }[]>([]);
|
|
|
|
|
-// 症状选择的值
|
|
|
|
|
-const symptomsValue = ref({
|
|
|
|
|
- parent: '',
|
|
|
|
|
- child: '',
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-// 处理父级点击
|
|
|
|
|
-const handleParentClick = (name: string) => {
|
|
|
|
|
- if (symptomsValue.value.parent === name) {
|
|
|
|
|
- // 如果点击的是当前选中的父级,则清空选择
|
|
|
|
|
- symptomsValue.value = {
|
|
|
|
|
- parent: '',
|
|
|
|
|
- child: '',
|
|
|
|
|
- };
|
|
|
|
|
- } else {
|
|
|
|
|
- // 选择新的父级
|
|
|
|
|
- symptomsValue.value = {
|
|
|
|
|
- parent: name,
|
|
|
|
|
- child: '',
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 处理子级选择变化
|
|
|
|
|
-const handleChildChange = (e: any) => {
|
|
|
|
|
- const selectedValue = e.target.value;
|
|
|
|
|
- const currentParent = symptomsValue.value.parent;
|
|
|
|
|
- // 找到当前症状
|
|
|
|
|
- const symptom = activeObj.value.symptomsData.find((item) => item.name === currentParent);
|
|
|
|
|
-
|
|
|
|
|
- if (symptom) {
|
|
|
|
|
- // 如果点击的是当前选中的值,则取消选择
|
|
|
|
|
- if (symptom.selectedId === selectedValue) {
|
|
|
|
|
- // 取消选择
|
|
|
|
|
- symptom.selectedValue = '';
|
|
|
|
|
- symptom.selectedId = null;
|
|
|
|
|
-
|
|
|
|
|
- // 从已选择的症状列表中移除
|
|
|
|
|
- const index = selectedSymptomsList.value.findIndex((item) => item.name === currentParent);
|
|
|
|
|
- if (index > -1) {
|
|
|
|
|
- selectedSymptomsList.value.splice(index, 1);
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- // 选择新的值
|
|
|
|
|
- const child = symptom.child.find((item) => item.value === selectedValue);
|
|
|
|
|
- if (child) {
|
|
|
|
|
- symptom.selectedValue = selectedValue;
|
|
|
|
|
- symptom.selectedId = selectedValue;
|
|
|
|
|
-
|
|
|
|
|
- // 更新已选择的症状列表
|
|
|
|
|
- const existingIndex = selectedSymptomsList.value.findIndex((item) => item.name === currentParent);
|
|
|
|
|
- if (existingIndex > -1) {
|
|
|
|
|
- selectedSymptomsList.value[existingIndex].value = selectedValue;
|
|
|
|
|
- } else {
|
|
|
|
|
- selectedSymptomsList.value.push({
|
|
|
|
|
- name: currentParent,
|
|
|
|
|
- value: selectedValue,
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- symptomsValue.value.parent = '';
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 是否出现新症状
|
|
|
|
|
-const selectSymptomsData = reactive([
|
|
|
|
|
- { name: '有', id: 'Y' },
|
|
|
|
|
- { name: '没有', id: 'N' },
|
|
|
|
|
-]);
|
|
|
|
|
-
|
|
|
|
|
-const uploadProps = reactive({ showRemoveIcon: true });
|
|
|
|
|
-const changeTag = (item: any) => {
|
|
|
|
|
- activeObj.value.fillin.isHaveNewSyndrome = item.id;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const upImgList = ref<UploadFile[]>([]);
|
|
|
|
|
-const downImageList = ref<UploadFile[]>([]);
|
|
|
|
|
-const faceImageList = ref<UploadFile[]>([]);
|
|
|
|
|
-// 预览图片
|
|
|
|
|
-const handlePreview = async (file: UploadFile) => {
|
|
|
|
|
- previewImg.value = file.response?.url ?? file.thumbUrl;
|
|
|
|
|
- visible.value = true;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 填写随访内容
|
|
|
|
|
-function subFollowContent() {
|
|
|
|
|
- activeObj.value.fillin.upImg = upImgList.value[0]?.response?.url;
|
|
|
|
|
- activeObj.value.fillin.downImg = downImageList.value[0]?.response?.url;
|
|
|
|
|
- activeObj.value.fillin.faceImg = faceImageList.value[0]?.response?.url;
|
|
|
|
|
- symptomsList.value = [];
|
|
|
|
|
- activeObj.value.symptomsData.forEach((item) => {
|
|
|
|
|
- symptomsList.value.push({ name: item.name, type: item.selectedValue });
|
|
|
|
|
- });
|
|
|
|
|
- activeObj.value.fillin.symptomsList = symptomsList.value;
|
|
|
|
|
- FillFollowContentMethod(activeObj.value).then(() => {
|
|
|
|
|
- notification.success({
|
|
|
|
|
- message: '',
|
|
|
|
|
- description: '提交成功!',
|
|
|
|
|
- });
|
|
|
|
|
- emits('submit');
|
|
|
|
|
- load();
|
|
|
|
|
- });
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 取消提交
|
|
|
|
|
-function cancelFollowContent() {
|
|
|
|
|
- VxeUI.modal.close(`follow-modal`);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-function customUpload(e: any) {
|
|
|
|
|
- // uploadApi 你的二次封装上传接口
|
|
|
|
|
- UploadIFile(e.file)
|
|
|
|
|
- .then((res) => {
|
|
|
|
|
- // 调用实例的成功方法通知组件该文件上传成功
|
|
|
|
|
- e.onSuccess(res, e);
|
|
|
|
|
- })
|
|
|
|
|
- .catch((err) => {
|
|
|
|
|
- // 调用实例的失败方法通知组件该文件上传失败
|
|
|
|
|
- e.onError(err);
|
|
|
|
|
- });
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const visible = ref<boolean>(false);
|
|
|
|
|
-const setVisible = (value: boolean): void => {
|
|
|
|
|
- visible.value = value;
|
|
|
|
|
-};
|
|
|
|
|
-const previewImg = ref<string>('');
|
|
|
|
|
-</script>
|
|
|
|
|
-
|
|
|
|
|
-<template>
|
|
|
|
|
- <div>
|
|
|
|
|
- <div class="flex font-bold">
|
|
|
|
|
- <!-- 左边-->
|
|
|
|
|
- <div class="animated-vertical-tabs">
|
|
|
|
|
- <div class="tab-list">
|
|
|
|
|
- <div class="font-bold h-8 pt-3 mb-3 ml-2">{{ activeObj?.followupPlanName }}</div>
|
|
|
|
|
- <div
|
|
|
|
|
- style="font-size: 14px"
|
|
|
|
|
- v-for="(content, index) in contentArr"
|
|
|
|
|
- :key="content.id"
|
|
|
|
|
- class="tab-item mb-3"
|
|
|
|
|
- :class="{ active: activeKey === content.id }"
|
|
|
|
|
- @click="changeTab(content, index)"
|
|
|
|
|
- >
|
|
|
|
|
- <div>{{ content.followupTaskName }}</div>
|
|
|
|
|
- <span class="tab-label">{{ content.arrangeTime }}</span>
|
|
|
|
|
- <div :class="content.progress == 1 ? 'text-red-600' : content.progress == 2 ? 'text-green-900' : content.progress == 3 ? 'text-blue-900' : ''">
|
|
|
|
|
- {{ content.progress === '1' ? '未完成' : content.progress === '2' ? '已完成' : '未开始' }}
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- 右边-->
|
|
|
|
|
- <div :key="activeObj.id">
|
|
|
|
|
- <div class="h-8 text-center">
|
|
|
|
|
- {{ activeObj?.followupTaskName }}
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="mb-2 text-center">预定随访时间:{{ activeObj?.arrangeTime }}</div>
|
|
|
|
|
- <div class="mb-2 ml-2">
|
|
|
|
|
- 您好,您于<span class="text-blue-600">【{{ activeObj?.medicalTime }}】</span>在我院<span class="text-blue-600">【{{ activeObj?.institutionName }}】</span>因为<span
|
|
|
|
|
- class="text-blue-600"
|
|
|
|
|
- >【{{ activeObj?.diagnosis }}】</span
|
|
|
|
|
- >就诊。接下来我们将对您进行一个随访,请根据目前的实际情况回答。
|
|
|
|
|
- </div>
|
|
|
|
|
- <div
|
|
|
|
|
- class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2"
|
|
|
|
|
- v-if="(activeObj?.progress === '1' && activeObj?.symptomsData?.length > 0) || (activeObj.progress === '2' && activeObj?.fillin?.symptomsList?.length > 0)"
|
|
|
|
|
- >
|
|
|
|
|
- <div class="mb-3 border-b-0">
|
|
|
|
|
- 1、请问您的症状有没有<span class="text-red-600">好转</span>或者<span class="text-red-600">恶化</span>?请先点击症状,再选择好转还是恶化。(没有操作的症状默认没有变化)
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div class="ml-4" v-if="activeObj.progress === '1'">
|
|
|
|
|
- <!-- 症状选择器 -->
|
|
|
|
|
- <div class="symptom-container flex flex-wrap">
|
|
|
|
|
- <div v-for="item in activeObj?.symptomsData" :key="item.name" class="symptom-item">
|
|
|
|
|
- <div class="symptom-button" @click="activeObj.progress !== '0' ? handleParentClick(item.name) : ''" :class="{ 'disabled': activeObj.progress === '0' }">
|
|
|
|
|
- <span>{{ item.name }}</span>
|
|
|
|
|
- <span v-if="item.selectedValue" class="selected-value">: {{ item.selectedValue }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-show="symptomsValue.parent === item.name" class="symptom-options">
|
|
|
|
|
- <a-radio-group :model-value="item.selectedId" @change="activeObj.progress !== '0' ? handleChildChange : ''" class="flex flex-wrap" :disabled="activeObj.progress === '0'">
|
|
|
|
|
- <a-radio :value="tag.value" v-for="tag in item.child" :key="tag.value" class="mr-4">
|
|
|
|
|
- {{ tag.label }}
|
|
|
|
|
- </a-radio>
|
|
|
|
|
- </a-radio-group>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- 已经评估过 -->
|
|
|
|
|
- <div v-else>
|
|
|
|
|
- <div class="symptom-container flex flex-wrap">
|
|
|
|
|
- <div v-for="item in activeObj?.fillin?.symptomsList" :key="item.name" class="symptom-item">
|
|
|
|
|
- <div class="symptom-button">
|
|
|
|
|
- <span>{{ item.name }}</span>
|
|
|
|
|
- <span class="selected-value">: {{ item.type }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 第二个-->
|
|
|
|
|
- <div class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2">
|
|
|
|
|
- <div class="mb-3">2、请问有没有出现<span class="text-red-600">新</span>的症状?</div>
|
|
|
|
|
- <div class="mb-8 ml-4 flex">
|
|
|
|
|
- <div v-for="symptoms in selectSymptomsData" :key="symptoms.name" class="mr-4" @click="activeObj?.progress === '1' ? changeTag(symptoms) : ''">
|
|
|
|
|
- <div>
|
|
|
|
|
- <div class="border-solid b-1 w-20 text-center" :class="[activeObj.fillin.isHaveNewSyndrome === symptoms.id ? 'bg-blue text-#fff' : '', activeObj.progress === '0' ? 'disabled' : '']">
|
|
|
|
|
- {{ symptoms.name }}
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- 第三个-->
|
|
|
|
|
- <div class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2" v-if="activeObj.fillin?.isHaveNewSyndrome === 'Y'">
|
|
|
|
|
- <div class="mb-3">3、请描述新的症状</div>
|
|
|
|
|
- <div class="mb-4 ml-4">
|
|
|
|
|
- <a-input v-model:value="activeObj.fillin.newSyndrome" placeholder="请输入" :auto-size="{ minRows: 2, maxRows: 5 }" :disabled="activeObj.progress === '2' || activeObj.progress === '0'" />
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- 第四个-->
|
|
|
|
|
- <div class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2">
|
|
|
|
|
- <div class="mb-3">4、如果有其他情况,请留言</div>
|
|
|
|
|
- <div class="mb-4 ml-4">
|
|
|
|
|
- <a-input v-model:value="activeObj.fillin.otherDesc" placeholder="请输入" :auto-size="{ minRows: 2, maxRows: 5 }" :disabled="activeObj.progress === '2' || activeObj.progress === '0'" />
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- 第五个-->
|
|
|
|
|
- <div class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2">
|
|
|
|
|
- <div class="mb-3">5、为了医生更好地了解您的恢复情况,需要您上传舌面象照片</div>
|
|
|
|
|
- <div class="mb-4 ml-3">
|
|
|
|
|
- <!-- 上传图片-->
|
|
|
|
|
- <div class="flex">
|
|
|
|
|
- <!-- 舌面-->
|
|
|
|
|
- <div class="flex flex-col items-center mr-4">
|
|
|
|
|
- <a-upload
|
|
|
|
|
- :showUploadList="uploadProps"
|
|
|
|
|
- v-model:file-list="upImgList"
|
|
|
|
|
- list-type="picture-card"
|
|
|
|
|
- @preview="handlePreview"
|
|
|
|
|
- :maxCount="1"
|
|
|
|
|
- :customRequest="customUpload"
|
|
|
|
|
- :disabled="activeObj.progress === '2' || activeObj.progress === '0'"
|
|
|
|
|
- >
|
|
|
|
|
- <div v-if="upImgList.length < 1">
|
|
|
|
|
- <plus-outlined />
|
|
|
|
|
- </div>
|
|
|
|
|
- </a-upload>
|
|
|
|
|
- <div class="font-bold">舌面</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- 舌下-->
|
|
|
|
|
- <div class="flex flex-col items-center mr-4">
|
|
|
|
|
- <a-upload
|
|
|
|
|
- :showUploadList="uploadProps"
|
|
|
|
|
- v-model:file-list="downImageList"
|
|
|
|
|
- list-type="picture-card"
|
|
|
|
|
- @preview="handlePreview"
|
|
|
|
|
- :maxCount="1"
|
|
|
|
|
- :customRequest="customUpload"
|
|
|
|
|
- :disabled="activeObj.progress === '2' || activeObj.progress === '0'"
|
|
|
|
|
- >
|
|
|
|
|
- <div v-if="downImageList.length < 1">
|
|
|
|
|
- <plus-outlined />
|
|
|
|
|
- </div>
|
|
|
|
|
- </a-upload>
|
|
|
|
|
- <div class="font-bold">舌下</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- 面部-->
|
|
|
|
|
- <div class="flex flex-col items-center mr-4">
|
|
|
|
|
- <a-upload
|
|
|
|
|
- :showUploadList="uploadProps"
|
|
|
|
|
- v-model:file-list="faceImageList"
|
|
|
|
|
- list-type="picture-card"
|
|
|
|
|
- @preview="handlePreview"
|
|
|
|
|
- :maxCount="1"
|
|
|
|
|
- :customRequest="customUpload"
|
|
|
|
|
- :disabled="activeObj.progress === '2' || activeObj.progress === '0'"
|
|
|
|
|
- >
|
|
|
|
|
- <div v-if="faceImageList.length < 1">
|
|
|
|
|
- <plus-outlined />
|
|
|
|
|
- </div>
|
|
|
|
|
- </a-upload>
|
|
|
|
|
- <div class="font-bold">面部</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- --------end-->
|
|
|
|
|
- </div>
|
|
|
|
|
- <a-image
|
|
|
|
|
- :width="200"
|
|
|
|
|
- :style="{ display: 'none' }"
|
|
|
|
|
- :preview="{
|
|
|
|
|
- visible,
|
|
|
|
|
- onVisibleChange: setVisible,
|
|
|
|
|
- }"
|
|
|
|
|
- :src="previewImg"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <!-- -->
|
|
|
|
|
- <div class="ml-2 mt-1">
|
|
|
|
|
- 感谢您的配合,为了更好地了解您的回复情况,我们将会在<span class="text-blue-600"> {{ activeObj?.arrangeTime }} </span
|
|
|
|
|
- >再次对您进行随访,届时请点击随访链接参与,再次感谢您!
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="flex items-center justify-center mt-6 mb-6">
|
|
|
|
|
- <a-button size="small" class="mr-4" @click="cancelFollowContent">取消</a-button>
|
|
|
|
|
- <a-button type="primary" size="small" @click="subFollowContent" v-show="activeObj.progress === '1'">提交 </a-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
-</template>
|
|
|
|
|
-<style scoped lang="scss">
|
|
|
|
|
-.ant-upload-select-picture-card i {
|
|
|
|
|
- font-size: 32px;
|
|
|
|
|
- color: #999;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ant-upload-select-picture-card .ant-upload-text {
|
|
|
|
|
- margin-top: 8px;
|
|
|
|
|
- color: #666;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.mesh-grid {
|
|
|
|
|
- border-collapse: collapse;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.mesh-grid td {
|
|
|
|
|
- border: 1px solid black;
|
|
|
|
|
- width: 100px;
|
|
|
|
|
- padding: 20px 20px;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.animated-vertical-tabs {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- height: 730px;
|
|
|
|
|
- width: 17%;
|
|
|
|
|
- overflow: auto;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.tab-list {
|
|
|
|
|
- border-right: 1px solid #f0f0f0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.tab-item {
|
|
|
|
|
- position: relative;
|
|
|
|
|
- padding: 10px;
|
|
|
|
|
- cursor: pointer;
|
|
|
|
|
- transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.tab-item:hover {
|
|
|
|
|
- background-color: rgba(24, 144, 255, 0.06);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.tab-item.active {
|
|
|
|
|
- background: lightgray;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.tab-indicator {
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- top: 0;
|
|
|
|
|
- right: -1px;
|
|
|
|
|
- width: 2px;
|
|
|
|
|
- height: 100%;
|
|
|
|
|
- background-color: #1890ff;
|
|
|
|
|
- transform: scaleY(0);
|
|
|
|
|
- transform-origin: center top;
|
|
|
|
|
- transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.tab-item.active .tab-indicator {
|
|
|
|
|
- transform: scaleY(1);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.tab-content {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- padding: 0 24px;
|
|
|
|
|
- overflow: auto;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.fade-enter-active,
|
|
|
|
|
-.fade-leave-active {
|
|
|
|
|
- transition: opacity 0.3s ease;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.fade-enter-from,
|
|
|
|
|
-.fade-leave-to {
|
|
|
|
|
- opacity: 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 症状选择器样式
|
|
|
|
|
-.symptom-container {
|
|
|
|
|
- .symptom-item {
|
|
|
|
|
- position: relative;
|
|
|
|
|
- margin-right: 16px;
|
|
|
|
|
- margin-bottom: 16px;
|
|
|
|
|
-
|
|
|
|
|
- .symptom-button {
|
|
|
|
|
- min-width: 100px;
|
|
|
|
|
- padding: 8px 16px;
|
|
|
|
|
- border: 1px solid #d9d9d9;
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
- text-align: center;
|
|
|
|
|
- cursor: pointer;
|
|
|
|
|
- transition: all 0.3s;
|
|
|
|
|
- background: #fff;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
-
|
|
|
|
|
- &:hover {
|
|
|
|
|
- border-color: #40a9ff;
|
|
|
|
|
- color: #40a9ff;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- &.active {
|
|
|
|
|
- border-color: #1890ff;
|
|
|
|
|
- color: #1890ff;
|
|
|
|
|
- background: rgba(24, 144, 255, 0.1);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- &.has-value {
|
|
|
|
|
- border-color: #52c41a;
|
|
|
|
|
- color: #52c41a;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .selected-value {
|
|
|
|
|
- margin-left: 4px;
|
|
|
|
|
- font-weight: 500;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .symptom-options {
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- top: 100%;
|
|
|
|
|
- left: 0;
|
|
|
|
|
- z-index: 1;
|
|
|
|
|
- margin-top: 8px;
|
|
|
|
|
- padding: 8px;
|
|
|
|
|
- background: #fff;
|
|
|
|
|
- border: 1px solid #d9d9d9;
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
|
|
|
- animation: fadeIn 0.3s;
|
|
|
|
|
-
|
|
|
|
|
- .ant-radio-group {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
- gap: 8px;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .ant-radio-wrapper {
|
|
|
|
|
- padding: 4px 8px;
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
- transition: all 0.3s;
|
|
|
|
|
-
|
|
|
|
|
- &:hover {
|
|
|
|
|
- background: rgba(24, 144, 255, 0.1);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 已选择症状标签样式
|
|
|
|
|
-.selected-symptoms {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-wrap: wrap;
|
|
|
|
|
- gap: 8px;
|
|
|
|
|
- margin-bottom: 16px;
|
|
|
|
|
-
|
|
|
|
|
- .ant-tag {
|
|
|
|
|
- margin: 0;
|
|
|
|
|
- padding: 4px 8px;
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
- transition: all 0.3s;
|
|
|
|
|
-
|
|
|
|
|
- &:hover {
|
|
|
|
|
- background: rgba(24, 144, 255, 0.1);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 动画
|
|
|
|
|
-@keyframes fadeIn {
|
|
|
|
|
- from {
|
|
|
|
|
- opacity: 0;
|
|
|
|
|
- transform: translateY(-10px);
|
|
|
|
|
- }
|
|
|
|
|
- to {
|
|
|
|
|
- opacity: 1;
|
|
|
|
|
- transform: translateY(0);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 整体布局优化
|
|
|
|
|
-.border-1 {
|
|
|
|
|
- margin-bottom: 16px;
|
|
|
|
|
- padding: 16px;
|
|
|
|
|
- border-radius: 8px;
|
|
|
|
|
- background: #fff;
|
|
|
|
|
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.mb-8 {
|
|
|
|
|
- margin-bottom: 32px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.ml-4 {
|
|
|
|
|
- margin-left: 16px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.text-blue-600 {
|
|
|
|
|
- color: #1890ff;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.text-red-600 {
|
|
|
|
|
- color: #ff4d4f;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.font-bold {
|
|
|
|
|
- font-weight: 600;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 禁用状态样式
|
|
|
|
|
-.disabled {
|
|
|
|
|
- opacity: 0.5;
|
|
|
|
|
- cursor: not-allowed !important;
|
|
|
|
|
- pointer-events: none;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.symptom-button.disabled {
|
|
|
|
|
- background-color: #f5f5f5;
|
|
|
|
|
- color: #999;
|
|
|
|
|
- border-color: #d9d9d9;
|
|
|
|
|
- cursor: not-allowed;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.symptom-button.disabled:hover {
|
|
|
|
|
- border-color: #d9d9d9;
|
|
|
|
|
- color: #999;
|
|
|
|
|
- background-color: #f5f5f5;
|
|
|
|
|
-}
|
|
|
|
|
-</style>
|
|
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+import type { TaskModel } from '@/model/follow.model';
|
|
|
|
|
+import { FillFollowContentMethod, UploadIFile, FollowContentMethod } from '@/request/api/follow.api';
|
|
|
|
|
+import { getDictionaryMethod } from '@/request/api/dictionary.api';
|
|
|
|
|
+import { useRequest } from 'alova/client';
|
|
|
|
|
+import { PlusOutlined } from '@ant-design/icons-vue';
|
|
|
|
|
+
|
|
|
|
|
+import { notification } from 'ant-design-vue';
|
|
|
|
|
+import type { UploadFile } from 'ant-design-vue/es/upload/interface';
|
|
|
|
|
+import { VxeUI } from 'vxe-pc-ui';
|
|
|
|
|
+type FormModel = Partial<TaskModel>;
|
|
|
|
|
+
|
|
|
|
|
+const props = defineProps<{ data: FormModel }>();
|
|
|
|
|
+
|
|
|
|
|
+const emits = defineEmits<{
|
|
|
|
|
+ submit: [data?: TaskModel];
|
|
|
|
|
+}>();
|
|
|
|
|
+const {
|
|
|
|
|
+ data: contentArr,
|
|
|
|
|
+ loading,
|
|
|
|
|
+ send: load,
|
|
|
|
|
+} = useRequest(() => FollowContentMethod(props.data), {
|
|
|
|
|
+ initialData: [],
|
|
|
|
|
+}).onSuccess(({ data }) => {
|
|
|
|
|
+ const index = data.findIndex((item) => item.id === props.data.id);
|
|
|
|
|
+ if (index > -1) {
|
|
|
|
|
+ changeTab(data[index], index);
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+const statusList = ref<string[]>([]);
|
|
|
|
|
+onBeforeMount(() => {
|
|
|
|
|
+ getDictionaryMethod('followup_syndrome_change').then((res) => {
|
|
|
|
|
+ statusList.value = res;
|
|
|
|
|
+ });
|
|
|
|
|
+});
|
|
|
|
|
+const activeKey = ref<number>();
|
|
|
|
|
+const activeIndex = ref<number>();
|
|
|
|
|
+const activeObj = ref<any>({ fillin: {}, symptomsData: [] });
|
|
|
|
|
+// 切换侧边栏任务
|
|
|
|
|
+const changeTab = (data: any, index: number) => {
|
|
|
|
|
+ activeKey.value = data.id;
|
|
|
|
|
+ activeObj.value = { ...data, fillin: { ...data.fillin } };
|
|
|
|
|
+ activeIndex.value = index;
|
|
|
|
|
+ activeObj.value.symptomsData = [];
|
|
|
|
|
+ downImageList.value = [];
|
|
|
|
|
+ const upImg = data.fillin?.upImg;
|
|
|
|
|
+ const downImg = data.fillin?.downImg;
|
|
|
|
|
+ const faceImg = data.fillin?.faceImg;
|
|
|
|
|
+ if (activeObj.value?.syndromeList && activeObj.value.syndromeList.length > 0) {
|
|
|
|
|
+ activeObj.value.syndromeList.forEach((syndrome) => {
|
|
|
|
|
+ activeObj.value.symptomsData.push({ name: syndrome });
|
|
|
|
|
+ });
|
|
|
|
|
+ activeObj.value.symptomsData.forEach((item) => {
|
|
|
|
|
+ item.child = statusList.value;
|
|
|
|
|
+ item.selectedValue = '';
|
|
|
|
|
+ item.selectedId = null;
|
|
|
|
|
+ item.id = data.id;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ symptomsValue.value.parent = '';
|
|
|
|
|
+ upImgList.value = upImg
|
|
|
|
|
+ ? [
|
|
|
|
|
+ {
|
|
|
|
|
+ uid: '-1',
|
|
|
|
|
+ status: 'done',
|
|
|
|
|
+ url: upImg,
|
|
|
|
|
+ thumbUrl: upImg,
|
|
|
|
|
+ response: { url: upImg },
|
|
|
|
|
+ },
|
|
|
|
|
+ ]
|
|
|
|
|
+ : [];
|
|
|
|
|
+ downImageList.value = downImg
|
|
|
|
|
+ ? [
|
|
|
|
|
+ {
|
|
|
|
|
+ uid: '-1',
|
|
|
|
|
+ status: 'done',
|
|
|
|
|
+ url: downImg,
|
|
|
|
|
+ thumbUrl: downImg,
|
|
|
|
|
+ response: { url: downImg },
|
|
|
|
|
+ },
|
|
|
|
|
+ ]
|
|
|
|
|
+ : [];
|
|
|
|
|
+ faceImageList.value = faceImg
|
|
|
|
|
+ ? [
|
|
|
|
|
+ {
|
|
|
|
|
+ uid: '-1',
|
|
|
|
|
+ status: 'done',
|
|
|
|
|
+ url: faceImg,
|
|
|
|
|
+ thumbUrl: faceImg,
|
|
|
|
|
+ response: { url: faceImg },
|
|
|
|
|
+ },
|
|
|
|
|
+ ]
|
|
|
|
|
+ : [];
|
|
|
|
|
+ uploadProps.showRemoveIcon = data.progress === '1';
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 存储所有选择的症状
|
|
|
|
|
+const selectedSymptomsList = ref<{ name: string; value: string }[]>([]);
|
|
|
|
|
+// 存储症状
|
|
|
|
|
+const symptomsList = ref<{ name: string; type: string }[]>([]);
|
|
|
|
|
+// 症状选择的值
|
|
|
|
|
+const symptomsValue = ref({
|
|
|
|
|
+ parent: '',
|
|
|
|
|
+ child: '',
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 处理父级点击
|
|
|
|
|
+const handleParentClick = (name: string) => {
|
|
|
|
|
+ if (symptomsValue.value.parent === name) {
|
|
|
|
|
+ // 如果点击的是当前选中的父级,则清空选择
|
|
|
|
|
+ symptomsValue.value = {
|
|
|
|
|
+ parent: '',
|
|
|
|
|
+ child: '',
|
|
|
|
|
+ };
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 选择新的父级
|
|
|
|
|
+ symptomsValue.value = {
|
|
|
|
|
+ parent: name,
|
|
|
|
|
+ child: '',
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 处理子级选择变化
|
|
|
|
|
+const handleChildChange = (e: any) => {
|
|
|
|
|
+ const selectedValue = e.target.value;
|
|
|
|
|
+ const currentParent = symptomsValue.value.parent;
|
|
|
|
|
+ // 找到当前症状
|
|
|
|
|
+ const symptom = activeObj.value.symptomsData.find((item) => item.name === currentParent);
|
|
|
|
|
+
|
|
|
|
|
+ if (symptom) {
|
|
|
|
|
+ // 如果点击的是当前选中的值,则取消选择
|
|
|
|
|
+ if (symptom.selectedId === selectedValue) {
|
|
|
|
|
+ // 取消选择
|
|
|
|
|
+ symptom.selectedValue = '';
|
|
|
|
|
+ symptom.selectedId = null;
|
|
|
|
|
+
|
|
|
|
|
+ // 从已选择的症状列表中移除
|
|
|
|
|
+ const index = selectedSymptomsList.value.findIndex((item) => item.name === currentParent);
|
|
|
|
|
+ if (index > -1) {
|
|
|
|
|
+ selectedSymptomsList.value.splice(index, 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 选择新的值
|
|
|
|
|
+ const child = symptom.child.find((item) => item.value === selectedValue);
|
|
|
|
|
+ if (child) {
|
|
|
|
|
+ symptom.selectedValue = selectedValue;
|
|
|
|
|
+ symptom.selectedId = selectedValue;
|
|
|
|
|
+
|
|
|
|
|
+ // 更新已选择的症状列表
|
|
|
|
|
+ const existingIndex = selectedSymptomsList.value.findIndex((item) => item.name === currentParent);
|
|
|
|
|
+ if (existingIndex > -1) {
|
|
|
|
|
+ selectedSymptomsList.value[existingIndex].value = selectedValue;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ selectedSymptomsList.value.push({
|
|
|
|
|
+ name: currentParent,
|
|
|
|
|
+ value: selectedValue,
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ symptomsValue.value.parent = '';
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 是否出现新症状
|
|
|
|
|
+const selectSymptomsData = reactive([
|
|
|
|
|
+ { name: '有', id: 'Y' },
|
|
|
|
|
+ { name: '没有', id: 'N' },
|
|
|
|
|
+]);
|
|
|
|
|
+
|
|
|
|
|
+const uploadProps = reactive({ showRemoveIcon: true });
|
|
|
|
|
+const changeTag = (item: any) => {
|
|
|
|
|
+ activeObj.value.fillin.isHaveNewSyndrome = item.id;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const upImgList = ref<UploadFile[]>([]);
|
|
|
|
|
+const downImageList = ref<UploadFile[]>([]);
|
|
|
|
|
+const faceImageList = ref<UploadFile[]>([]);
|
|
|
|
|
+// 预览图片
|
|
|
|
|
+const handlePreview = async (file: UploadFile) => {
|
|
|
|
|
+ previewImg.value = file.response?.url ?? file.thumbUrl;
|
|
|
|
|
+ visible.value = true;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 填写随访内容
|
|
|
|
|
+function subFollowContent() {
|
|
|
|
|
+ activeObj.value.fillin.upImg = upImgList.value[0]?.response?.url;
|
|
|
|
|
+ activeObj.value.fillin.downImg = downImageList.value[0]?.response?.url;
|
|
|
|
|
+ activeObj.value.fillin.faceImg = faceImageList.value[0]?.response?.url;
|
|
|
|
|
+ symptomsList.value = [];
|
|
|
|
|
+ activeObj.value.symptomsData.forEach((item) => {
|
|
|
|
|
+ symptomsList.value.push({ name: item.name, type: item.selectedValue });
|
|
|
|
|
+ });
|
|
|
|
|
+ activeObj.value.fillin.symptomsList = symptomsList.value;
|
|
|
|
|
+ FillFollowContentMethod(activeObj.value).then(() => {
|
|
|
|
|
+ notification.success({
|
|
|
|
|
+ message: '',
|
|
|
|
|
+ description: '提交成功!',
|
|
|
|
|
+ });
|
|
|
|
|
+ emits('submit');
|
|
|
|
|
+ load();
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 取消提交
|
|
|
|
|
+function cancelFollowContent() {
|
|
|
|
|
+ VxeUI.modal.close(`follow-modal`);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function customUpload(e: any) {
|
|
|
|
|
+ // uploadApi 你的二次封装上传接口
|
|
|
|
|
+ UploadIFile(e.file)
|
|
|
|
|
+ .then((res) => {
|
|
|
|
|
+ // 调用实例的成功方法通知组件该文件上传成功
|
|
|
|
|
+ e.onSuccess(res, e);
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch((err) => {
|
|
|
|
|
+ // 调用实例的失败方法通知组件该文件上传失败
|
|
|
|
|
+ e.onError(err);
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const visible = ref<boolean>(false);
|
|
|
|
|
+const setVisible = (value: boolean): void => {
|
|
|
|
|
+ visible.value = value;
|
|
|
|
|
+};
|
|
|
|
|
+const previewImg = ref<string>('');
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div class="flex font-bold">
|
|
|
|
|
+ <!-- 左边-->
|
|
|
|
|
+ <div class="animated-vertical-tabs">
|
|
|
|
|
+ <div class="tab-list">
|
|
|
|
|
+ <div class="font-bold h-8 pt-3 mb-3 ml-2">{{ activeObj?.followupPlanName }}</div>
|
|
|
|
|
+ <div
|
|
|
|
|
+ style="font-size: 14px"
|
|
|
|
|
+ v-for="(content, index) in contentArr"
|
|
|
|
|
+ :key="content.id"
|
|
|
|
|
+ class="tab-item mb-3"
|
|
|
|
|
+ :class="{ active: activeKey === content.id }"
|
|
|
|
|
+ @click="changeTab(content, index)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div>{{ content.followupTaskName }}</div>
|
|
|
|
|
+ <span class="tab-label">{{ content.arrangeTime }}</span>
|
|
|
|
|
+ <div :class="content.progress == 1 ? 'text-red-600' : content.progress == 2 ? 'text-green-900' : content.progress == 3 ? 'text-blue-900' : ''">
|
|
|
|
|
+ {{ content.progress === '1' ? '未完成' : content.progress === '2' ? '已完成' : '未开始' }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 右边-->
|
|
|
|
|
+ <div :key="activeObj.id">
|
|
|
|
|
+ <div class="h-8 text-center">
|
|
|
|
|
+ {{ activeObj?.followupTaskName }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="mb-2 text-center">预定随访时间:{{ activeObj?.arrangeTime }}</div>
|
|
|
|
|
+ <div class="mb-2 ml-2">
|
|
|
|
|
+ 您好,您于<span class="text-blue-600">【{{ activeObj?.medicalTime }}】</span>在我院<span class="text-blue-600">【{{ activeObj?.institutionName }}】</span>因为<span
|
|
|
|
|
+ class="text-blue-600"
|
|
|
|
|
+ >【{{ activeObj?.diagnosis }}】</span
|
|
|
|
|
+ >就诊。接下来我们将对您进行一个随访,请根据目前的实际情况回答。
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2"
|
|
|
|
|
+ v-if="(activeObj?.progress === '1' && activeObj?.symptomsData?.length > 0) || (activeObj.progress === '2' && activeObj?.fillin?.symptomsList?.length > 0)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="mb-3 border-b-0">
|
|
|
|
|
+ 1、请问您的症状有没有<span class="text-red-600">好转</span>或者<span class="text-red-600">恶化</span>?请先点击症状,再选择好转还是恶化。(没有操作的症状默认没有变化)
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="ml-4" v-if="activeObj.progress === '1'">
|
|
|
|
|
+ <!-- 症状选择器 -->
|
|
|
|
|
+ <div class="symptom-container flex flex-wrap">
|
|
|
|
|
+ <div v-for="item in activeObj?.symptomsData" :key="item.name" class="symptom-item">
|
|
|
|
|
+ <div class="symptom-button" @click="activeObj.progress !== '0' ? handleParentClick(item.name) : ''" :class="{ 'disabled': activeObj.progress === '0' }">
|
|
|
|
|
+ <span>{{ item.name }}</span>
|
|
|
|
|
+ <span v-if="item.selectedValue" class="selected-value">: {{ item.selectedValue }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-show="symptomsValue.parent === item.name" class="symptom-options">
|
|
|
|
|
+ <a-radio-group :model-value="item.selectedId" @change="activeObj.progress !== '0' && handleChildChange($event)" class="flex flex-wrap" :disabled="activeObj.progress === '0'">
|
|
|
|
|
+ <a-radio :value="tag.value" v-for="tag in item.child" :key="tag.value" class="mr-4">
|
|
|
|
|
+ {{ tag.label }}
|
|
|
|
|
+ </a-radio>
|
|
|
|
|
+ </a-radio-group>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 已经评估过 -->
|
|
|
|
|
+ <div v-else>
|
|
|
|
|
+ <div class="symptom-container flex flex-wrap">
|
|
|
|
|
+ <div v-for="item in activeObj?.fillin?.symptomsList" :key="item.name" class="symptom-item">
|
|
|
|
|
+ <div class="symptom-button">
|
|
|
|
|
+ <span>{{ item.name }}</span>
|
|
|
|
|
+ <span class="selected-value">: {{ item.type }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 第二个-->
|
|
|
|
|
+ <div class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2">
|
|
|
|
|
+ <div class="mb-3">2、请问有没有出现<span class="text-red-600">新</span>的症状?</div>
|
|
|
|
|
+ <div class="mb-8 ml-4 flex">
|
|
|
|
|
+ <div v-for="symptoms in selectSymptomsData" :key="symptoms.name" class="mr-4" @click="activeObj?.progress === '1' ? changeTag(symptoms) : ''">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div class="border-solid b-1 w-20 text-center" :class="[activeObj.fillin.isHaveNewSyndrome === symptoms.id ? 'bg-blue text-#fff' : '', activeObj.progress === '0' ? 'disabled' : '']">
|
|
|
|
|
+ {{ symptoms.name }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 第三个-->
|
|
|
|
|
+ <div class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2" v-if="activeObj.fillin?.isHaveNewSyndrome === 'Y'">
|
|
|
|
|
+ <div class="mb-3">3、请描述新的症状</div>
|
|
|
|
|
+ <div class="mb-4 ml-4">
|
|
|
|
|
+ <a-input v-model:value="activeObj.fillin.newSyndrome" placeholder="请输入" :auto-size="{ minRows: 2, maxRows: 5 }" :disabled="activeObj.progress === '2' || activeObj.progress === '0'" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 第四个-->
|
|
|
|
|
+ <div class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2">
|
|
|
|
|
+ <div class="mb-3">4、如果有其他情况,请留言</div>
|
|
|
|
|
+ <div class="mb-4 ml-4">
|
|
|
|
|
+ <a-input v-model:value="activeObj.fillin.otherDesc" placeholder="请输入" :auto-size="{ minRows: 2, maxRows: 5 }" :disabled="activeObj.progress === '2' || activeObj.progress === '0'" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 第五个-->
|
|
|
|
|
+ <div class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2">
|
|
|
|
|
+ <div class="mb-3">5、为了医生更好地了解您的恢复情况,需要您上传舌面象照片</div>
|
|
|
|
|
+ <div class="mb-4 ml-3">
|
|
|
|
|
+ <!-- 上传图片-->
|
|
|
|
|
+ <div class="flex">
|
|
|
|
|
+ <!-- 舌面-->
|
|
|
|
|
+ <div class="flex flex-col items-center mr-4">
|
|
|
|
|
+ <a-upload
|
|
|
|
|
+ :showUploadList="uploadProps"
|
|
|
|
|
+ v-model:file-list="upImgList"
|
|
|
|
|
+ list-type="picture-card"
|
|
|
|
|
+ @preview="handlePreview"
|
|
|
|
|
+ :maxCount="1"
|
|
|
|
|
+ :customRequest="customUpload"
|
|
|
|
|
+ :disabled="activeObj.progress === '2' || activeObj.progress === '0'"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div v-if="upImgList.length < 1">
|
|
|
|
|
+ <plus-outlined />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-upload>
|
|
|
|
|
+ <div class="font-bold">舌面</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 舌下-->
|
|
|
|
|
+ <div class="flex flex-col items-center mr-4">
|
|
|
|
|
+ <a-upload
|
|
|
|
|
+ :showUploadList="uploadProps"
|
|
|
|
|
+ v-model:file-list="downImageList"
|
|
|
|
|
+ list-type="picture-card"
|
|
|
|
|
+ @preview="handlePreview"
|
|
|
|
|
+ :maxCount="1"
|
|
|
|
|
+ :customRequest="customUpload"
|
|
|
|
|
+ :disabled="activeObj.progress === '2' || activeObj.progress === '0'"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div v-if="downImageList.length < 1">
|
|
|
|
|
+ <plus-outlined />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-upload>
|
|
|
|
|
+ <div class="font-bold">舌下</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 面部-->
|
|
|
|
|
+ <div class="flex flex-col items-center mr-4">
|
|
|
|
|
+ <a-upload
|
|
|
|
|
+ :showUploadList="uploadProps"
|
|
|
|
|
+ v-model:file-list="faceImageList"
|
|
|
|
|
+ list-type="picture-card"
|
|
|
|
|
+ @preview="handlePreview"
|
|
|
|
|
+ :maxCount="1"
|
|
|
|
|
+ :customRequest="customUpload"
|
|
|
|
|
+ :disabled="activeObj.progress === '2' || activeObj.progress === '0'"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div v-if="faceImageList.length < 1">
|
|
|
|
|
+ <plus-outlined />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-upload>
|
|
|
|
|
+ <div class="font-bold">面部</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- --------end-->
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <a-image
|
|
|
|
|
+ :width="200"
|
|
|
|
|
+ :style="{ display: 'none' }"
|
|
|
|
|
+ :preview="{
|
|
|
|
|
+ visible,
|
|
|
|
|
+ onVisibleChange: setVisible,
|
|
|
|
|
+ }"
|
|
|
|
|
+ :src="previewImg"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- -->
|
|
|
|
|
+ <div class="ml-2 mt-1">
|
|
|
|
|
+ 感谢您的配合,为了更好地了解您的回复情况,我们将会在<span class="text-blue-600"> {{ activeObj?.arrangeTime }} </span
|
|
|
|
|
+ >再次对您进行随访,届时请点击随访链接参与,再次感谢您!
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flex items-center justify-center mt-6 mb-6">
|
|
|
|
|
+ <a-button size="small" class="mr-4" @click="cancelFollowContent">取消</a-button>
|
|
|
|
|
+ <a-button type="primary" size="small" @click="subFollowContent" v-show="activeObj.progress === '1'">提交 </a-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+.ant-upload-select-picture-card i {
|
|
|
|
|
+ font-size: 32px;
|
|
|
|
|
+ color: #999;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.ant-upload-select-picture-card .ant-upload-text {
|
|
|
|
|
+ margin-top: 8px;
|
|
|
|
|
+ color: #666;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.mesh-grid {
|
|
|
|
|
+ border-collapse: collapse;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.mesh-grid td {
|
|
|
|
|
+ border: 1px solid black;
|
|
|
|
|
+ width: 100px;
|
|
|
|
|
+ padding: 20px 20px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.animated-vertical-tabs {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ height: 730px;
|
|
|
|
|
+ width: 17%;
|
|
|
|
|
+ overflow: auto;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tab-list {
|
|
|
|
|
+ border-right: 1px solid #f0f0f0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tab-item {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ padding: 10px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tab-item:hover {
|
|
|
|
|
+ background-color: rgba(24, 144, 255, 0.06);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tab-item.active {
|
|
|
|
|
+ background: lightgray;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tab-indicator {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ right: -1px;
|
|
|
|
|
+ width: 2px;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ background-color: #1890ff;
|
|
|
|
|
+ transform: scaleY(0);
|
|
|
|
|
+ transform-origin: center top;
|
|
|
|
|
+ transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tab-item.active .tab-indicator {
|
|
|
|
|
+ transform: scaleY(1);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.tab-content {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ padding: 0 24px;
|
|
|
|
|
+ overflow: auto;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.fade-enter-active,
|
|
|
|
|
+.fade-leave-active {
|
|
|
|
|
+ transition: opacity 0.3s ease;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.fade-enter-from,
|
|
|
|
|
+.fade-leave-to {
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 症状选择器样式
|
|
|
|
|
+.symptom-container {
|
|
|
|
|
+ .symptom-item {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ margin-right: 16px;
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+
|
|
|
|
|
+ .symptom-button {
|
|
|
|
|
+ min-width: 100px;
|
|
|
|
|
+ padding: 8px 16px;
|
|
|
|
|
+ border: 1px solid #d9d9d9;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ transition: all 0.3s;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ border-color: #40a9ff;
|
|
|
|
|
+ color: #40a9ff;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.active {
|
|
|
|
|
+ border-color: #1890ff;
|
|
|
|
|
+ color: #1890ff;
|
|
|
|
|
+ background: rgba(24, 144, 255, 0.1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.has-value {
|
|
|
|
|
+ border-color: #52c41a;
|
|
|
|
|
+ color: #52c41a;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .selected-value {
|
|
|
|
|
+ margin-left: 4px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .symptom-options {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 100%;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ z-index: 1;
|
|
|
|
|
+ margin-top: 8px;
|
|
|
|
|
+ padding: 8px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border: 1px solid #d9d9d9;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
|
|
|
+ animation: fadeIn 0.3s;
|
|
|
|
|
+
|
|
|
|
|
+ .ant-radio-group {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .ant-radio-wrapper {
|
|
|
|
|
+ padding: 4px 8px;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ transition: all 0.3s;
|
|
|
|
|
+
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ background: rgba(24, 144, 255, 0.1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 已选择症状标签样式
|
|
|
|
|
+.selected-symptoms {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+
|
|
|
|
|
+ .ant-tag {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ padding: 4px 8px;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ transition: all 0.3s;
|
|
|
|
|
+
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ background: rgba(24, 144, 255, 0.1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 动画
|
|
|
|
|
+@keyframes fadeIn {
|
|
|
|
|
+ from {
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+ transform: translateY(-10px);
|
|
|
|
|
+ }
|
|
|
|
|
+ to {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+ transform: translateY(0);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 整体布局优化
|
|
|
|
|
+.border-1 {
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+ padding: 16px;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.mb-8 {
|
|
|
|
|
+ margin-bottom: 32px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.ml-4 {
|
|
|
|
|
+ margin-left: 16px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.text-blue-600 {
|
|
|
|
|
+ color: #1890ff;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.text-red-600 {
|
|
|
|
|
+ color: #ff4d4f;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.font-bold {
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 禁用状态样式
|
|
|
|
|
+.disabled {
|
|
|
|
|
+ opacity: 0.5;
|
|
|
|
|
+ cursor: not-allowed !important;
|
|
|
|
|
+ pointer-events: none;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.symptom-button.disabled {
|
|
|
|
|
+ background-color: #f5f5f5;
|
|
|
|
|
+ color: #999;
|
|
|
|
|
+ border-color: #d9d9d9;
|
|
|
|
|
+ cursor: not-allowed;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.symptom-button.disabled:hover {
|
|
|
|
|
+ border-color: #d9d9d9;
|
|
|
|
|
+ color: #999;
|
|
|
|
|
+ background-color: #f5f5f5;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|