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