init
This commit is contained in:
2025-06-27 17:42:38 +08:00
commit bd6402478b
5317 changed files with 785994 additions and 0 deletions
@@ -0,0 +1,466 @@
<template>
<div class="traceability">
<div class="header">
<div class="header-font">
<span>{{ type.title }}</span>
<span>{{ type.sub }}</span>
</div>
<img :src="headerIcon" />
</div>
<div class="container">
<div class="question-box" v-for="(quesItem, index) in questionList" :key="index">
<div class="question-header">
<div>{{ quesItem.name }}</div>
<div v-if="qustType === '1'" @click="handleLookRes(quesItem)">查看最新检查结果</div>
</div>
<template v-for="(qus, quIndex) in quesItem.question">
<div class="question-title" v-if="qus.isShow" :key="quIndex">
<div class="title">
<span class="tips">*</span>
<div>
<span>{{ quIndex + 1 }}</span>
<span>{{ qus.title }}</span>
</div>
</div>
<template v-if="qus.inputType === 'radio'">
<a-radio-group v-model:value="qus.answer" @change="(e) => changeRadio(index, e, qus.type)">
<a-radio class="radioStyle" v-for="(optionItem, indexItem) in qus.options" :key="indexItem" :value="optionItem.value">
{{ optionItem.name }}</a-radio
>
</a-radio-group>
</template>
<template v-if="qus.inputType === 'text'">
<div class="error-box">
<div class="error-item" v-for="(optionItem, optionIndex) in qus.options" :key="optionIndex">
<van-field class="field-input" v-model="optionItem.remark" :label="optionItem.sizeMsg" />
<van-field class="field-input" v-model="optionItem.position" :label="optionItem.positionMsg" />
<van-icon
v-if="optionIndex !== 0"
class="deleteIcon"
size="26"
name="clear"
color="#666666"
@click="deleteICon(index, optionIndex)"
/>
</div>
</div>
<div class="error-btn" @click="addInfo(index, qus.options, qus.type)">添加斑块信息</div>
</template>
<template v-if="qus.inputType === 'input'">
<van-field type="number" class="field-answer" v-model="qus.answer" />
</template>
</div>
</template>
</div>
</div>
<div class="bottom-btn">
<van-button class="btn" round type="primary" @click="handleSubmit">提交</van-button>
</div>
<van-overlay :show="popupShow">
<div class="dialog">
<img :src="resultIcon" />
<div class="content-overlay">
<div class="popup-title">{{ detailRes?.name }}</div>
<div v-if="detailRes?.conclusion !== ''" class="popup-con">{{ detailRes?.conclusion }}</div>
<div v-else class="no-date">暂无结果</div>
</div>
<van-icon class="closeIcon" name="close" color="#ffffff" size="36" @click="handleClose" />
</div>
</van-overlay>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import headerIcon from '/@/assets/images/traceability/headerImage.png';
import resultIcon from '/@/assets/images/traceability/resultIcon.png';
import { useTypeHeader } from '/@/views/23intervene/ImageTraceability/traceabilityHooks';
import { useRouter, useRoute } from 'vue-router';
import { showToast, showSuccessToast, showFailToast } from 'vant';
import {
getBehaviorSurveyApi,
getEnvironmentSurveyApi,
getSurveyApi,
submitBehaviorSurveyApi,
submitEnvironmentSurveyApi,
submitSurveyApi,
} from '/@/views/23intervene/ImageTraceability/tranceabilityApi';
import { destroyPage } from '/@/hooks/openPage';
import { useLoading } from '/@/utils/compUtils';
const questionList = ref([]);
const submitParams = ref({});
const popupShow = ref(false);
const router = useRouter();
const route = useRoute();
const detailRes = ref({});
const isEdit = ref(''); // 0 新增 1编辑
const qustType = route.query?.traceabType;
const type = useTypeHeader(qustType); // 1 影像溯源、2 行为溯源、 3环境溯源
const { loadingSpinner, loadingClose } = useLoading();
onMounted(() => {
useTypeApi(qustType).getApi();
});
function useTypeApi(type: number) {
const data = {
1: {
getApi: getSurvey,
subApi: subSurvey,
},
2: {
getApi: getBehavior,
subApi: subBehavior,
},
3: {
getApi: getEnvironment,
subApi: subEnvironment,
},
};
return data[type];
}
/**
*
* @param index
* @param val 0 不存在异常、否, 1 存在异常、是
* @param qustType 1 影像溯源、2 行为溯源、3环境溯源
*/
function changeRadio(index: number, val: number, field: string) {
let data = val.target.value;
let qusData = questionList.value;
submitParams.value[field] = data;
if (qustType === '1') {
qusData[index].question[1].isShow = data === 1;
if (data === 0) {
let optionsList = qusData[index].question[1].options;
if (optionsList.length > 1) {
optionsList.splice(1, optionsList.length - 1);
optionsList[0].size = '';
optionsList[0].position = '';
}
}
} else if (qustType === '2') {
let qusList = qusData[index].question;
if (qusList.length > 1) {
qusList.filter((v: any) => {
if (v.inputType === 'input') {
if (v.answer !== '') {
v.answer = '';
}
v.isShow = data === 1;
}
});
}
}
questionList.value = qusData;
}
function addInfo(index: number, data: Array) {
let dataParams = {
remark: '',
position: '',
sizeMsg: data[0].sizeMsg,
positionMsg: data[0].positionMsg,
};
questionList.value[index].question[1].options.push(dataParams);
}
function deleteICon(index: number, optionIndex: number) {
questionList.value[index].question[1].options.splice(optionIndex, 1);
}
function getParams() {
questionList.value.map((quItem: any) => {
quItem.question.map((item: any) => {
if (item.inputType === 'text' && item.isShow) {
submitParams.value[item.type] = item.options;
}
if (['radio', 'input'].includes(item.inputType) && item.isShow) {
submitParams.value[item.type] = item.answer;
}
});
});
return submitParams.value;
}
// 影像
async function getSurvey() {
const { code, result } = await getSurveyApi({});
getResult(code, result);
}
async function subSurvey() {
const { code, result, message } = await submitSurveyApi(getParams());
subResult(code, result, message);
}
// 行为
async function getBehavior() {
const { code, result } = await getBehaviorSurveyApi({});
getResult(code, result);
}
async function subBehavior() {
const { code, result, message } = await submitBehaviorSurveyApi(getParams());
subResult(code, result, message);
}
// 环境
async function getEnvironment() {
const { code, result } = await getEnvironmentSurveyApi({});
getResult(code, result);
}
async function subEnvironment() {
const { code, result, message } = await submitEnvironmentSurveyApi(getParams());
subResult(code, result, message);
}
function getResult(code: number, result: any) {
if (code === 200) {
isEdit.value = result.status;
questionList.value = result.questionList;
}
}
function subResult(code: number, result: any, message: string) {
if (code === 200) {
loadingClose();
showSuccessToast('提交成功');
try {
destroyPage();
} catch {
router.go(-1);
}
} else {
loadingClose();
showFailToast(message);
}
}
async function handleSubmit() {
let vis = true;
questionList.value.map((v: any) => {
v.question.map((qusItem: any) => {
if (qusItem.isShow && ['radio', 'input'].includes(qusItem.inputType)) {
if (qusItem.answer === '') {
vis = false;
showToast('请填写完问卷');
}
}
if (qusItem.isShow && qusItem.inputType === 'text') {
qusItem.options.map((e: any) => {
if (e.position === '' || e.remark === '') {
vis = false;
showToast('请填写异常信息');
}
});
}
});
});
if (vis) {
loadingSpinner();
useTypeApi(qustType).subApi();
}
}
async function handleLookRes(item: any) {
popupShow.value = true;
detailRes.value = item;
}
function handleClose() {
popupShow.value = false;
}
</script>
<style scoped lang="less">
.traceability {
width: 100%;
height: 100vh;
background-color: #f5f7fb;
position: relative;
.header {
z-index: 4;
width: 100%;
height: 140px;
position: relative;
img {
width: 100%;
height: 100%;
}
.header-font {
position: absolute;
left: 7%;
top: 22%;
display: flex;
flex-direction: column;
font-weight: bold;
font-style: italic;
span:nth-child(1) {
font-size: 30px;
color: #ffffff;
}
span:nth-child(2) {
margin-top: -12px;
color: rgba(255, 255, 255, 0.1);
font-size: 22px;
}
}
}
.container {
width: 100%;
height: calc(100vh - 180px);
overflow-y: auto;
position: absolute;
left: 0;
top: 125px;
z-index: 99;
.question-box {
margin-bottom: 18px;
border-radius: 16px;
background-color: #ffffff;
.question-header {
border-top-left-radius: 16px;
border-top-right-radius: 16px;
display: flex;
justify-content: space-between;
height: 43px;
padding: 20px;
background: linear-gradient(180deg, rgba(26, 104, 238, 0.2) 0%, rgba(48, 160, 226, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
> div:nth-child(1) {
font-size: 16px;
color: #333333;
font-weight: bold;
}
> div:nth-child(2) {
color: #1a68ee;
font-size: 14px;
}
}
.question-title {
padding: 20px;
.title {
color: #333b42;
font-weight: bold;
padding-bottom: 20px;
position: relative;
.tips {
color: #ed2a26;
font-size: 18px;
font-weight: bold;
position: absolute;
top: -2px;
left: -10px;
}
}
.radioStyle {
display: block;
height: 40px;
}
.error-item {
position: relative;
margin-top: 12px;
border-radius: 16px;
& > .field-input:nth-child(1) {
border-top-left-radius: 16px;
border-top-right-radius: 16px;
}
& > .field-input:nth-child(2) {
border-bottom-left-radius: 16px;
border-bottom-right-radius: 16px;
}
& > .deleteIcon {
position: absolute;
right: -10px;
top: -10px;
z-index: 9;
}
:deep(.van-field__control:-webkit-autofill) {
background-color: transparent;
padding-left: 10px;
transition: background-color 0s linear 3600s;
}
:deep(.van-field__control) {
padding-left: 10px;
}
:deep(.van-cell) {
background-color: #eff5ff;
line-height: 38px;
}
:deep(.van-field__label) {
font-weight: bold;
}
:deep(.van-cell__value) {
height: 38px;
background-color: #ffffff;
}
}
.error-btn {
text-align: center;
color: #1a68ee;
padding: 20px 0px;
}
.field-answer {
border-bottom: 1px solid #eaecf1;
}
}
}
}
.bottom-btn {
width: 100%;
position: absolute;
left: 0;
bottom: 0;
height: 50px;
background-color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
.btn {
width: 80%;
height: 40px;
line-height: 40px;
background-color: #1a68ee;
border-radius: 16px;
color: #ffffff;
text-align: center;
}
}
:deep(.ant-radio-group) {
width: 100%;
}
:deep(.van-overlay){
z-index: 99;
}
.dialog {
position: absolute;
top: 30%;
left: 11%;
width: 80%;
margin: 0 auto;
img {
position: absolute;
top: -35px;
left: 43%;
width: 15%;
}
.content-overlay {
background-color: #ffffff;
border-radius: 16px;
padding: 40px 20px 20px 20px;
.popup-title {
font-size: 18px;
font-weight: bold;
padding-bottom: 10px;
}
.popup-con {
font-size: 15px;
line-height: 25px;
max-height: 120px;
overflow-y: auto;
text-align: left;
}
.no-date {
text-align: center;
color: #999999;
height: 120px;
line-height: 120px;
}
}
.closeIcon {
position: relative;
left: 45%;
padding-top: 10%;
}
}
}
</style>
@@ -0,0 +1,18 @@
export function useTypeHeader(type: number) {
const data = {
1: {
title: '影像溯源',
sub: 'IMAGE TRACEABILITY',
},
2: {
title: '行为溯源',
sub: 'BEHAVIOR TRACEABILITY',
},
3: {
title: '环境溯源',
sub: 'ENVIRONMENTAL TRACEABILITY',
},
};
// @ts-ignore
return data[type];
}
@@ -0,0 +1,21 @@
import { get, post } from '/@/views/mobile/api/api';
const prefix: string = import.meta.env.VITE_GLOB_APP_PREFIX || '';
// 获取影像溯源
export const getSurveyApi = (params: any) => get(`${prefix}/cancer/api/getImageSurvey`, params);
// 提交影像溯源
export const submitSurveyApi = (params: any) => post(`${prefix}/cancer/api/postImageSurvey`, params);
// 获取行为溯源
export const getBehaviorSurveyApi = (params: any) => get(`${prefix}/cancer/api/getBehaviorSurvey`, params);
// 提交行为溯源
export const submitBehaviorSurveyApi = (params: any) => post(`${prefix}/cancer/api/postBehaviorSurvey`, params);
// 获取环境溯源
export const getEnvironmentSurveyApi = (params: any) => get(`${prefix}/cancer/api/getEnvironmentSurvey`, params);
// 提交环境溯源
export const submitEnvironmentSurveyApi = (params: any) => post(`${prefix}/cancer/api/postEnvironmentSurvey`, params);