中心调查表链接添加二维码
continuous-integration/drone/push Build is passing Details

uat_us
wangxiaoshuang 2024-07-15 15:52:47 +08:00
parent e45903d55e
commit 7f36aa5a05
3 changed files with 334 additions and 134 deletions

View File

@ -50,6 +50,7 @@
"path-to-regexp": "2.4.0", "path-to-regexp": "2.4.0",
"pdfobject": "^2.2.8", "pdfobject": "^2.2.8",
"popper.js": "^1.16.1", "popper.js": "^1.16.1",
"qrcodejs2": "0.0.2",
"sass-loader": "^8.0.0", "sass-loader": "^8.0.0",
"screenfull": "^4.2.0", "screenfull": "^4.2.0",
"sortablejs": "^1.15.0", "sortablejs": "^1.15.0",

View File

@ -455,7 +455,7 @@ $cursor: #fff;
<style lang="scss" scoped> <style lang="scss" scoped>
$bg: #2d3a4b; $bg: #2d3a4b;
$dark_gray: #0093dd; $dark_gray: #889aa4;
$light_gray: #606266; $light_gray: #606266;
.login-container { .login-container {
position: relative; position: relative;

View File

@ -5,9 +5,14 @@
<el-form :inline="true"> <el-form :inline="true">
<!-- 中心 --> <!-- 中心 -->
<el-form-item :label="$t('trials:researchRecord:table:siteId')"> <el-form-item :label="$t('trials:researchRecord: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"
@ -20,17 +25,21 @@
v-model="searchData.UserKeyInfo" v-model="searchData.UserKeyInfo"
class="mr" class="mr"
clearable clearable
:placeholder="`${$t('trials:researchRecord:placeholder:contactorInfo')}`" :placeholder="`${$t(
style="width:140px;" 'trials:researchRecord:placeholder:contactorInfo'
)}`"
style="width: 140px"
/> />
</el-form-item> </el-form-item>
<!-- 初审人 --> <!-- 初审人 -->
<el-form-item :label="$t('trials:researchRecord:table:preliminaryUser')"> <el-form-item
:label="$t('trials:researchRecord:table:preliminaryUser')"
>
<el-input <el-input
v-model="searchData.PreliminaryUserName" v-model="searchData.PreliminaryUserName"
class="mr" class="mr"
clearable clearable
style="width:140px;" style="width: 140px"
/> />
</el-form-item> </el-form-item>
<!-- 审核人 --> <!-- 审核人 -->
@ -39,14 +48,19 @@
v-model="searchData.ReviewerUserName" v-model="searchData.ReviewerUserName"
class="mr" class="mr"
clearable clearable
style="width:140px;" style="width: 140px"
/> />
</el-form-item> </el-form-item>
<!-- 状态 --> <!-- 状态 -->
<el-form-item :label="$t('trials:researchRecord:table:status')"> <el-form-item :label="$t('trials:researchRecord:table:status')">
<el-select v-model="searchData.State" clearable filterable style="width:120px;"> <el-select
v-model="searchData.State"
clearable
filterable
style="width: 120px"
>
<el-option <el-option
v-for="(item,index) of $d.ResearchRecord" v-for="(item, index) of $d.ResearchRecord"
:key="index" :key="index"
:label="item.label" :label="item.label"
:value="item.value" :value="item.value"
@ -55,8 +69,19 @@
</el-form-item> </el-form-item>
<!-- 是否废除 --> <!-- 是否废除 -->
<el-form-item :label="$t('trials:researchRecord:table:isDeleted')"> <el-form-item :label="$t('trials:researchRecord:table:isDeleted')">
<el-select v-model="searchData.IsDeleted" clearable filterable style="width:120px;"> <el-select
<el-option v-for="item of $d.YesOrNo" v-show="item.raw.ValueCN !== ''" :key="`IsDeleted${item.value}`" :label="item.label" :value="item.value" /> v-model="searchData.IsDeleted"
clearable
filterable
style="width: 120px"
>
<el-option
v-for="item of $d.YesOrNo"
v-show="item.raw.ValueCN !== '无'"
:key="`IsDeleted${item.value}`"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 更新时间 --> <!-- 更新时间 -->
@ -66,34 +91,42 @@
type="daterange" type="daterange"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
format="yyyy-MM-dd" format="yyyy-MM-dd"
style="width:250px;" style="width: 250px"
/> />
</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 <el-button
v-hasPermi="['trials:trials-panel:attachments:site-research:summary-record']" v-hasPermi="[
'trials:trials-panel:attachments:site-research:summary-record',
]"
type="primary" type="primary"
icon="el-icon-info" icon="el-icon-info"
@click="showResearchUser" @click="showResearchUser"
> >
{{ $t('trials:researchRecord:button:questionStaffs') }} {{ $t("trials:researchRecord:button:questionStaffs") }}
</el-button> </el-button>
<!-- 调查表链接 --> <!-- 调查表链接 -->
<el-button <el-button
v-hasPermi="['trials:trials-panel:attachments:site-research:questionnaire-link']" v-hasPermi="[
'trials:trials-panel:attachments:site-research:questionnaire-link',
]"
type="primary" type="primary"
icon="el-icon-link" icon="el-icon-link"
@click="showResearchLink" @click="showResearchLink"
> >
{{ $t('trials:researchRecord:button:questionLink') }} {{ $t("trials:researchRecord:button:questionLink") }}
</el-button> </el-button>
</el-form> </el-form>
</template> </template>
@ -103,7 +136,7 @@
<el-table <el-table
ref="siteResearchList" ref="siteResearchList"
v-loading="loading" v-loading="loading"
v-adaptive="{bottomOffset:60}" v-adaptive="{ bottomOffset: 60 }"
:data="list" :data="list"
stripe stripe
height="100" height="100"
@ -153,7 +186,11 @@
show-overflow-tooltip show-overflow-tooltip
> >
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.PreliminaryUser?scope.row.PreliminaryUser.RealName:"" }} {{
scope.row.PreliminaryUser
? scope.row.PreliminaryUser.RealName
: ""
}}
</template> </template>
</el-table-column> </el-table-column>
<!-- 审核人 --> <!-- 审核人 -->
@ -164,7 +201,7 @@
show-overflow-tooltip show-overflow-tooltip
> >
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.ReviewerUser?scope.row.ReviewerUser.RealName:"" }} {{ scope.row.ReviewerUser ? scope.row.ReviewerUser.RealName : "" }}
</template> </template>
</el-table-column> </el-table-column>
<!-- 状态 --> <!-- 状态 -->
@ -175,10 +212,18 @@
show-overflow-tooltip show-overflow-tooltip
> >
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag v-if="scope.row.State === 0" type="primary">{{ $fd('ResearchRecord', scope.row.State) }}</el-tag> <el-tag v-if="scope.row.State === 0" type="primary">{{
<el-tag v-if="scope.row.State === 1" type="info">{{ $fd('ResearchRecord', scope.row.State) }}</el-tag> $fd("ResearchRecord", scope.row.State)
<el-tag v-if="scope.row.State === 2" type="warning">{{ $fd('ResearchRecord', scope.row.State) }}</el-tag> }}</el-tag>
<el-tag v-if="scope.row.State === 3" type="danger">{{ $fd('ResearchRecord', scope.row.State) }}</el-tag> <el-tag v-if="scope.row.State === 1" type="info">{{
$fd("ResearchRecord", scope.row.State)
}}</el-tag>
<el-tag v-if="scope.row.State === 2" type="warning">{{
$fd("ResearchRecord", scope.row.State)
}}</el-tag>
<el-tag v-if="scope.row.State === 3" type="danger">{{
$fd("ResearchRecord", scope.row.State)
}}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<!-- 是否废除 --> <!-- 是否废除 -->
@ -189,8 +234,12 @@
show-overflow-tooltip show-overflow-tooltip
> >
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag v-if="scope.row.IsDeleted" type="danger">{{ $fd('YesOrNo', scope.row.IsDeleted) }}</el-tag> <el-tag v-if="scope.row.IsDeleted" type="danger">{{
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsDeleted) }}</el-tag> $fd("YesOrNo", scope.row.IsDeleted)
}}</el-tag>
<el-tag v-else type="primary">{{
$fd("YesOrNo", scope.row.IsDeleted)
}}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<!-- 更新时间 --> <!-- 更新时间 -->
@ -200,9 +249,7 @@
min-width="150" min-width="150"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column width="150">
width="150"
>
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 查看 --> <!-- 查看 -->
<el-button <el-button
@ -214,7 +261,9 @@
/> />
<!-- 审批 --> <!-- 审批 -->
<el-button <el-button
v-hasPermi="['trials:trials-panel:attachments:site-research:auidt']" v-hasPermi="[
'trials:trials-panel:attachments:site-research:auidt',
]"
:disabled="scope.row.State === 0 || scope.row.State === 3" :disabled="scope.row.State === 0 || scope.row.State === 3"
circle circle
:title="$t('trials:researchRecord:action:view')" :title="$t('trials:researchRecord:action:view')"
@ -223,7 +272,9 @@
/> />
<!-- 废除 --> <!-- 废除 -->
<el-button <el-button
v-hasPermi="['trials:trials-panel:attachments:site-research:abolish']" v-hasPermi="[
'trials:trials-panel:attachments:site-research:abolish',
]"
:disabled="scope.row.State !== 0 || scope.row.IsDeleted" :disabled="scope.row.State !== 0 || scope.row.IsDeleted"
circle circle
:title="$t('trials:researchRecord:action:abolish')" :title="$t('trials:researchRecord:action:abolish')"
@ -235,7 +286,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>
<!-- 中心人员 --> <!-- 中心人员 -->
@ -246,10 +303,12 @@
custom-class="base-dialog-wrapper" custom-class="base-dialog-wrapper"
:fullscreen="true" :fullscreen="true"
> >
<div class="base-modal-body" style="border:1px solid #ccc;padding: 10px"> <div
class="base-modal-body"
style="border: 1px solid #ccc; padding: 10px"
>
<Users v-if="researchUserVisible" /> <Users v-if="researchUserVisible" />
</div> </div>
</el-dialog> </el-dialog>
<!-- 调查表 --> <!-- 调查表 -->
@ -265,53 +324,87 @@
<!-- 调查表链接 --> <!-- 调查表链接 -->
<base-model :config="share_model"> <base-model :config="share_model">
<template slot="dialog-body"> <template slot="dialog-body">
<div style="width: 100%; display: flex">
<div class="shareLink">
<div> <div>
<i style="color:#428bca;" class="el-icon-success" /> <i style="color: #428bca" class="el-icon-success" />
<!-- 成功创建调查表链接 --> <!-- 成功创建调查表链接 -->
<span>{{ $t('trials:researchRecord:message:createLinkSuccessfully') }}</span> <span>{{
$t("trials:researchRecord:message:createLinkSuccessfully")
}}</span>
</div> </div>
<div style="margin:10px 0;"> <div style="margin: 10px 0">
<!-- 链接 --> <!-- 链接 -->
{{ $t('trials:researchRecord:label:link') }} {{ $t("trials:researchRecord:label:link") }}
<el-input ref="shareLink" v-model="shareLink" readonly type="textarea" autosize /> <el-input
ref="shareLink"
v-model="shareLink"
readonly
type="textarea"
autosize
/>
</div> </div>
<div> <div>
<!-- 复制链接 --> <!-- 复制链接 -->
<el-button type="primary" round @click="copyLink"> <el-button
{{ $t('trials:researchRecord:button:copyLink') }} type="primary"
round
@click="copyLink"
class="shareLinkBtn"
>
{{ $t("trials:researchRecord:button:copyLink") }}
</el-button> </el-button>
</div> </div>
</div>
<div class="shareCode">
<div class="qrCode">
<div id="qrcode" ref="qrcode"></div>
</div>
<div class="codeBtnBox">
<el-button @click="handleCopyImg" type="primary" round>{{
$t("trials:researchRecord:button:copyCode")
}}</el-button>
<el-button @click="savePic" round>{{
$t("trials:researchRecord:button:savePic")
}}</el-button>
</div>
</div>
</div>
</template> </template>
</base-model> </base-model>
</BaseContainer> </BaseContainer>
</template> </template>
<script> <script>
import { getTrialSiteSurveyList, getTrialSiteSelect, abandonSiteSurvey } from '@/api/trials' import {
import { changeURLStatic } from '@/utils/history.js' getTrialSiteSurveyList,
import BaseContainer from '@/components/BaseContainer' getTrialSiteSelect,
import Pagination from '@/components/Pagination' abandonSiteSurvey,
import Users from './components/users' } from "@/api/trials";
import ResearchForm from '@/views/research/form' import { changeURLStatic } from "@/utils/history.js";
import BaseModel from '@/components/BaseModel' import BaseContainer from "@/components/BaseContainer";
import Pagination from "@/components/Pagination";
import Users from "./components/users";
import ResearchForm from "@/views/research/form";
import BaseModel from "@/components/BaseModel";
import QRCode from "qrcodejs2";
const searchDataDefault = () => { const searchDataDefault = () => {
return { return {
SortField: '', SortField: "",
Asc: true, Asc: true,
PageIndex: 1, PageIndex: 1,
PageSize: 20, PageSize: 20,
TrialSiteId: '', TrialSiteId: "",
UserKeyInfo: '', UserKeyInfo: "",
State: null, State: null,
IsDeleted: '', IsDeleted: "",
DateRange: [], DateRange: [],
PreliminaryUserName: null, PreliminaryUserName: null,
ReviewerUserName: null ReviewerUserName: null,
} };
} };
export default { export default {
name: 'SiteResearchList', name: "SiteResearchList",
components: { BaseContainer, Pagination, Users, ResearchForm, BaseModel }, components: { BaseContainer, Pagination, Users, ResearchForm, BaseModel },
data() { data() {
return { return {
@ -323,117 +416,223 @@ export default {
siteOptions: [], siteOptions: [],
researchUserVisible: false, researchUserVisible: false,
researchInfoVisible: false, researchInfoVisible: false,
share_model: { visible: false, title: '', width: '500px' }, share_model: {
shareLink: '', visible: false,
researchState: this.$d.ResearchRecord title: this.$t("trials:researchRecord:title:shark"),
} width: "800px",
},
shareLink: "",
researchState: this.$d.ResearchRecord,
qrcode: null,
};
}, },
mounted() { mounted() {
this.getList() this.getList();
this.getSite() this.getSite();
}, },
methods: { methods: {
// //
getList() { getList() {
this.loading = true this.loading = true;
this.searchData.TrialId = this.trialId this.searchData.TrialId = this.trialId;
if (this.searchData.DateRange && this.searchData.DateRange.length === 2) { if (this.searchData.DateRange && this.searchData.DateRange.length === 2) {
this.searchData.UpdateTimeBegin = this.searchData.DateRange[0] this.searchData.UpdateTimeBegin = this.searchData.DateRange[0];
this.searchData.updateTimeEnd = this.searchData.DateRange[1] this.searchData.updateTimeEnd = this.searchData.DateRange[1];
} else { } else {
this.searchData.UpdateTimeBegin = '' this.searchData.UpdateTimeBegin = "";
this.searchData.updateTimeEnd = '' this.searchData.updateTimeEnd = "";
} }
getTrialSiteSurveyList(this.searchData).then(res => { getTrialSiteSurveyList(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;
}).catch(() => { this.total = res.Result.TotalCount;
this.loading = false
}) })
.catch(() => {
this.loading = false;
});
}, },
// //
handleViewResearchList(row) { handleViewResearchList(row) {
changeURLStatic('trialSiteSurveyId', row.Id) changeURLStatic("trialSiteSurveyId", row.Id);
this.researchInfoVisible = true this.researchInfoVisible = true;
}, },
// //
handleRepealResearch(row) { handleRepealResearch(row) {
// //
this.$confirm(this.$t('trials:researchRecord:message:abolish'), { this.$confirm(this.$t("trials:researchRecord:message:abolish"), {
type: 'warning', type: "warning",
distinguishCancelAndClose: true distinguishCancelAndClose: true,
}) }).then(() => {
.then(() => { abandonSiteSurvey(this.trialId, row.Id).then((res) => {
abandonSiteSurvey(this.trialId, row.Id)
.then(res => {
if (res.IsSuccess) { if (res.IsSuccess) {
this.getList() this.getList();
// //
this.$message.success(this.$t('trials:researchRecord:message:abolishSuccessfully')) this.$message.success(
this.$t("trials:researchRecord:message:abolishSuccessfully")
);
} }
}) });
}) });
}, },
// //
showResearchUser() { showResearchUser() {
this.researchUserVisible = true this.researchUserVisible = true;
}, },
// //
copyLink() { copyLink() {
// //
this.$copyText(`${this.$t('trials:researchRecord:message:researchFormLink')}: ${this.shareLink}`).then( this.$copyText(
res => { `${this.$t("trials:researchRecord:message:researchFormLink")}: ${
this.shareLink
}`
)
.then((res) => {
// //
this.$message.success(this.$t('trials:researchRecord:message:copySuccessfully')) this.$message.success(
} this.$t("trials:researchRecord:message:copySuccessfully")
).catch(() => { );
//
this.$alert(this.$t('trials:researchRecord:message:copyFailed'))
}) })
.catch(() => {
//
this.$alert(this.$t("trials:researchRecord:message:copyFailed"));
});
},
//
creatQrCode() {
this.$refs.qrcode.innerHTML = ""; //
let text = this.shareLink;
this.qrcode = new QRCode(this.$refs.qrcode, {
text: text, // ,#
width: 200,
height: 200,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H,
});
// qrcode.clear(); //
},
//
savePic() {
let qrCodeCanvas = document
.getElementById("qrcode")
.getElementsByTagName("canvas");
let a = document.createElement("a");
a.href = qrCodeCanvas[0].toDataURL("image/url");
a.download = `${this.$t("trials:researchRecord:title:code")}.png`;
a.click();
},
//
handleCopyImg() {
let qrCodeCanvas = document
.getElementById("qrcode")
.getElementsByTagName("canvas");
qrCodeCanvas[0].toBlob(async (blob) => {
console.log(blob);
const data = [
new ClipboardItem({
[blob.type]: blob,
}),
]; // https://w3c.github.io/clipboard-apis/#dom-clipboard-write
await navigator.clipboard.write(data).then(
() => {
this.$message.success(
this.$t("trials:researchRecord:message:copySuccess")
);
},
() => {
this.$message.error(
this.$t("trials:researchRecord:message:UnableWrite")
);
}
);
});
}, },
// site // site
getSite() { getSite() {
getTrialSiteSelect(this.trialId).then(res => { getTrialSiteSelect(this.trialId).then((res) => {
this.siteOptions = res.Result this.siteOptions = res.Result;
}) });
}, },
// //
showResearchLink() { showResearchLink() {
const trialId = this.trialId const trialId = this.trialId;
this.shareLink = `${location.protocol}//${location.host}/researchLogin?trialId=${trialId}&lang=${this.$i18n.locale}` this.shareLink = `${location.protocol}//${location.host}/researchLogin?trialId=${trialId}&lang=${this.$i18n.locale}`;
this.share_model.visible = true this.share_model.visible = true;
this.$nextTick(() => {
this.creatQrCode();
});
}, },
// //
handleReset() { handleReset() {
this.searchData = searchDataDefault() this.searchData = searchDataDefault();
this.searchData.DateRange = [] this.searchData.DateRange = [];
if (this.searchData.DateRange && this.searchData.DateRange.length === 2) { if (this.searchData.DateRange && this.searchData.DateRange.length === 2) {
this.searchData.UpdateTimeBegin = this.searchData.DateRange[0] this.searchData.UpdateTimeBegin = this.searchData.DateRange[0];
this.searchData.updateTimeEnd = this.searchData.DateRange[1] this.searchData.updateTimeEnd = this.searchData.DateRange[1];
} else { } else {
this.searchData.UpdateTimeBegin = '' this.searchData.UpdateTimeBegin = "";
this.searchData.updateTimeEnd = '' this.searchData.updateTimeEnd = "";
} }
this.getList() this.getList();
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.siteResearchList.clearSort() this.$refs.siteResearchList.clearSort();
}) });
}, },
// //
handleSearch() { handleSearch() {
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.getList() this.getList();
},
},
beforeDestroy() {
if (this.qrcode) {
this.qrcode = null;
} }
},
};
</script>
<style lang="scss" scoped>
.shareLink {
padding-right: 20px;
width: 50%;
position: relative;
.shareLinkBtn{
position: absolute;
bottom: 0px;
left: 0px;
} }
} }
</script> .shareCode {
width: 50%;
border-left: 1px solid #eee;
display: flex;
justify-content: center;
flex-wrap: wrap;
.qrCode {
width: 220px;
height: 220px;
display: flex;
border: 1px solid #c0c4cc;
border-radius: 5px;
box-shadow: 1px 1px 5px #c0c4cc;
align-items: center;
justify-content: center;
}
.codeBtnBox {
margin-top: 20px;
width: 100%;
display: flex;
justify-content: space-around;
}
}
</style>