意见反馈影像上传、影像质疑、一致性核查绑定访视
continuous-integration/drone/push Build is passing Details

uat_us
DESKTOP-6C3NK6N\WXS 2024-08-21 13:46:46 +08:00
parent e961829ef1
commit f5c4b49e6f
8 changed files with 1990 additions and 1076 deletions

View File

@ -3,7 +3,7 @@ import FEEDBACKCOMP from "./index.vue";
const FBConstructor = Vue.extend(FEEDBACKCOMP); const FBConstructor = Vue.extend(FEEDBACKCOMP);
const FB = options => { const FB = options => {
const { type, callBack, cancelBack, trialId = null, Id = null, visitTaskId = null } = options; const { type, callBack, cancelBack, trialId = null, Id = null, visitTaskId = null, SubjectVisitId = null } = options;
if (!type) throw `type is requred.but ${type}` if (!type) throw `type is requred.but ${type}`
const id = `FB${new Date().getTime()}`; const id = `FB${new Date().getTime()}`;
const instance = new FBConstructor(); const instance = new FBConstructor();
@ -12,7 +12,7 @@ const FB = options => {
if (instance.vm.visible) return; if (instance.vm.visible) return;
document.body.appendChild(instance.vm.$el); document.body.appendChild(instance.vm.$el);
console.log(type); console.log(type);
instance.vm.open({ type, trialId, Id, visitTaskId }); instance.vm.open({ type, trialId, Id, visitTaskId, SubjectVisitId });
instance.vm.$on("success", (Id) => { instance.vm.$on("success", (Id) => {
if (callBack) callBack(); if (callBack) callBack();

View File

@ -14,7 +14,7 @@
{{ title }} {{ title }}
</div> </div>
<!-- 项目详情 --> <!-- 项目详情 -->
<div class="trialsBox" v-if="visitTaskId"> <div class="trialsBox" v-if="visitTaskId || SubjectVisitId">
<el-form <el-form
label-position="right" label-position="right"
:model="form" :model="form"
@ -187,6 +187,7 @@ export default {
TrialSiteId: null, TrialSiteId: null,
TrialId: null, TrialId: null,
VisitTaskId: null, VisitTaskId: null,
SubjectVisitId: null,
ScreenshotList: [], ScreenshotList: [],
ScreenshotListStr: null, ScreenshotListStr: null,
}, },
@ -251,16 +252,15 @@ export default {
}, },
methods: { methods: {
open(data) { open(data) {
let { type, trialId, Id, visitTaskId } = data; let { type, trialId, Id, visitTaskId, SubjectVisitId } = data;
this.type = type; this.type = type;
this.trialId = trialId; this.trialId = trialId;
this.Id = Id; this.Id = Id;
this.visitTaskId = visitTaskId; this.visitTaskId = visitTaskId;
console.log(visitTaskId, "visitTaskId"); this.SubjectVisitId = SubjectVisitId;
if (visitTaskId) { if (visitTaskId) {
this.isImgfail = true; this.isImgfail = true;
} }
console.log(this.isImgfail, "isImgfail");
this.setTypeOption(); this.setTypeOption();
if (!Id) { if (!Id) {
this.title = this.setTitle(); this.title = this.setTitle();
@ -284,6 +284,9 @@ export default {
if (this.visitTaskId) { if (this.visitTaskId) {
this.form.VisitTaskId = this.visitTaskId; this.form.VisitTaskId = this.visitTaskId;
} }
if (this.SubjectVisitId) {
this.form.SubjectVisitId = this.SubjectVisitId;
}
if (this.Id) { if (this.Id) {
this.form.Id = this.Id; this.form.Id = this.Id;
} }
@ -336,6 +339,9 @@ export default {
if (res.Result.VisitTaskId) { if (res.Result.VisitTaskId) {
this.visitTaskId = res.Result.VisitTaskId; this.visitTaskId = res.Result.VisitTaskId;
} }
if (res.Result.SubjectVisitId) {
this.SubjectVisitId = res.Result.SubjectVisitId;
}
let code = this.$fd("UserType", res.Result.UserTypeEnum); let code = this.$fd("UserType", res.Result.UserTypeEnum);
this.title = this.setTitle(code, res.Result.FeedBackFullName); this.title = this.setTitle(code, res.Result.FeedBackFullName);
if (visitTaskId) { if (visitTaskId) {

View File

@ -11,7 +11,8 @@ const getDefaultState = () => {
config: {}, config: {},
uploadTip: null, uploadTip: null,
timer: null, timer: null,
whiteList: [] whiteList: [],
checkTaskId: null
} }
} }

View File

@ -347,3 +347,6 @@ body .el-table th.gutter {
background: #000; background: #000;
z-index: 3999; z-index: 3999;
} }
.el-message-box__wrapper{
z-index: 9999 !important;
}

View File

@ -58,6 +58,7 @@ export default {
this.$FB({ this.$FB({
type: "feedback", type: "feedback",
trialId: this.$route.query.trialId, trialId: this.$route.query.trialId,
SubjectVisitId: this.$store.state.trials.checkTaskId,
}); });
}, },
// //

View File

@ -1,13 +1,18 @@
<template> <template>
<BaseContainer style="height:100%;"> <BaseContainer style="height: 100%">
<!-- 搜索框 --> <!-- 搜索框 -->
<template slot="search-container"> <template slot="search-container">
<el-form :inline="true"> <el-form :inline="true">
<!-- 中心编号 --> <!-- 中心编号 -->
<el-form-item :label="$t('trials:crcQuestion:table:siteId')"> <el-form-item :label="$t('trials:crcQuestion:table:siteId')">
<el-select v-model="searchData.TrialSiteId" clearable filterable style="width:120px;"> <el-select
v-model="searchData.TrialSiteId"
clearable
filterable
style="width: 120px"
>
<el-option <el-option
v-for="(item,index) of siteOptions" v-for="(item, index) of siteOptions"
:key="index" :key="index"
:label="item.TrialSiteCode" :label="item.TrialSiteCode"
:value="item.TrialSiteId" :value="item.TrialSiteId"
@ -16,13 +21,16 @@
</el-form-item> </el-form-item>
<!-- 受试者编号 --> <!-- 受试者编号 -->
<el-form-item :label="$t('trials:crcQuestion:table:subjectId')"> <el-form-item :label="$t('trials:crcQuestion:table:subjectId')">
<el-input v-model="searchData.SubjectCode" style="width:100px;" /> <el-input v-model="searchData.SubjectCode" style="width: 100px" />
</el-form-item> </el-form-item>
<!-- 访视名称 --> <!-- 访视名称 -->
<el-form-item class="my_multiple" :label="$t('trials:crcQuestion:table:visitName')"> <el-form-item
class="my_multiple"
:label="$t('trials:crcQuestion:table:visitName')"
>
<el-select <el-select
v-model="searchData.VisitPlanArray" v-model="searchData.VisitPlanArray"
style="width:140px" style="width: 140px"
clearable clearable
multiple multiple
> >
@ -34,39 +42,70 @@
> >
<span style="float: left">{{ item.VisitName }}</span> <span style="float: left">{{ item.VisitName }}</span>
</el-option> </el-option>
<el-option <el-option key="Other" label="Out of Plan" value="1.11" />
key="Other"
label="Out of Plan"
value="1.11"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 是否超限 --> <!-- 是否超限 -->
<el-form-item :label="$t('trials:crcQuestion:table:isOverTime')"> <el-form-item :label="$t('trials:crcQuestion:table:isOverTime')">
<el-select v-model="searchData.IsOverTime" clearable style="width:120px"> <el-select
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" :key="item.id"/> v-model="searchData.IsOverTime"
clearable
style="width: 120px"
>
<el-option
v-for="item of $d.YesOrNo"
:value="item.value"
:label="item.label"
:key="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item :label="$t('trials:crcQuestion:table:isClose')"> <el-form-item :label="$t('trials:crcQuestion:table:isClose')">
<el-select v-model="searchData.IsClosed" clearable style="width:120px"> <el-select
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" :key="item.id"/> v-model="searchData.IsClosed"
clearable
style="width: 120px"
>
<el-option
v-for="item of $d.YesOrNo"
:value="item.value"
:label="item.label"
:key="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item :label="$t('trials:crcQuestion:table:reuploadSatus')"> <el-form-item :label="$t('trials:crcQuestion:table:reuploadSatus')">
<el-select v-model="searchData.ReuploadEnum" clearable style="width:120px"> <el-select
<el-option v-for="item of $d.ReuploadEnum" :value="item.value" :label="item.label" :key="item.id"/> v-model="searchData.ReuploadEnum"
clearable
style="width: 120px"
>
<el-option
v-for="item of $d.ReuploadEnum"
:value="item.value"
:label="item.label"
:key="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch"> <el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t('common:button:search') }} {{ $t("common:button:search") }}
</el-button> </el-button>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset"> <el-button
{{ $t('common:button:reset') }} type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t("common:button:reset") }}
</el-button> </el-button>
<!--导出--> <!--导出-->
<el-button type="primary" icon="el-icon-download" @click="handleExport"> <el-button
{{ $t('common:button:export') }} type="primary"
icon="el-icon-download"
@click="handleExport"
>
{{ $t("common:button:export") }}
</el-button> </el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -76,7 +115,7 @@
<template slot="main-container"> <template slot="main-container">
<el-table <el-table
v-loading="loading" v-loading="loading"
v-adaptive="{bottomOffset:60}" v-adaptive="{ bottomOffset: 60 }"
:data="list" :data="list"
stripe stripe
height="100" height="100"
@ -93,7 +132,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
type="text" type="text"
:style="{color:scope.row.IsClosed?'':'red'}" :style="{ color: scope.row.IsClosed ? '' : 'red' }"
@click="handleReplay(scope.row)" @click="handleReplay(scope.row)"
> >
{{ scope.row.ChallengeCode }} {{ scope.row.ChallengeCode }}
@ -132,16 +171,23 @@
sortable="custom" sortable="custom"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<div v-if="otherInfo.QCProcessEnum === 1"> <div v-if="otherInfo.QCProcessEnum === 1">
<!-- {{ scope.row.CurrentQCEnum === 1?'审核':'--' }} --> <!-- {{ scope.row.CurrentQCEnum === 1?'审核':'--' }} -->
<el-tag v-if="scope.row.CurrentQCEnum === 1" type="primary">{{ $fd('CurrentQCType', 0) }}</el-tag> <el-tag v-if="scope.row.CurrentQCEnum === 1" type="primary">{{
$fd("CurrentQCType", 0)
}}</el-tag>
<span v-else>--</span> <span v-else>--</span>
</div> </div>
<div v-else-if="otherInfo.QCProcessEnum === 2"> <div v-else-if="otherInfo.QCProcessEnum === 2">
<!-- {{ scope.row.CurrentQCEnum === 1?'初审':scope.row.CurrentQCEnum === 2?'复审':'--' }} --> <!-- {{ scope.row.CurrentQCEnum === 1?'初审':scope.row.CurrentQCEnum === 2?'复审':'--' }} -->
<el-tag v-if="scope.row.CurrentQCEnum === 1" type="primary">{{ $fd('CurrentQCType', scope.row.CurrentQCEnum) }}</el-tag> <el-tag v-if="scope.row.CurrentQCEnum === 1" type="primary">{{
<el-tag v-else-if="scope.row.CurrentQCEnum === 2" type="warning">{{ $fd('CurrentQCType', scope.row.CurrentQCEnum) }}</el-tag> $fd("CurrentQCType", scope.row.CurrentQCEnum)
}}</el-tag>
<el-tag
v-else-if="scope.row.CurrentQCEnum === 2"
type="warning"
>{{ $fd("CurrentQCType", scope.row.CurrentQCEnum) }}</el-tag
>
<span v-else>--</span> <span v-else>--</span>
</div> </div>
</template> </template>
@ -170,8 +216,10 @@
width="140" width="140"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag v-if="scope.row.IsOverTime" type="danger">{{ $fd('YesOrNo', scope.row.IsOverTime) }}</el-tag> <el-tag v-if="scope.row.IsOverTime" type="danger">{{
<el-tag v-else>{{ $fd('YesOrNo', scope.row.IsOverTime) }}</el-tag> $fd("YesOrNo", scope.row.IsOverTime)
}}</el-tag>
<el-tag v-else>{{ $fd("YesOrNo", scope.row.IsOverTime) }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<!-- 最新回复时间 --> <!-- 最新回复时间 -->
@ -191,8 +239,12 @@
sortable="custom" sortable="custom"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag v-if="scope.row.IsClosed">{{ $fd('YesOrNo', scope.row.IsClosed) }}</el-tag> <el-tag v-if="scope.row.IsClosed">{{
<el-tag v-else type="danger">{{ $fd('YesOrNo', scope.row.IsClosed) }}</el-tag> $fd("YesOrNo", scope.row.IsClosed)
}}</el-tag>
<el-tag v-else type="danger">{{
$fd("YesOrNo", scope.row.IsClosed)
}}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<!-- 关闭时间 --> <!-- 关闭时间 -->
@ -213,9 +265,15 @@
> >
<template slot-scope="scope"> <template slot-scope="scope">
<span v-if="scope.row.ReuploadEnum === 0">--</span> <span v-if="scope.row.ReuploadEnum === 0">--</span>
<el-tag v-else-if="scope.row.ReuploadEnum === 1" type="danger">{{ $fd('ReuploadEnum', scope.row.ReuploadEnum) }}</el-tag> <el-tag v-else-if="scope.row.ReuploadEnum === 1" type="danger">{{
<el-tag v-else-if="scope.row.ReuploadEnum === 2" type="warning">{{ $fd('ReuploadEnum', scope.row.ReuploadEnum) }}</el-tag> $fd("ReuploadEnum", scope.row.ReuploadEnum)
<el-tag v-else-if="scope.row.ReuploadEnum === 3" type="primary">{{ $fd('ReuploadEnum', scope.row.ReuploadEnum) }}</el-tag> }}</el-tag>
<el-tag v-else-if="scope.row.ReuploadEnum === 2" type="warning">{{
$fd("ReuploadEnum", scope.row.ReuploadEnum)
}}</el-tag>
<el-tag v-else-if="scope.row.ReuploadEnum === 3" type="primary">{{
$fd("ReuploadEnum", scope.row.ReuploadEnum)
}}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<!-- 重传完成时间 --> <!-- 重传完成时间 -->
@ -247,7 +305,13 @@
</el-table> </el-table>
<!-- 分页组件 --> <!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" /> <pagination
class="page"
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
</template> </template>
<!-- 回复质疑 --> <!-- 回复质疑 -->
@ -255,32 +319,54 @@
v-if="chatVisible" v-if="chatVisible"
:visible.sync="chatVisible" :visible.sync="chatVisible"
:close-on-click-modal="false" :close-on-click-modal="false"
:close-on-press-escape="false"
:before-close="beforeClose"
width="800px" width="800px"
:title="$t('trials:crcQuestion:dialogTitle:message1') + `(${currentQCRow.SubjectCode} ${currentQCRow.VisitName})`" :title="
$t('trials:crcQuestion:dialogTitle:message1') +
`(${currentQCRow.SubjectCode} ${currentQCRow.VisitName})`
"
> >
<chat-form ref="chatForm" :data="currentQCRow" user-type="crc" :body-parts="otherInfo.BodyPartTypes" :modalities="otherInfo.Modalitys" :subject-visit-id="currentQCRow.Id" :clinical-enum="otherInfo.ClinicalInformationTransmissionEnum" @close="close" @getDialogList="getDialogList" @getNextTask="getNextTask"/> <chat-form
ref="chatForm"
:data="currentQCRow"
user-type="crc"
:body-parts="otherInfo.BodyPartTypes"
:modalities="otherInfo.Modalitys"
:subject-visit-id="currentQCRow.Id"
:clinical-enum="otherInfo.ClinicalInformationTransmissionEnum"
@close="beforeClose"
@getDialogList="getDialogList"
@getNextTask="getNextTask"
/>
</el-dialog> </el-dialog>
</BaseContainer> </BaseContainer>
</template> </template>
<script> <script>
import { getCRCChallengeList, getTrialSiteSelect, getTrialVisitStageSelect, getQCChallengeDialogList, getNextCRCChallenge } from '@/api/trials' import {
import { getQCChallengeList_Export } from '@/api/export' getCRCChallengeList,
import ChatForm from './components/chatForm' getTrialSiteSelect,
import BaseContainer from '@/components/BaseContainer' getTrialVisitStageSelect,
import Pagination from '@/components/Pagination' getQCChallengeDialogList,
getNextCRCChallenge,
} from "@/api/trials";
import { getQCChallengeList_Export } from "@/api/export";
import ChatForm from "./components/chatForm";
import BaseContainer from "@/components/BaseContainer";
import Pagination from "@/components/Pagination";
const searchDataDefault = () => { const searchDataDefault = () => {
return { return {
IsOverTime: null, IsOverTime: null,
SubjectCode: '', SubjectCode: "",
TrialSiteId: '', TrialSiteId: "",
VisitPlanArray: [], VisitPlanArray: [],
IsClosed: null, IsClosed: null,
PageIndex: 1, PageIndex: 1,
PageSize: 20 PageSize: 20,
} };
} };
export default { export default {
name: 'CrcQusetion', name: "CrcQusetion",
components: { BaseContainer, Pagination, ChatForm }, components: { BaseContainer, Pagination, ChatForm },
data() { data() {
return { return {
@ -293,115 +379,144 @@ export default {
siteOptions: [], siteOptions: [],
visitPlanOptions: [], visitPlanOptions: [],
otherInfo: {}, otherInfo: {},
trialId: this.$route.query.trialId trialId: this.$route.query.trialId,
} };
}, },
mounted() { mounted() {
this.getList() this.getList();
this.getSite() this.getSite();
this.getVisitPlanOptions() this.getVisitPlanOptions();
},
watch: {
chatVisible() {
if (!this.chatVisible) {
this.$store.state.trials.checkTaskId = null;
}
},
}, },
methods: { methods: {
beforeClose() {
this.chatVisible = false;
this.$store.state.trials.checkTaskId = null;
},
handleExport() { handleExport() {
getQCChallengeList_Export(this.searchData).then(res => { getQCChallengeList_Export(this.searchData)
}).catch(() => { this.loading = false }) .then((res) => {})
.catch(() => {
this.loading = false;
});
}, },
// //
getList() { getList() {
this.loading = true this.loading = true;
this.searchData.TrialId = this.trialId this.searchData.TrialId = this.trialId;
getCRCChallengeList(this.searchData).then(res => { getCRCChallengeList(this.searchData)
this.loading = false .then((res) => {
this.list = res.Result.CurrentPageData this.loading = false;
this.total = res.Result.TotalCount this.list = res.Result.CurrentPageData;
this.otherInfo = res.OtherInfo this.total = res.Result.TotalCount;
}).catch(() => { this.loading = false }) this.otherInfo = res.OtherInfo;
})
.catch(() => {
this.loading = false;
});
}, },
// //
handleReplay(row) { handleReplay(row) {
this.loading = true this.loading = true;
getQCChallengeDialogList(row.Id).then(res => { getQCChallengeDialogList(row.Id)
this.loading = false .then((res) => {
if (res.IsSuccess) { this.loading = false;
if (res.Result.length > 0) { Object.assign(row, res.Result[0]) } if (res.IsSuccess) {
this.currentQCRow = { ...row } if (res.Result.length > 0) {
this.chatVisible = true Object.assign(row, res.Result[0]);
} }
}).catch(() => { this.loading = false }) this.currentQCRow = { ...row };
}, this.$store.state.trials.checkTaskId = row.SubjectVisitId;
close() { this.chatVisible = true;
this.chatVisible = false }
})
.catch(() => {
this.loading = false;
});
}, },
async getNextTask(qcChallengeId) { async getNextTask(qcChallengeId) {
try { try {
const params = { const params = {
trialId: this.trialId, trialId: this.trialId,
qcChallengeId: qcChallengeId qcChallengeId: qcChallengeId,
} };
const res = await getNextCRCChallenge(params) const res = await getNextCRCChallenge(params);
if (res.IsSuccess) { if (res.IsSuccess) {
const res2 = await getQCChallengeDialogList(res.Result.Id) const res2 = await getQCChallengeDialogList(res.Result.Id);
if (res2.IsSuccess) { if (res2.IsSuccess) {
Object.assign(res.Result, res2.Result[0]) Object.assign(res.Result, res2.Result[0]);
this.chatVisible = false this.chatVisible = false;
this.currentQCRow = res.Result this.currentQCRow = res.Result;
this.$nextTick(() => { this.$nextTick(() => {
this.chatVisible = true this.chatVisible = true;
}) });
} }
} }
} catch (e) { } catch (e) {
this.chatVisible = false this.chatVisible = false;
console.log(e) console.log(e);
} }
}, },
getDialogList() { getDialogList() {
this.loading = true this.loading = true;
getQCChallengeDialogList(this.currentQCRow.Id).then(res => { getQCChallengeDialogList(this.currentQCRow.Id)
this.loading = false .then((res) => {
if (res.IsSuccess && res.Result.length > 0) { this.loading = false;
var i = this.list.findIndex(item => item.Id === this.currentQCRow.Id) if (res.IsSuccess && res.Result.length > 0) {
if (i > -1) { var i = this.list.findIndex(
this.currentQCRow = Object.assign(this.list[i], res.Result[0]) (item) => item.Id === this.currentQCRow.Id
this.$refs['chatForm'].addMessage(res.Result[0].DialogList[res.Result[0].DialogList.length - 1]) );
if (i > -1) {
this.currentQCRow = Object.assign(this.list[i], res.Result[0]);
this.$refs["chatForm"].addMessage(
res.Result[0].DialogList[res.Result[0].DialogList.length - 1]
);
}
} }
} })
}).catch(() => { this.loading = false }) .catch(() => {
this.loading = false;
});
}, },
// //
handleReset() { handleReset() {
this.searchData = searchDataDefault() this.searchData = searchDataDefault();
this.getList() this.getList();
}, },
// //
handleSearch() { handleSearch() {
this.searchData.PageIndex = 1 this.searchData.PageIndex = 1;
this.getList() this.getList();
}, },
// //
handleSortByColumn(column) { handleSortByColumn(column) {
if (column.order === 'ascending') { if (column.order === "ascending") {
this.searchData.Asc = true this.searchData.Asc = true;
} else { } else {
this.searchData.Asc = false this.searchData.Asc = false;
} }
this.searchData.SortField = column.prop this.searchData.SortField = column.prop;
this.searchData.PageIndex = 1 this.searchData.PageIndex = 1;
this.getList() this.getList();
}, },
// site // site
getSite() { getSite() {
getTrialSiteSelect(this.trialId).then(res => { getTrialSiteSelect(this.trialId).then((res) => {
this.siteOptions = res.Result this.siteOptions = res.Result;
}) });
}, },
// 访 // 访
getVisitPlanOptions() { getVisitPlanOptions() {
getTrialVisitStageSelect(this.trialId) getTrialVisitStageSelect(this.trialId).then((res) => {
.then((res) => { this.visitPlanOptions = res.Result;
this.visitPlanOptions = res.Result });
}) },
} },
} };
}
</script> </script>

File diff suppressed because it is too large Load Diff