|
|
@@ -0,0 +1,691 @@
|
|
|
+<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';
|
|
|
+
|
|
|
+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({ 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.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) => {
|
|
|
+ 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.downImg = upImgList.value[0]?.response?.url;
|
|
|
+ activeObj.value.fillin.upImg = 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;
|
|
|
+ // console.log('填写的随访内容', activeObj.value.fillin);
|
|
|
+ // return;
|
|
|
+ FillFollowContentMethod(activeObj.value).then(() => {
|
|
|
+ notification.success({
|
|
|
+ message: '',
|
|
|
+ description: '提交成功!',
|
|
|
+ });
|
|
|
+ emits('submit');
|
|
|
+ load();
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 取消提交
|
|
|
+function cancelFollowContent() {
|
|
|
+ VxeUI.modal.close(`follow-modal`);
|
|
|
+}
|
|
|
+
|
|
|
+function customUpload(e) {
|
|
|
+ // uploadApi 你的二次封装上传接口
|
|
|
+ UploadIFile(e.file)
|
|
|
+ .then((res) => {
|
|
|
+ // 调用实例的成功方法通知组件该文件上传成功
|
|
|
+ e.onSuccess(res, e);
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ // 调用实例的失败方法通知组件该文件上传失败
|
|
|
+ e.onError(err);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+const visible = ref<boolean>(false);
|
|
|
+const setVisible = (value): 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">失眠门诊随访</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="w-full flex flex-col items-center h-8 mb-3">
|
|
|
+ <div class="font-bold mb-2">
|
|
|
+ {{ activeObj?.followupTaskName }}
|
|
|
+ </div>
|
|
|
+ <div>预定随访时间:{{ activeObj?.arrangeTime }}</div>
|
|
|
+ </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">
|
|
|
+ <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="handleParentClick(item.name)">
|
|
|
+ <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="handleChildChange"
|
|
|
+ class="flex flex-wrap"
|
|
|
+ >
|
|
|
+ <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.value?.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="changeTag(symptoms)"
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <div
|
|
|
+ class="border-solid b-1 w-20 text-center"
|
|
|
+ :class="
|
|
|
+ activeObj.fillin.isHaveNewSyndrome === symptoms.id ? 'bg-blue text-#fff' : ''
|
|
|
+ "
|
|
|
+ >
|
|
|
+ {{ symptoms.name }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 第三个-->
|
|
|
+ <div class="border-1 border-solid border-gray:50 pl-2 pd-10 ml-2">
|
|
|
+ <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 }"
|
|
|
+ />
|
|
|
+ </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 }"
|
|
|
+ />
|
|
|
+ </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"
|
|
|
+ >
|
|
|
+ <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"
|
|
|
+ >
|
|
|
+ <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"
|
|
|
+ >
|
|
|
+ <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">提交</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;
|
|
|
+}
|
|
|
+</style>
|