From 4518a41e3fce438fcf861317a603c6c17c1a047a Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期四, 13 二月 2025 17:52:32 +0800 Subject: [PATCH] 实验室资质、能力范围、场所或设施页面迁移 --- src/api/structural/laboratory.js | 26 ++ src/assets/styles/index.scss | 3 src/views/structural/premises/index.vue | 13 + src/views/structural/laboratory/index.vue | 462 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/structural/capability/index.vue | 13 + src/api/system/customer.js | 1 6 files changed, 517 insertions(+), 1 deletions(-) diff --git a/src/api/structural/laboratory.js b/src/api/structural/laboratory.js new file mode 100644 index 0000000..bf318db --- /dev/null +++ b/src/api/structural/laboratory.js @@ -0,0 +1,26 @@ +import request from '@/utils/request' + +// 鏌ヨ璧勮川鏄庣粏鍒楄〃 +export function getCertificationDetail(query) { + return request({ + url: '/certification/getCertificationDetail', + method: 'post', + params: query + }) +} +// 娣诲姞璧勮川鏄庣粏鍒楄〃 +export function addCertificationDetail(query) { + return request({ + url: '/certification/addCertificationDetail', + method: 'post', + params: query + }) +} +// 鍒犻櫎璧勮川鏄庣粏鍒楄〃 +export function delCertificationDetail(query) { + return request({ + url: '/certification/delCertificationDetail', + method: 'post', + params: query + }) +} diff --git a/src/api/system/customer.js b/src/api/system/customer.js index f64f3e2..a218cfb 100644 --- a/src/api/system/customer.js +++ b/src/api/system/customer.js @@ -1,5 +1,4 @@ import request from '@/utils/request' -import { parseStrEmpty } from "@/utils/ruoyi"; // 鏌ヨ瀹㈡埛鍒楄〃 export function selectCustomPageList(query) { diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss index 2f3b9ef..cacf353 100644 --- a/src/assets/styles/index.scss +++ b/src/assets/styles/index.scss @@ -123,6 +123,9 @@ .app-container { padding: 20px; } +.capacity-scope { + padding: 20px; +} .components-container { margin: 30px 50px; diff --git a/src/views/structural/capability/index.vue b/src/views/structural/capability/index.vue new file mode 100644 index 0000000..2ebcd51 --- /dev/null +++ b/src/views/structural/capability/index.vue @@ -0,0 +1,13 @@ +<script> +export default { +name: "index" +} +</script> + +<template> + +</template> + +<style scoped lang="scss"> + +</style> diff --git a/src/views/structural/laboratory/index.vue b/src/views/structural/laboratory/index.vue new file mode 100644 index 0000000..00da998 --- /dev/null +++ b/src/views/structural/laboratory/index.vue @@ -0,0 +1,462 @@ +<template> + <div class="capacity-scope"> + <div> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> + <el-form-item label="璧勮川鍚嶇О" prop="nickName"> + <el-select v-model="queryParams.name" placeholder="閫夋嫨璧勮川鍚嶇О" size="small" @change="refreshTable()"> + <el-option v-for="dict in dict.type.qualification_name" :key="dict.value" :label="dict.label" :value="dict.value"> + {{ dict.label }} + </el-option> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="refreshTable">鏌� 璇�</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="refresh">閲� 缃�</el-button> + </el-form-item> + </el-form> + </div> + <div> + <el-row class="title"> + <el-col :span="12" style="text-align: left"> + <el-radio-group v-model="radio" @input="selectorSwitch" size="medium" fill="#409EFF"> + <el-radio-button :label="0">璧勮川鏄庣粏</el-radio-button> + <el-radio-button :label="1">璧勮川鎬昏</el-radio-button> + </el-radio-group> + </el-col> + <el-col :span="12" style="text-align: right;" v-if="radio===0"> + <el-button size="small" type="primary" @click="openAdd">璧勮川鏇存柊</el-button> + <el-button size="small" icon="el-icon-delete" @click="handleDel">鍒犻櫎</el-button> + </el-col> + </el-row> + </div> + <div v-if="radio===0"> + <lims-table :tableData="tableData" :column="column" + :isSelection="true" :handleSelectionChange="handleSelectionChange" + :page="page" :tableLoading="tableLoading"></lims-table> + </div> + <div class="table" v-if="radio===1" v-loading="pageLoading" @scroll="scrollFn"> + <el-row :gutter="16"> + <el-col :span="6" v-for="(m,i) in list" :key="i" :xs="24" :sm="12" :md="8" :lg="6" :xl="6" style="margin-bottom: 16px;"> + <div class="table-item"> + <el-image style="width: 102px;height: 102px;margin-right: 20px;border-radius: 16px;" :src="process.env.VUE_APP_BASE_API+'/img/'+m.imageUrl"> + <div slot="error" class="image-error" style="width: 100px; + height: 100px; + border-radius: 16px; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid #EEEEEE;"> + <i class="el-icon-picture-outline" style="font-size:30px;color:#666666;"></i> + </div> + </el-image> + <div class="table-item-right" style="flex: 1;font-size: 12px;color: #666666;"> + <p style="line-height: 26px;">璧勮川鍚嶇О锛�<span style="color: #3A7BFA;">{{ m.name }}</span></p> + <p style="line-height: 26px;">棰佸彂鏃堕棿锛歿{m.recentlyTime}}</p> + <p style="line-height: 26px;">鍒版湡鏃堕棿锛歿{m.expireTime}}</p> + <p> + <span>鐘舵�侊細</span> + <el-tag :type="m.state===0?'danger':'success'" size="small">{{ m.state===0?'澶辨晥':'鏈夋晥' }}</el-tag> + </p> + </div> + </div> + </el-col> + </el-row> + <div v-if="list.length<1&&!pageLoading&&!isLoding" style="color:#909399;font-size:14px;text-align: center;margin-top:200px" >鏆傛棤鏁版嵁</div> + <div v-if="list.length>0"> + <el-button v-if="isLoding" type="text" style="display: flex; margin: 0 auto; color: #909399"> + <i class="el-icon-loading" style="font-size:20px"></i> + </el-button> + <el-button type="text" v-if="finishLoding" style="display: flex; margin: 0 auto; color: #909399">宸茬粡娌℃湁鏇村鍟</el-button> + </div> + </div> + <el-dialog title="璧勮川鏇存柊" :visible.sync="qualificationsConnectVisible" width="400px"> + <div class="search_thing" style="margin-bottom: 16px;"> + <div class="search_label" style="width:120px"><span class="required-span">* </span>璧勮川鍚嶇О锛�</div> + <div class="search_input"> + <el-select v-model="formData.name" placeholder="璇烽�夋嫨" style="width: 100%;" size="small" clearable> + <el-option + v-for="item in qualificationsList" + :key="item.value" + :label="item.label" + :value="item.value"> + </el-option> + </el-select> + </div> + </div> + <div class="search_thing" style="margin-bottom: 16px;"> + <div class="search_label" style="width:120px"><span class="required-span">* </span>璧勮川缂栫爜锛�</div> + <div class="search_input"> + <el-input + size="small" + placeholder="璇疯緭鍏�" + clearable + v-model="formData.code"></el-input> + </div> + </div> + <div class="search_thing" style="margin-bottom: 16px;"> + <div class="search_label" style="width:120px"><span class="required-span">* </span>棰佸彂鏈烘瀯锛�</div> + <div class="search_input"> + <el-input + size="small" + placeholder="璇疯緭鍏�" + clearable + v-model="formData.organization"></el-input> + </div> + </div> + <div class="search_thing" style="margin-bottom: 16px;"> + <div class="search_label" style="width:120px">璧勮川璇存槑锛�</div> + <div class="search_input"> + <el-input + size="small" + placeholder="璇疯緭鍏�" + clearable + v-model="formData.explanation"></el-input> + </div> + </div> + + <div class="search_thing" style="margin-bottom: 16px;"> + <div class="search_label" style="width:120px"><span class="required-span">* </span>棰佸彂鏃堕棿锛�</div> + <div class="search_input"> + <el-date-picker style="width:100%" v-model="formData.dateOfIssuance" + type="datetime" + size="small" + format="yyyy-MM-dd HH:mm:ss" + value-format="yyyy-MM-dd HH:mm:ss" + clearable + placeholder="閫夋嫨鏃ユ湡"> + </el-date-picker> + </div> + </div> + <div class="search_thing" style="margin-bottom: 16px;"> + <div class="search_label" style="width:120px"><span class="required-span">* </span>鍒版湡鏃堕棿锛�</div> + <div class="search_input"> + <el-date-picker style="width:100%" v-model="formData.expireTime" + type="datetime" + size="small" + format="yyyy-MM-dd HH:mm:ss" + value-format="yyyy-MM-dd HH:mm:ss" + clearable + placeholder="閫夋嫨鏃ユ湡"> + </el-date-picker> + </div> + </div> + <div class="search_thing" style="margin-bottom: 16px;"> + <div class="search_label" style="width:120px">璧勮川鍥剧墖锛�</div> + <div class="search_input"> + <el-upload + ref="upload" + :action="action" + :on-success="m=>handleSuccessUpImg(m,'imageUrl')" + accept='image/jpg,image/jpeg,image/png' + :multiple="false" + :limit="1" + :headers="headers" :on-change="beforeUpload" + :on-error="onError"> + <el-button slot="trigger" size="small" type="primary">閫夊彇鍥剧墖</el-button> + </el-upload> + </div> + </div> + <div class="search_thing" style="margin-bottom: 16px;"> + <div class="search_label" style="width:120px">璧勮川闄勪欢锛�</div> + <div class="search_input"> + <el-upload + ref="upload1" + :action="action" + :on-success="m=>handleSuccessUpImg(m,'fileUrl')" + accept='image/jpg,image/jpeg,image/png,application/pdf,.doc,.docx' :headers="headers" :multiple="false" :limit="1" :on-change="beforeUpload1" + :on-error="onError1"> + <el-button slot="trigger" size="small" type="primary">閫夊彇鏂囦欢</el-button> + </el-upload> + </div> + </div> + <span slot="footer" class="dialog-footer"> + <el-button @click="qualificationsConnectVisible = false">鍙� 娑�</el-button> + <el-button type="primary" @click="confirmQualifications" :loading="loading">纭� 瀹�</el-button> + </span> + </el-dialog> + </div> +</template> + +<script> +import limsTable from "@/components/Table/lims-table.vue"; +import {addCertificationDetail, delCertificationDetail, getCertificationDetail} from "@/api/structural/laboratory"; + +export default { + components: { + limsTable + }, + dicts: ['qualification_name'], + data() { + return { + radio: 0, + queryParams: { + name: '' + }, + tableData: [], + selection: [], + column: [ + {label: '璧勮川鍚嶇О', prop: 'name'}, + {label: '璧勮川缂栫爜', prop: 'code'}, + {label: '棰佸彂鏈烘瀯', prop: 'organization'}, + {label: '璧勮川璇存槑', prop: 'explanation'}, + {label: '棣栨棰佸彂鏃堕棿', prop: 'firstIssuanceDate'}, + {label: '鏈�杩戦鍙戞椂闂�', prop: 'latestIssuanceDate'}, + {label: '鍒版湡棰佸彂鏃堕棿', prop: 'expireTime'}, + { + dataType: 'action', + fixed: 'right', + label: '鎿嶄綔', + operation: [ + { + name: '闄勪欢涓嬭浇', + type: 'text', + clickFun: (row) => { + this.handleDownLoad(row); + }, + }, + ] + } + ], + page: { + total:0, + size:10, + current:0 + }, + tableLoading: false, + qualificationsList:[], + qualificationsConnectVisible:false, + formData:{}, + loading:false, + pageLoading:false, + isLoding: false, // 鍔犺浇涓紝loading鍥炬爣,榛樿涓簍rue + finishLoding: false, // 鍔犺浇瀹屾垚锛屾樉绀哄凡缁忔病鏈夋洿澶氫簡 + currentPage: 1, // 褰撳墠椤� + pageSize: 16, // 涓�椤�16鏉� + total: '', + list:[], + } + }, + computed: { + headers() { + return { + 'token': sessionStorage.getItem('token') + } + }, + action() { + return '' + } + }, + mounted() { + this.refreshTable() + }, + methods: { + selectorSwitch(radio) { + if(radio === '1'){ + this.list = []; + this.refreshTable(); + } + }, + refreshTable() { + if (this.radio === '0') { + getCertificationDetail({...this.page,...this.queryParams,}).then(res => { + this.tableLoading = false + if (res.code === 200) { + this.tableData = res.data + this.page.total = res.total + } + }).catch(err => { + this.tableLoading = false + }) + } else { + if(this.currentPage>1){ + this.isLoding = true + }else{ + this.pageLoading = true + } + if(this.list.length===0){ + window.addEventListener("scroll", this.throttle(this.scrollFn, 20000)); + } + getCertificationDetail({ + page: { + current: this.currentPage, + size: this.pageSize + }, + entity: this.queryParams + }).then(res => { + if(res.code===200){ + this.total = res.data.body.total + let list = res.data.body.records; + if(list.length===0){ + this.finishLoding = true; + }else{ + if(list.length<this.pageSize){ + this.finishLoding = true; + } + this.list = this.list.concat(list) + if(this.total===this.list.length){ + this.finishLoding = true; + } + } + } + this.pageLoading = false + this.isLoding = false; + }).catch(err => { + this.pageLoading = false + this.isLoding = false; + }) + } + }, + // 閲嶇疆 + refresh() { + this.queryParams.name = '' + this.page.size = 10 + this.page.current = 1 + this.refreshTable() + }, + // 琛ㄦ牸澶氶�� + handleSelectionChange (selection) { + this.selection = selection; + }, + // 璧勮川鏄庣粏鎵归噺鍒犻櫎 + handleDel(){ + if (this.selection.length===0) { + this.$message.warning('璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�') + return + } + const delIds = [] + this.selection.forEach(item => { + delIds.push(item.id) + }) + delCertificationDetail(delIds).then(res => { + if (res.code !== 200) return + this.refreshTable(); + this.$message.success('鍒犻櫎鎴愬姛') + }) + }, + // 璧勮川鏄庣粏闄勪欢涓嬭浇 + handleDownLoad(row){ + // let url = row.fileUrl; + // const link = document.createElement('a'); + // link.href = this.javaApi + '/img/'+ url; + // document.body.appendChild(link); + // link.target = '_blank'; + // link.click(); + const url = process.env.VUE_APP_BASE_API + '/img/'+ row.fileUrl + this.$download.saveAs(url, row.fileUrl); + }, + openAdd() { + this.qualificationsConnectVisible = true; + this.$nextTick(()=>{ + this.$refs.upload.clearFiles() + this.$refs.upload1.clearFiles() + }) + this.formData = {}; + }, + handleSuccessUpImg(response,name) { + if (response.code === 200) { + this.formData[name] = response.data.url; + } + }, + beforeUpload(file) { + if (file.size > 1024 * 1024 * 10) { + this.$message.error('涓婁紶鏂囦欢涓嶈秴杩�10M'); + this.$refs.upload.clearFiles() + return false; + } else { + return true; + } + }, + onError(err, file, fileList) { + this.$message.error('涓婁紶澶辫触') + this.$refs.upload.clearFiles() + }, + beforeUpload1(file) { + if (file.size > 1024 * 1024 * 10) { + this.$message.error('涓婁紶鏂囦欢涓嶈秴杩�10M'); + this.$refs.upload1.clearFiles() + return false; + } else { + return true; + } + }, + onError1(err, file, fileList) { + this.$message.error('涓婁紶澶辫触') + this.$refs.upload1.clearFiles() + }, + confirmQualifications(){ + if(!this.formData.name){ + this.$message.error('鏈~鍐欒祫璐ㄥ悕绉�'); + return + } + if(!this.formData.code){ + this.$message.error('鏈~鍐欒祫璐ㄧ紪鐮�'); + return + } + if(!this.formData.organization){ + this.$message.error('鏈~鍐欓鍙戞満鏋�'); + return + } + if(!this.formData.expireTime){ + this.$message.error('鏈~鍐欏埌鏈熼鍙戞椂闂�'); + return + } + if(!this.formData.imageUrl){ + this.$message.error('鏈笂浼犺祫璐ㄥ浘鐗�'); + return + } + if(!this.formData.fileUrl){ + this.$message.error('鏈笂浼犺祫璐ㄩ檮浠�'); + return + } + this.loading = true; + addCertificationDetail({...this.formData}).then(res => { + this.loading = false + if (res.code === 201) return + this.$message.success('宸叉彁浜�') + this.refreshTable('page') + this.qualificationsConnectVisible = false + }) + }, + // 婊氬姩瑙﹀簳鍔犺浇 + scrollFn() { + let clientHeight = document.documentElement.clientHeight - 18; //鍙鍖哄煙 + let scrollHeight = document.body.scrollHeight; // 婊氬姩鏂囨。楂樺害 + let scrollTop = parseInt(document.documentElement.scrollTop); // 宸叉粴鍔ㄧ殑楂樺害 + let height = 300; + if (scrollTop + clientHeight >= scrollHeight - height && scrollHeight !== 0) { + if (!this.finishLoding&&this.currentPage*this.pageSize<this.total) { + this.currentPage = this.currentPage + 1; + this.refreshTable(); + } + } else { + return false; + } + }, + throttle(fn, wait) { + // 灏佽鍑芥暟杩涜鑺傛祦 + var timer = null; + return function () { + var context = this; + var args = arguments; + if (!timer) { + timer = setTimeout(function () { + fn.apply(context, args); + timer = null; + }, wait); + } + }; + }, + }, + destroyed() { + window.removeEventListener("scroll", this.throttle(), false); + }, +} +</script> + +<style scoped> +.title { + height: 40px; + line-height: 40px; + margin-bottom: 10px; +} +</style> diff --git a/src/views/structural/premises/index.vue b/src/views/structural/premises/index.vue new file mode 100644 index 0000000..65bfbb8 --- /dev/null +++ b/src/views/structural/premises/index.vue @@ -0,0 +1,13 @@ +<script> +export default { + name: "index" +} +</script> + +<template> + +</template> + +<style scoped lang="scss"> + +</style> -- Gitblit v1.9.3