|
|
@@ -0,0 +1,465 @@
|
|
|
+<script setup lang="ts" name="Experiment">
|
|
|
+import apis from "@a"
|
|
|
+import dayjs from "dayjs"
|
|
|
+import EDetail from "./_detail.vue"
|
|
|
+
|
|
|
+const experimentUsersOptions = ref([])
|
|
|
+const tableRef = ref()
|
|
|
+const modalRef = ref()
|
|
|
+const sampleSelectRef = ref()
|
|
|
+const opts = reactive({
|
|
|
+ columns: [
|
|
|
+ { field: "id", name: "实验ID", width: 100, isSort: true, visible: false, tooltip: true },
|
|
|
+ {
|
|
|
+ field: "experimentName",
|
|
|
+ name: "实验名称",
|
|
|
+ visible: true,
|
|
|
+ isSort: false,
|
|
|
+ width: "auto",
|
|
|
+ tooltip: true
|
|
|
+ },
|
|
|
+ { field: "experimentType", name: "实验类型", visible: true, isSort: false, width: 200 },
|
|
|
+ {
|
|
|
+ field: "experimentManagerName",
|
|
|
+ name: "实验负责人",
|
|
|
+ visible: true,
|
|
|
+ isSort: false,
|
|
|
+ width: 120,
|
|
|
+ tooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: "reviewManagerName",
|
|
|
+ name: "审核负责人",
|
|
|
+ visible: true,
|
|
|
+ isSort: false,
|
|
|
+ width: 120,
|
|
|
+ tooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: "experimentStatus",
|
|
|
+ name: "实验状态",
|
|
|
+ visible: true,
|
|
|
+ isSort: false,
|
|
|
+ width: 100,
|
|
|
+ tooltip: true
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: "rawDataUrl",
|
|
|
+ name: "原始数据",
|
|
|
+ visible: true,
|
|
|
+ isSort: false,
|
|
|
+ width: 230,
|
|
|
+ tooltip: true
|
|
|
+ },
|
|
|
+ { field: "reportUrl", name: "实验报告", visible: true, isSort: false, width: 230 },
|
|
|
+
|
|
|
+ { field: "actions", name: `操作`, width: 150 }
|
|
|
+ ] as any[],
|
|
|
+ queryParams: {
|
|
|
+ experimentName: undefined,
|
|
|
+ experimentType: undefined,
|
|
|
+ experimentStatus: 3
|
|
|
+ },
|
|
|
+ searchFormItems: [
|
|
|
+ {
|
|
|
+ field: "experimentName",
|
|
|
+ label: "实验名称",
|
|
|
+ class: "w-100",
|
|
|
+ required: false,
|
|
|
+ placeholder: "请输入实验名称",
|
|
|
+ component: "I",
|
|
|
+ listeners: {
|
|
|
+ keyup: (e: KeyboardEvent) => {
|
|
|
+ if (e.code == "Enter") {
|
|
|
+ handleQuery()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: "experimentType",
|
|
|
+ label: "实验类型",
|
|
|
+ class: "w-100",
|
|
|
+ required: false,
|
|
|
+ component: "Dict",
|
|
|
+ props: {
|
|
|
+ placeholder: "请选择实验类型",
|
|
|
+ dictType: "experiment_type",
|
|
|
+ valueIsNumber: 1,
|
|
|
+ type: "select"
|
|
|
+ },
|
|
|
+ listeners: {
|
|
|
+ change: () => {
|
|
|
+ handleQuery()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ] as any,
|
|
|
+ permission: "experiment:experiment",
|
|
|
+ handleBtns: [],
|
|
|
+ handleFuns: {
|
|
|
+ handleCreate,
|
|
|
+ handleUpdate: () => {
|
|
|
+ const row = tableRef.value.getSelected()
|
|
|
+ handleUpdate(row)
|
|
|
+ },
|
|
|
+ handleDelete: () => {
|
|
|
+ const rows = tableRef.value.getSelecteds()
|
|
|
+ handleDelete(rows)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ customBtns: [],
|
|
|
+ tableListFun: apis.experiment.experimentApi.list,
|
|
|
+ getEntityFun: apis.experiment.experimentApi.get,
|
|
|
+ deleteEntityFun: apis.experiment.experimentApi.del,
|
|
|
+ exportUrl: apis.experiment.experimentApi.exportUrl,
|
|
|
+ exportName: "Experiment",
|
|
|
+ modalTitle: "实验管理",
|
|
|
+ formItems: [
|
|
|
+ {
|
|
|
+ field: "experimentName",
|
|
|
+ label: "实验名称",
|
|
|
+ class: "w-100",
|
|
|
+ required: true,
|
|
|
+ placeholder: "请输入实验名称",
|
|
|
+ component: "I"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: "experimentType",
|
|
|
+ label: "实验类型",
|
|
|
+ class: "w-100",
|
|
|
+ required: true,
|
|
|
+ component: "Dict",
|
|
|
+ props: {
|
|
|
+ placeholder: "请选择实验类型",
|
|
|
+ dictType: "experiment_type",
|
|
|
+ type: "select",
|
|
|
+ valueIsNumber: 1
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: "sampleNames",
|
|
|
+ label: "实验样品",
|
|
|
+ class: "w-100",
|
|
|
+ required: true,
|
|
|
+ placeholder: "请选择实验样品",
|
|
|
+ data: () => [],
|
|
|
+ props: {
|
|
|
+ type: "select"
|
|
|
+ },
|
|
|
+ append: "icon",
|
|
|
+ appendClickFunc: () => {
|
|
|
+ sampleSelectRef.value.open()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: "reviewManager",
|
|
|
+ label: "审核负责人",
|
|
|
+ class: "w-100",
|
|
|
+ required: true,
|
|
|
+ placeholder: "请选择审核负责人",
|
|
|
+ component: "VS",
|
|
|
+ data: () => experimentUsersOptions.value,
|
|
|
+ props: {
|
|
|
+ valueIsNumber: 1,
|
|
|
+ type: "select"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: "description",
|
|
|
+ label: "实验描述",
|
|
|
+ class: "w-100",
|
|
|
+ required: false,
|
|
|
+ placeholder: "请输入实验描述",
|
|
|
+ component: "I",
|
|
|
+ props: {
|
|
|
+ type: "textarea"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ] as any,
|
|
|
+ resetForm: () => {
|
|
|
+ form.value = emptyFormData.value
|
|
|
+ },
|
|
|
+ labelWidth: "80px",
|
|
|
+ emptyFormData: {
|
|
|
+ id: undefined,
|
|
|
+ experimentName: undefined,
|
|
|
+ experimentType: undefined,
|
|
|
+ sampleIds: undefined,
|
|
|
+ sampleNames: undefined,
|
|
|
+ reviewManager: undefined
|
|
|
+ }
|
|
|
+})
|
|
|
+const { queryParams, emptyFormData } = toRefs(opts)
|
|
|
+const form = ref<any>(emptyFormData.value)
|
|
|
+
|
|
|
+/** 搜索按钮操作 */
|
|
|
+function handleQuery(query?: any) {
|
|
|
+ query = query || tableRef.value?.getQueryParams() || queryParams.value
|
|
|
+ addDateRange(query, query.dateRangeCreateTime)
|
|
|
+ addDateRange(query, query.dateRangeUpdateTime, "UpdateTime")
|
|
|
+ tableRef.value?.query(query)
|
|
|
+}
|
|
|
+
|
|
|
+/** 重置按钮操作 */
|
|
|
+function resetQuery(query?: any) {
|
|
|
+ query = query || tableRef.value?.getQueryParams() || queryParams.value
|
|
|
+ query.dateRangeCreateTime = [] as any
|
|
|
+ addDateRange(query, query.dateRangeCreateTime)
|
|
|
+ query.dateRangeUpdateTime = [] as any
|
|
|
+ addDateRange(query, query.dateRangeUpdateTime, "UpdateTime")
|
|
|
+ //
|
|
|
+}
|
|
|
+
|
|
|
+function handleCreate() {
|
|
|
+ tableRef.value.defaultHandleFuns.handleCreate()
|
|
|
+}
|
|
|
+
|
|
|
+/** 修改按钮操作 */
|
|
|
+function handleUpdate(row: any) {
|
|
|
+ // tableRef.value.defaultHandleFuns.handleUpdate("", row)
|
|
|
+ apis.experiment.experimentApi.get(row.id).then((res) => {
|
|
|
+ form.value = res.data
|
|
|
+ form.value.sampleIds = res.data.sampleList.map((item) => item.sampleId)
|
|
|
+ form.value.sampleNames = res.data.sampleList.map((item) => item.sampleName)
|
|
|
+ modalRef.value.show()
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/** 删除按钮操作 */
|
|
|
+function handleDelete(rows: any[]) {
|
|
|
+ tableRef.value.defaultHandleFuns.handleDelete("", rows)
|
|
|
+}
|
|
|
+
|
|
|
+/** 提交按钮 */
|
|
|
+function submitForm() {
|
|
|
+ apis.experiment.experimentApi.addOrUpdate(form.value).then(() => {
|
|
|
+ handleQuery()
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function onSampleSelectConfirm(data: any) {
|
|
|
+ console.log("data", data)
|
|
|
+ form.value.sampleIds = data.map((item) => item.id)
|
|
|
+ form.value.sampleNames = data.map((item) => item.sampleName)
|
|
|
+}
|
|
|
+
|
|
|
+function getExperimentUsersOptions() {
|
|
|
+ apis.experiment.experimentApi.getExperimentUsers().then((res) => {
|
|
|
+ experimentUsersOptions.value = res.data.map((item) => {
|
|
|
+ return {
|
|
|
+ label: `${item.nickname}(${item.username})`,
|
|
|
+ value: item.userId
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+function handleStart(row: any) {
|
|
|
+ message.confirm("确定要开始实验吗?", "开始实验").then(() => {
|
|
|
+ apis.experiment.experimentApi.start(row.id).then(() => {
|
|
|
+ handleQuery()
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+const reportModalRef = ref()
|
|
|
+const reportForm = ref({
|
|
|
+ id: undefined,
|
|
|
+ rawDataUrl: undefined,
|
|
|
+ reportUrl: undefined
|
|
|
+})
|
|
|
+const reportFormItems = [
|
|
|
+ {
|
|
|
+ field: "rawDataUrl",
|
|
|
+ label: "原始数据",
|
|
|
+ class: "w-100",
|
|
|
+ required: true,
|
|
|
+ placeholder: "请上传原始数据",
|
|
|
+ component: "Vu",
|
|
|
+ props: {
|
|
|
+ uploadType: "file",
|
|
|
+ uploadUrl: "resource/oss/upload/experiment",
|
|
|
+ fileType: ["pdf", "doc", "docx", "xls", "xlsx", "zip"],
|
|
|
+ fileSize: 10,
|
|
|
+ limit: 5
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field: "reportUrl",
|
|
|
+ label: "实验报告",
|
|
|
+ class: "w-100",
|
|
|
+ required: true,
|
|
|
+ placeholder: "请上传实验报告",
|
|
|
+ component: "Vu",
|
|
|
+ props: {
|
|
|
+ uploadType: "file",
|
|
|
+ uploadUrl: "resource/oss/upload/experiment",
|
|
|
+ fileType: ["pdf", "doc", "docx", "xls", "xlsx", "zip"],
|
|
|
+ fileSize: 10,
|
|
|
+ limit: 5
|
|
|
+ }
|
|
|
+ }
|
|
|
+]
|
|
|
+function handleReport(row: any) {
|
|
|
+ reportForm.value = {
|
|
|
+ id: row.id,
|
|
|
+ rawDataUrl: undefined,
|
|
|
+ reportUrl: undefined
|
|
|
+ }
|
|
|
+ reportModalRef.value.show()
|
|
|
+}
|
|
|
+
|
|
|
+function submitReport() {
|
|
|
+ apis.experiment.experimentApi.submitExperiment(reportForm.value).then(() => {
|
|
|
+ handleQuery()
|
|
|
+ })
|
|
|
+}
|
|
|
+const pdfPreviewRef = ref()
|
|
|
+function handlePreviewPdf(file: string) {
|
|
|
+ const fileId = file.split("$")[0],
|
|
|
+ fileName = file.split("$")[1]
|
|
|
+ pdfPreviewRef.value.open({
|
|
|
+ fileId,
|
|
|
+ fileName
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const detailRef = ref()
|
|
|
+function handleDetail(row: any) {
|
|
|
+ apis.experiment.experimentApi.get(row.id).then((res) => {
|
|
|
+ detailRef.value.open(res.data)
|
|
|
+ })
|
|
|
+}
|
|
|
+function handleAudit(row: any, isAudit: boolean) {
|
|
|
+ message
|
|
|
+ .confirm(
|
|
|
+ `确定要${isAudit ? "通过" : "拒绝"}审核,${isAudit ? "吗" : "发回重新报告"}?`,
|
|
|
+ `${isAudit ? "通过" : "拒绝"}审核`
|
|
|
+ )
|
|
|
+ .then(() => {
|
|
|
+ apis.experiment.experimentApi.auditExperiment({ id: row.id, pass: isAudit }).then(() => {
|
|
|
+ handleQuery()
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+function init() {
|
|
|
+ getExperimentUsersOptions()
|
|
|
+}
|
|
|
+onMounted(init)
|
|
|
+</script>
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+ <VbDataTable
|
|
|
+ ref="tableRef"
|
|
|
+ keyField="id"
|
|
|
+ :columns="opts.columns"
|
|
|
+ :handle-perm="opts.permission"
|
|
|
+ :handle-btns="opts.handleBtns"
|
|
|
+ :handle-funs="opts.handleFuns"
|
|
|
+ :search-form-items="opts.searchFormItems"
|
|
|
+ :custom-btns="opts.customBtns"
|
|
|
+ :remote-fun="opts.tableListFun"
|
|
|
+ :get-entity-fun="opts.getEntityFun"
|
|
|
+ :delete-entity-fun="opts.deleteEntityFun"
|
|
|
+ :export-url="opts.exportUrl"
|
|
|
+ :export-name="opts.exportName"
|
|
|
+ :modal="modalRef"
|
|
|
+ :reset-form-fun="opts.resetForm"
|
|
|
+ v-model:form-data="form"
|
|
|
+ v-model:query-params="queryParams"
|
|
|
+ :check-multiple="true"
|
|
|
+ :reset-search-form-fun="resetQuery"
|
|
|
+ :custom-search-fun="handleQuery">
|
|
|
+ <template #experimentType="{ row }">
|
|
|
+ <DictTag type="experiment_type" :value-is-number="1" :value="row.experimentType"></DictTag>
|
|
|
+ </template>
|
|
|
+ <template #rawDataUrl="{ row }">
|
|
|
+ <template v-if="row.rawDataUrl">
|
|
|
+ <template v-for="(file, key) in row.rawDataUrl.split(',')" :key="key">
|
|
|
+ <span
|
|
|
+ v-if="file.split('$').length > 1"
|
|
|
+ class="text-primary p-1"
|
|
|
+ @click="handlePreviewPdf(file)">
|
|
|
+ {{ file.split("$")[1] }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ <template v-else>-</template>
|
|
|
+ </template>
|
|
|
+ <template #reportUrl="{ row }">
|
|
|
+ <template v-if="row.reportUrl">
|
|
|
+ <template v-for="(file, key) in row.reportUrl.split(',')" :key="key">
|
|
|
+ <span
|
|
|
+ v-if="file.split('$').length > 1"
|
|
|
+ class="text-primary p-1"
|
|
|
+ @click="handlePreviewPdf(file)">
|
|
|
+ {{ file.split("$")[1] }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ <template v-else>-</template>
|
|
|
+ </template>
|
|
|
+ <template #experimentStatus="{ row }">
|
|
|
+ <DictTag
|
|
|
+ type="experiment_status"
|
|
|
+ :value-is-number="1"
|
|
|
+ :value="row.experimentStatus"></DictTag>
|
|
|
+ </template>
|
|
|
+ <template #actions="{ row }">
|
|
|
+ <vb-tooltip content="实验详情" placement="top">
|
|
|
+ <el-button link type="primary" @click="handleDetail(row)">
|
|
|
+ <template #icon>
|
|
|
+ <VbIcon icon-name="book" icon-type="duotone" class="fs-3"></VbIcon>
|
|
|
+ </template>
|
|
|
+ </el-button>
|
|
|
+ </vb-tooltip>
|
|
|
+ <vb-tooltip v-if="row.experimentStatus === 3" content="审核通过" placement="top">
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="success"
|
|
|
+ @click="handleAudit(row, true)"
|
|
|
+ v-hasPermission="'experiment:experiment:edit'">
|
|
|
+ <template #icon>
|
|
|
+ <VbIcon icon-name="add-files" icon-type="duotone" class="fs-3"></VbIcon>
|
|
|
+ </template>
|
|
|
+ </el-button>
|
|
|
+ </vb-tooltip>
|
|
|
+ <vb-tooltip v-if="row.experimentStatus === 3" content="发回报告" placement="top">
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="danger"
|
|
|
+ @click="handleAudit(row, false)"
|
|
|
+ v-hasPermission="'experiment:experiment:edit'">
|
|
|
+ <template #icon>
|
|
|
+ <VbIcon icon-name="update-file" icon-type="duotone" class="fs-3"></VbIcon>
|
|
|
+ </template>
|
|
|
+ </el-button>
|
|
|
+ </vb-tooltip>
|
|
|
+ </template>
|
|
|
+ </VbDataTable>
|
|
|
+ <VbModal
|
|
|
+ v-model:modal="modalRef"
|
|
|
+ :title="opts.modalTitle"
|
|
|
+ :form-data="form"
|
|
|
+ :form-items="opts.formItems"
|
|
|
+ :label-width="opts.labelWidth"
|
|
|
+ append-to-body
|
|
|
+ @confirm="submitForm"></VbModal>
|
|
|
+ <VbModal
|
|
|
+ v-model:modal="reportModalRef"
|
|
|
+ title="上传报告"
|
|
|
+ :form-data="reportForm"
|
|
|
+ :form-items="reportFormItems as any"
|
|
|
+ :label-width="opts.labelWidth"
|
|
|
+ append-to-body
|
|
|
+ @confirm="submitReport"></VbModal>
|
|
|
+ <SampleSelect
|
|
|
+ ref="sampleSelectRef"
|
|
|
+ v-model="form.sampleIds"
|
|
|
+ @confirm="onSampleSelectConfirm"></SampleSelect>
|
|
|
+
|
|
|
+ <EDetail ref="detailRef"></EDetail>
|
|
|
+
|
|
|
+ <VbPdfPreview ref="pdfPreviewRef" />
|
|
|
+ </div>
|
|
|
+</template>
|