From 2172582b0fd2d742e3536617689bf8cd0939a7a9 Mon Sep 17 00:00:00 2001
From: qun <gongqun@develop.com>
Date: Fri, 1 Jul 2022 17:39:11 +0800
Subject: [PATCH 1/2] =?UTF-8?q?=E5=88=B6=E5=BA=A6=E7=AE=A1=E7=90=86?=
 =?UTF-8?q?=E7=BC=96=E8=BE=91=E9=A1=B5=E9=9D=A2=E6=8E=A5=E5=8F=A3=E8=81=94?=
 =?UTF-8?q?=E8=B0=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 WebSite/src/api/AttachFile.js                 |   4 +-
 WebSite/src/api/Attention.js                  |  14 +
 WebSite/src/api/BaseInfo.js                   |  18 ++
 WebSite/src/api/Institution.js                |   6 +-
 WebSite/src/core/base/request.js              |  20 +-
 WebSite/src/utils/Common.js                   |  42 +++
 .../components/FileItems.vue                  |  26 +-
 .../components/FileRelation.vue               |  22 +-
 .../policy-system-library/policy-edit.vue     | 280 +++++++++++-------
 .../system-management.vue                     | 125 +++++++-
 10 files changed, 425 insertions(+), 132 deletions(-)
 create mode 100644 WebSite/src/api/Attention.js
 create mode 100644 WebSite/src/api/BaseInfo.js

diff --git a/WebSite/src/api/AttachFile.js b/WebSite/src/api/AttachFile.js
index 6620435..ab1ac32 100644
--- a/WebSite/src/api/AttachFile.js
+++ b/WebSite/src/api/AttachFile.js
@@ -11,7 +11,9 @@ class AttachFile {
   }
   // 3. 涓嬭浇鍒跺害鏂囦欢(澶氫釜闄勪欢鎵撳寘涓嬭浇)
   static downloadFile(data) {
-    return request.post('/attachFile/downloadFile', data);
+    return request.post('/attachFile/downloadFile', data, {
+      responseType: 'blob'
+    });
   }
 }
 
diff --git a/WebSite/src/api/Attention.js b/WebSite/src/api/Attention.js
new file mode 100644
index 0000000..1f6e38b
--- /dev/null
+++ b/WebSite/src/api/Attention.js
@@ -0,0 +1,14 @@
+import request from '@/core/base/request';
+
+class Attention {
+  // 1  鍔犲叧娉�(鎵归噺)
+  static addAttention(data) {
+    return request.post('/attention/addAttention', data);
+  }
+  // 2  鍙栨秷鍏虫敞
+  static removeAttention(data) {
+    return request.post('/attention/removeAttention', data);
+  }
+}
+
+export default Attention;
diff --git a/WebSite/src/api/BaseInfo.js b/WebSite/src/api/BaseInfo.js
new file mode 100644
index 0000000..06a710c
--- /dev/null
+++ b/WebSite/src/api/BaseInfo.js
@@ -0,0 +1,18 @@
+import request from '@/core/base/request';
+
+class BaseInfo {
+  // 1. 鏌ヨ褰撳墠鐧诲綍浜鸿鑹插垪琛�
+  static getRoleListByLogin() {
+    return request.get('/baseInfo/getRoleListByLogin');
+  }
+  // 3. 鏌ヨ瀹℃牳浜哄垪琛�
+  static getAuditorList() {
+    return request.get('/baseInfo/getAuditorList');
+  }
+  // 鏌ヨ褰撳墠鐧诲綍浜�
+  static getLoginInfo() {
+    return request.get('/baseInfo/getLoginInfo');
+  }
+}
+
+export default BaseInfo;
diff --git a/WebSite/src/api/Institution.js b/WebSite/src/api/Institution.js
index 18d76cb..40508cb 100644
--- a/WebSite/src/api/Institution.js
+++ b/WebSite/src/api/Institution.js
@@ -2,7 +2,7 @@ import request from '@/core/base/request';
 
 class Institution {
   // 1. 鏌ヨ鍒跺害缂栧彿
-  static getClassifyTree() {
+  static getInstitutionDocumentCode() {
     return request.get('/institution/getInstitutionDocumentCode');
   }
   // 2. 鏂板/缂栬緫鍒跺害
@@ -49,6 +49,10 @@ class Institution {
   static getSearchLogList() {
     return request.get('/institution/getSearchLogList');
   }
+  // 鏌ヨ鍒跺害鍏宠仈鍒跺害(鍜屾湭鍏宠仈鍒跺害)(鍖呭惈妯$硦鏌ヨ)
+  static getInstitutionRelationList(data) {
+    return request.post('/institution/getInstitutionRelationList', data);
+  }
 }
 
 export default Institution;
diff --git a/WebSite/src/core/base/request.js b/WebSite/src/core/base/request.js
index 7983129..07fb2c8 100644
--- a/WebSite/src/core/base/request.js
+++ b/WebSite/src/core/base/request.js
@@ -28,7 +28,25 @@ axiosInstance.interceptors.request.use(
 axiosInstance.interceptors.response.use(
   response => {
     store.dispatch('app/endLoading');
-    return response.data;
+    // blob绫诲瀷闇€鍦ㄨ皟鐢╝pi鍙傛暟浣嶇疆浼犲叆鍙傛暟 responseType: 'blob'
+    if (response.config.responseType === 'blob') {
+      // 杩斿洖鏂囦欢娴佸唴瀹�
+      return Promise.resolve({
+        headers: response.headers,
+        data: response.data,
+        type: response.data.type
+      });
+    }
+    const { data } = response;
+    if (data.code !== '00000') {
+      ElNotification({
+        message: data.description,
+        type: 'error',
+        duration: 5 * 1000
+      });
+      return Promise.reject(data.description);
+    }
+    return data;
   },
   error => {
     store.dispatch('app/endLoading');
diff --git a/WebSite/src/utils/Common.js b/WebSite/src/utils/Common.js
index c0cd7d5..58ec8e5 100644
--- a/WebSite/src/utils/Common.js
+++ b/WebSite/src/utils/Common.js
@@ -21,6 +21,48 @@ class Common {
     });
     return targetObj;
   }
+  // blob涓簀son鏃惰В鏋恓son骞惰繑鍥瀝esolve
+  // blob涓簆df鏃惰繑鍥瀊lob閾炬帴
+  // blob涓哄叾瀹冪被鍨嬫椂锛岃緭鍑轰笅杞藉苟杩斿洖resolve
+  static getJsonOrDownloadFile(res) {
+    return new Promise(resolve => {
+      if (res.type === 'application/json') {
+        var reader = new FileReader();
+        reader.readAsText(res.data, 'utf-8');
+        reader.onload = function() {
+          return resolve(JSON.parse(reader.result));
+        };
+        // } else if (!res.isFile && res.type === 'application/pdf') {
+        //   let href = this.getFileUrl(res);
+        //   return resolve({ href });
+      } else {
+        this.downloadFile(res);
+        return resolve(res);
+      }
+    });
+  }
+
+  static downloadFile(res) {
+    if (!res.data) return;
+    let fileName = decodeURI(
+      res.headers['content-disposition'].split('filename=')[1]
+    );
+    fileName = fileName.replace(/\\"/g, '');
+    var blob = new Blob([res.data], { type: res.data.type });
+    // 閽堝浜嶪E娴忚鍣ㄧ殑澶勭悊, 鍥犻儴鍒咺E娴忚鍣ㄤ笉鏀寔createObjectURL
+    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
+      window.navigator.msSaveOrOpenBlob(blob, fileName);
+    } else {
+      var downloadElement = document.createElement('a');
+      var href = window.URL.createObjectURL(blob); // 鍒涘缓涓嬭浇鐨勯摼鎺�
+      downloadElement.href = href;
+      downloadElement.download = fileName; // 涓嬭浇鍚庢枃浠跺悕
+      document.body.appendChild(downloadElement);
+      downloadElement.click(); // 鐐瑰嚮涓嬭浇
+      document.body.removeChild(downloadElement); // 涓嬭浇瀹屾垚绉婚櫎鍏冪礌
+      window.URL.revokeObjectURL(href); // 閲婃斁鎺塨lob瀵硅薄
+    }
+  }
 }
 
 export default Common;
diff --git a/WebSite/src/views/policy-system-library/components/FileItems.vue b/WebSite/src/views/policy-system-library/components/FileItems.vue
index d434e26..42f4797 100644
--- a/WebSite/src/views/policy-system-library/components/FileItems.vue
+++ b/WebSite/src/views/policy-system-library/components/FileItems.vue
@@ -30,6 +30,7 @@
 </template>
 <script>
 import { reactive, computed, toRefs } from 'vue';
+import AttachFile from '@/api/AttachFile';
 export default {
   name: 'FileItems',
   props: {
@@ -44,6 +45,9 @@ export default {
     title: {
       type: String,
       default: '涓婁紶鏂囦欢'
+    },
+    fileType: {
+      type: Number
     }
   },
   setup(props, context) {
@@ -52,7 +56,7 @@ export default {
     });
     const fileList = computed({
       get() {
-        return props.files;
+        return props.files || [];
       },
       set(val) {
         context.emit('update:files', val);
@@ -60,7 +64,7 @@ export default {
     });
     const fileids = computed({
       get() {
-        return props.modelValue;
+        return props.modelValue || [];
       },
       set(val) {
         context.emit('update:modelValue', val);
@@ -70,11 +74,19 @@ export default {
       fileList.value.splice(fileList.value.indexOf(file), 1);
       fileids.value.splice(fileids.value.indexOf(file.id), 1);
     };
-    const onUploadHandler = (files, callback) => {
-      // todo 涓婁紶
-      const res = files.map(file => ({ id: file.uid, name: file.name }));
-      fileList.value.push(...res);
-      fileids.value.push(...res.map(item => item.id));
+    const onUploadHandler = async (files, callback) => {
+      // 涓婁紶
+      let req = new FormData();
+      req.append('fileType', props.fileType);
+      for (let index = 0; index < files.length; index++) {
+        const file = files[index];
+        req.append('files', file.raw);
+      }
+      const res = await AttachFile.uploadFile(req);
+      fileList.value.push(
+        ...files.map(file => ({ id: file.uid, name: file.name }))
+      );
+      fileids.value.push(...res.data);
       data.uploadFileDialog = false;
       callback();
     };
diff --git a/WebSite/src/views/policy-system-library/components/FileRelation.vue b/WebSite/src/views/policy-system-library/components/FileRelation.vue
index 6f9632b..22cff63 100644
--- a/WebSite/src/views/policy-system-library/components/FileRelation.vue
+++ b/WebSite/src/views/policy-system-library/components/FileRelation.vue
@@ -57,6 +57,7 @@
 </template>
 <script>
 import { reactive, computed, toRefs } from 'vue';
+import Institution from '@/api/Institution';
 export default {
   name: 'FileRelation',
   props: {
@@ -67,6 +68,9 @@ export default {
     files: {
       type: Array,
       default: () => []
+    },
+    id: {
+      type: String
     }
   },
   setup(props, context) {
@@ -77,7 +81,7 @@ export default {
     });
     const fileList = computed({
       get() {
-        return props.files;
+        return props.files || [];
       },
       set(val) {
         context.emit('update:files', val);
@@ -85,19 +89,21 @@ export default {
     });
     const fileids = computed({
       get() {
-        return props.modelValue;
+        return props.modelValue || [];
       },
       set(val) {
         context.emit('update:modelValue', val);
       }
     });
-    const onShowRelation = () => {
-      // todo: 鑾峰彇鍒跺害鍒楄〃
+    const onShowRelation = async () => {
+      // 鑾峰彇鍒跺害鍒楄〃
+      const res = await Institution.getInstitutionRelationList({
+        id: props.id
+      });
       data.selectFileList = [
-        { id: 11, name: '鍒跺害1' },
-        { id: 12, name: '鍒跺害2' },
-        { id: 13, name: '鍒跺害3' }
-      ];
+        ...res.data[0].noRelationInstitutionList,
+        ...res.data[0].relationInstitutionList
+      ].map(t => ({ id: t.id, name: t.title }));
       const ids = data.selectFileList.map(t => t.id);
       for (let i = 0; i < fileList.value.length; i++) {
         const file = fileList.value[i];
diff --git a/WebSite/src/views/policy-system-library/policy-edit.vue b/WebSite/src/views/policy-system-library/policy-edit.vue
index 172e41f..b4539cd 100644
--- a/WebSite/src/views/policy-system-library/policy-edit.vue
+++ b/WebSite/src/views/policy-system-library/policy-edit.vue
@@ -1,29 +1,37 @@
 <template>
   <div class="app-container">
-    <Crumbs :routeList="['鏀跨瓥鍒跺害搴�', title]" showroute back-to-my-home />
+    <!-- <Crumbs :routeList="['鏀跨瓥鍒跺害搴�', title]" showroute back-to-my-home /> -->
     <div class="app-content">
       <el-card class="edit-card">
-        <el-form label-width="100px" label-position="left">
+        <el-form
+          :model="editInfo"
+          :rules="rules"
+          ref="editInfoRef"
+          label-width="100px"
+          label-position="left"
+        >
           <el-row :gutter="40">
             <el-col :span="8">
               <el-form-item label="鏂囨。缂栧彿">
-                <el-input v-model="editInfo.keywords" placeholder="鑷姩鐢熸垚" />
-              </el-form-item>
-            </el-col>
-            <el-col :span="8">
-              <el-form-item label="鍒跺害鍚嶇О">
-                <el-input v-model="editInfo.no" placeholder="璇疯緭鍏ュ埗搴﹀悕绉�" />
+                <el-input
+                  v-model="editInfo.documentCode"
+                  placeholder="鑷姩鐢熸垚"
+                  readonly
+                />
               </el-form-item>
             </el-col>
             <el-col :span="8">
-              <el-form-item label="鏂囧彿">
-                <el-input v-model="editInfo.no" placeholder="璇疯緭鍏ユ枃鍙�" />
+              <el-form-item label="鍒跺害鍚嶇О" prop="title">
+                <el-input
+                  v-model="editInfo.title"
+                  placeholder="璇疯緭鍏ュ埗搴﹀悕绉�"
+                />
               </el-form-item>
             </el-col>
             <el-col :span="8">
-              <el-form-item label="鍒嗙被">
+              <el-form-item label="鍒嗙被" prop="classifyId">
                 <el-tree-select
-                  v-model="editInfo.type1"
+                  v-model="editInfo.classifyId"
                   :data="treeData"
                   :props="defaultProps"
                   check-strictly
@@ -32,63 +40,93 @@
               </el-form-item>
             </el-col>
             <el-col :span="8">
-              <el-form-item label="棰佸竷鏃ユ湡">
-                <el-date-picker
-                  style="width: 100%"
-                  v-model="editInfo.date"
-                  type="date"
-                  placeholder="璇烽€夋嫨棰佸竷鏃ユ湡"
+              <el-form-item label="涓婁紶浜�">
+                <el-input
+                  v-model="editInfo.creatorName"
+                  placeholder="褰撳墠鐧诲綍璐﹀彿锛堣嚜鍔ㄧ敓鎴愶級"
+                  readonly
                 />
               </el-form-item>
             </el-col>
             <el-col :span="8">
               <el-form-item label="涓婁紶鏃ユ湡">
+                <el-input
+                  v-model="editInfo.createDate"
+                  placeholder="褰撳墠鏃堕棿锛堣嚜鍔ㄧ敓鎴愶級"
+                  readonly
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="棰佸竷鏃ユ湡" prop="publishDate">
                 <el-date-picker
                   style="width: 100%"
-                  v-model="editInfo.date"
+                  v-model="editInfo.publishDate"
                   type="date"
-                  placeholder="褰撳墠鏃堕棿锛堣嚜鍔ㄧ敓鎴愶級"
+                  placeholder="璇烽€夋嫨棰佸竷鏃ユ湡"
                 />
               </el-form-item>
             </el-col>
             <el-col :span="8">
-              <el-form-item label="涓婁紶浜�">
-                <el-select v-model="editInfo.user" style="width:100%">
-                  <el-option label="寮犱笁" value="寮犱笁" />
-                </el-select>
+              <el-form-item label="鏂囧彿" prop="documentNo">
+                <el-input
+                  v-model="editInfo.documentNo"
+                  placeholder="璇疯緭鍏ユ枃鍙�"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="鍙戞枃鍗曚綅" prop="unit">
+                <el-input
+                  v-model="editInfo.unit"
+                  placeholder="璇疯緭鍏ュ彂鏂囧崟浣�"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="8"> </el-col>
+            <el-col :span="8">
+              <el-form-item label="鎵€灞炲簱">
+                <el-radio-group v-model="editInfo.belongLibrary" size="small">
+                  <el-radio :label="1" :disabled="isDept">閫氱敤鍒跺害搴�</el-radio>
+                  <el-radio :label="2">閮ㄩ棬绉佹湁搴�</el-radio>
+                </el-radio-group>
               </el-form-item>
             </el-col>
             <el-col :span="8">
               <el-form-item label="鏄惁闇€瑕佸鎵�">
-                <el-radio-group v-model="editInfo.isAp" size="small">
+                <el-radio-group v-model="editInfo.isAudit" size="small">
                   <el-radio :label="true">鏄�</el-radio>
                   <el-radio :label="false">鍚�</el-radio>
                 </el-radio-group>
               </el-form-item>
-              <el-form-item label="瀹℃壒浜�" v-if="editInfo.isAp">
+            </el-col>
+            <el-col :span="8">
+              <el-form-item
+                label="瀹℃壒浜�"
+                v-if="editInfo.isAudit"
+                prop="auditorId"
+              >
                 <el-select
                   filterable
-                  v-model="editInfo.user"
+                  v-model="editInfo.auditorId"
                   style="width:100%"
                 >
-                  <el-option label="寮犱笁" value="寮犱笁" />
+                  <el-option
+                    v-for="(item, index) in userList"
+                    :key="index"
+                    :label="item.name"
+                    :value="item.id"
+                  />
                 </el-select>
               </el-form-item>
             </el-col>
-            <el-col :span="8">
-              <el-form-item label="鎵€灞炲簱">
-                <el-radio-group v-model="editInfo.type2" size="small">
-                  <el-radio :label="1" disabled>閫氱敤鍒跺害搴�</el-radio>
-                  <el-radio :label="2">閮ㄩ棬绉佹湁搴�</el-radio>
-                </el-radio-group>
-              </el-form-item>
-            </el-col>
             <el-col :span="8">
               <el-form-item label="鍒跺害鏂囦欢">
                 <FileItems
                   title="涓婁紶鍒跺害鏂囦欢"
-                  v-model="editInfo.fileids"
-                  v-model:files="editInfo.files"
+                  v-model="editInfo.institutionFileIdList"
+                  v-model:files="editInfo.institutionFileList"
+                  :fileType="1"
                 />
               </el-form-item>
             </el-col>
@@ -96,22 +134,18 @@
               <el-form-item label="鍒跺害闄勪欢">
                 <FileItems
                   title="涓婁紶鍒跺害闄勪欢"
-                  v-model="editInfo.fileids3"
-                  v-model:files="editInfo.files3"
+                  v-model="editInfo.attachFileIdList"
+                  v-model:files="editInfo.attachFileList"
+                  :fileType="2"
                 />
               </el-form-item>
             </el-col>
             <el-col :span="8">
               <el-form-item label="鍏宠仈鍒跺害">
-                <!-- <FileItems
-                  title="涓婁紶鍏宠仈鏂囦欢"
-                  v-model="editInfo.fileids2"
-                  v-model:files="editInfo.files2"
-                >
-                </FileItems> -->
                 <FileRelation
-                  v-model="editInfo.fileids2"
-                  v-model:files="editInfo.files2"
+                  v-model="editInfo.relationInstitutionIdList"
+                  v-model:files="editInfo.relationInstitutionList"
+                  :id="editInfo.id"
                 />
               </el-form-item>
             </el-col>
@@ -121,13 +155,18 @@
               </el-form-item>
             </el-col>
             <el-col :span="24" class="btn-box">
-              <el-button type="primary" plain @click="onSave()" icon="Check">
+              <el-button
+                type="primary"
+                plain
+                @click="onSave(false)"
+                icon="Check"
+              >
                 淇濆瓨
               </el-button>
               <el-button
                 type="success"
                 plain
-                @click="onSave(1)"
+                @click="onSave(true)"
                 icon="Position"
               >
                 淇濆瓨骞跺彂甯�
@@ -144,16 +183,18 @@
 </template>
 
 <script>
-import { onMounted, reactive, toRefs } from 'vue';
-import {
-  useRoute
-  // , useRouter
-} from 'vue-router';
+import { onMounted, reactive, toRefs, ref } from 'vue';
+import { useRoute } from 'vue-router';
 
 // import { ElMessage, ElMessageBox } from 'element-plus';
 import FileItems from './components/FileItems';
 import FileRelation from './components/FileRelation';
 import { iOrFramerouterGo } from '@/router';
+import Classify from '@/api/Classify';
+import Institution from '@/api/Institution';
+// import AttachFile from '@/api/AttachFile';
+import BaseInfo from '@/api/BaseInfo';
+import moment from 'moment';
 export default {
   name: 'PolicyEdit',
   components: {
@@ -161,67 +202,101 @@ export default {
     FileRelation
   },
   setup() {
-    // const router = useRouter();
     const route = useRoute();
     const data = reactive({
-      id: route.query.id,
-      title: route.query.id ? '缂栬緫鍒跺害' : '鏂板缓鍒跺害',
-      editInfo: { isAp: false },
       defaultProps: {
         children: 'children',
         label: 'name',
         value: 'id'
       },
-      treeData: []
+      editInfo: {
+        id: route.query.id, // 鍒跺害id
+        documentCode: '', // 鍒跺害缂栧彿
+        documentNo: '', // 鍒跺害鏂囧彿
+        unit: '', // 鍙戞枃鍗曚綅
+        title: '', // 鏍囬
+        content: '', // 姝f枃
+        classifyId: '', // 鍒嗙被id
+        publishDate: '', // 棰佸竷鏃ユ湡
+        belongLibrary: 2, // 鎵€灞炲簱(1:閫氱敤鍒跺害搴� 2锛氶儴闂ㄧ鏈夊簱)
+        isAudit: true, // 鏄惁闇€瑕佸鏍�(true: 瀹℃牳  false:涓嶅鏍�
+        auditorId: '', // 瀹℃牳浜篿d
+        isPublish: '', // 鏄惁鍙戝竷 (true: 鍙戝竷  false: 涓嶅彂甯�)
+        remark: '', // 澶囨敞
+        institutionFileIdList: [], // 鍒跺害鏂囦欢id闆嗗悎
+        institutionFileList: [], // 鍒跺害鏂囦欢闆嗗悎
+        attachFileIdList: [], // 鍒跺害闄勪欢id闆嗗悎
+        attachFileList: [], // 鍒跺害闄勪欢闆嗗悎
+        relationInstitutionIdList: [], // 鍏宠仈鍒跺害id闆嗗悎
+        relationInstitutionList: [] // 鍏宠仈鍒跺害闆嗗悎
+      },
+      rules: {
+        title: [
+          { required: true, message: '鍒跺害鍚嶇О涓嶈兘涓虹┖', trigger: 'blur' }
+        ],
+        classifyId: [
+          { required: true, message: '鍒嗙被涓嶈兘涓虹┖', trigger: 'change' }
+        ],
+        publishDate: [
+          { required: true, message: '棰佸竷鏃ユ湡涓虹┖', trigger: 'change' }
+        ],
+        documentNo: [
+          { required: true, message: '鏂囧彿涓嶈兘涓虹┖', trigger: 'blur' }
+        ],
+        unit: [
+          { required: true, message: '鍙戞枃鍗曚綅涓嶈兘涓虹┖', trigger: 'blur' }
+        ],
+        auditorId: [
+          { required: true, message: '瀹℃壒浜轰笉鑳戒负绌�', trigger: 'change' }
+        ]
+      },
+      treeData: [],
+      userList: [],
+      roleList: [],
+      isDept: true
     });
+    const editInfoRef = ref(null);
 
-    const getData = () => {
-      data.editInfo = {
-        id: data.id,
-        isAp: true,
-        type2: 2,
-        files: [],
-        fileids: [],
-        files2: [],
-        fileids2: [],
-        files3: [],
-        fileids3: [],
-        content: ``
-      };
-      data.editInfo.content = `<h2>娴嬭瘯鏍囬</h2><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p><h3>娴嬭瘯鏍囬</h3><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><h2>娴嬭瘯鏍囬</h2><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p><h3>娴嬭瘯鏍囬</h3><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p>`;
-      // setTimeout(() => {
-      //   data.editInfo.content = `<h2>娴嬭瘯鏍囬</h2><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p><h3>娴嬭瘯鏍囬</h3><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><h2>娴嬭瘯鏍囬</h2><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p><h3>娴嬭瘯鏍囬</h3><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p>`;
-      // }, 2000);
+    const getData = async () => {
+      if (!data.editInfo.id) {
+        // 鏂板鍒跺害
+        data.editInfo.createDate = moment().format('YYYY-MM-DD');
+        const res = await Institution.getInstitutionDocumentCode();
+        data.editInfo.documentCode = res.data[0];
+        const userRes = await BaseInfo.getLoginInfo();
+        data.editInfo.creatorName = userRes.data[0].name;
+        return;
+      }
+      const res = await Institution.getInstitutionById({
+        id: data.editInfo.id
+      });
+      data.editInfo = res.data[0];
     };
 
-    onMounted(() => {
-      // todo 鑾峰彇鍒跺害鍒嗙被鏍�
-      data.treeData = [
-        {
-          id: 1,
-          name: '鏀垮簻浼氳鍑嗗垯鍒跺害',
-          children: [
-            { id: 2, name: '浼氳鍒跺害+琛ュ厖瑙勫畾' },
-            { id: 3, name: '鍩烘湰鎸囧紩' },
-            { id: 4, name: '鍩烘湰鍑嗗垯' }
-          ]
-        },
-
-        {
-          id: 8,
-          name: '璐㈠姟棰勭畻绠$悊鍒跺害'
-        }
-      ];
-      getData();
+    onMounted(async () => {
+      const res = await Classify.getClassifyTree();
+      data.treeData = res.data;
+      const userRes = await BaseInfo.getAuditorList();
+      data.userList = userRes.data;
+      const roleRes = await BaseInfo.getRoleListByLogin();
+      data.roleList = roleRes.data.map(t => t.name);
+      data.isDept =
+        !data.roleList.includes('鏁欏绠$悊鍛�') &&
+        !data.roleList.includes('鏁欏瀹℃牳鍛�');
+      await getData();
     });
 
-    const onSave = (type = 0) => {
-      console.log(data.editInfo);
-      if (type) {
+    const onSave = async (isPublish = false) => {
+      data.editInfo.isPublish = isPublish;
+      const valid = await editInfoRef.value.validate().catch(() => false);
+      if (!valid) {
+        return;
+      }
+      const res = await Institution.saveInstitution(data.editInfo);
+      console.log(res);
+      if (isPublish) {
         // 淇濆瓨骞跺彂甯�
         iOrFramerouterGo(-1);
-      } else {
-        // 淇濆瓨
       }
     };
 
@@ -232,7 +307,8 @@ export default {
     return {
       ...toRefs(data),
       onSave,
-      onBack
+      onBack,
+      editInfoRef
     };
   }
 };
diff --git a/WebSite/src/views/policy-system-library/system-management.vue b/WebSite/src/views/policy-system-library/system-management.vue
index ebb698a..0455066 100644
--- a/WebSite/src/views/policy-system-library/system-management.vue
+++ b/WebSite/src/views/policy-system-library/system-management.vue
@@ -124,10 +124,20 @@
               </el-button>
             </div>
             <div>
-              <el-button type="info" plain icon="Download">
+              <el-button
+                type="info"
+                plain
+                icon="Download"
+                @click="onDownloadFiles()"
+              >
                 涓嬭浇
               </el-button>
-              <el-button type="primary" plain icon="Star">
+              <el-button
+                type="primary"
+                plain
+                icon="Star"
+                @click="onAddAttention()"
+              >
                 鍔犲叧娉�
               </el-button>
             </div>
@@ -221,6 +231,7 @@
                     缂栬緫
                   </el-button>
                   <el-popconfirm
+                    v-if="row.publishStatus !== EnumPublishStatus.Type2"
                     :title="`鏄惁${getPublishBtnText(row)}?`"
                     @confirm="setPublishStatus(row)"
                   >
@@ -231,6 +242,7 @@
                     </template>
                   </el-popconfirm>
                   <el-button
+                    v-else
                     type="danger"
                     plain
                     icon="CircleClose"
@@ -238,10 +250,15 @@
                   >
                     浣滃簾
                   </el-button>
-                  <el-button type="info" plain icon="Download">
+                  <el-button
+                    type="info"
+                    plain
+                    icon="Download"
+                    @click="onDownloadFiles(row)"
+                  >
                     涓嬭浇
                   </el-button>
-                  <el-button plain icon="Clock">
+                  <el-button plain icon="Clock" @click="onShowHistory(row)">
                     鎿嶄綔璁板綍
                   </el-button>
                 </div>
@@ -257,19 +274,33 @@
         </el-card>
       </div>
     </div>
+    <!-- 鎿嶄綔璁板綍寮规 -->
+    <el-dialog v-model="historydialogVisible" title="鎿嶄綔璁板綍" width="600px">
+      <el-timeline>
+        <el-timeline-item v-for="(history, index) in historyList" :key="index">
+          <div class="history-item">
+            <div class="history-createDate">{{ history.createDate }}</div>
+            <div class="history-operatorName">{{ history.operatorName }}</div>
+            <div class="history-content" v-html="history.content"></div>
+          </div>
+        </el-timeline-item>
+      </el-timeline>
+    </el-dialog>
   </div>
 </template>
 
 <script>
 import { computed, onMounted, reactive, toRefs } from 'vue';
 import { iOrFrameRouterPush } from '@/router';
-// import { ElMessage, ElMessageBox } from 'element-plus';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import { EnumPublishStatus, EnumAuditStatus } from '@/utils/Enum';
 import Classify from '@/api/Classify';
 import Institution from '@/api/Institution';
-import { EnumPublishStatus, EnumAuditStatus } from '@/utils/Enum';
+import AttachFile from '@/api/AttachFile';
+import Attention from '@/api/Attention';
 import moment from 'moment';
+import Common from '@/utils/Common';
 export default {
-  name: '鍒跺害搴撶鐞�',
   setup() {
     const data = reactive({
       defaultProps: {
@@ -296,7 +327,9 @@ export default {
         total: 0,
         data: []
       },
-      multipleSelection: []
+      multipleSelection: [],
+      historydialogVisible: false,
+      historyList: []
     });
 
     const publishDate = computed({
@@ -368,16 +401,71 @@ export default {
     };
 
     const setPublishStatus = async row => {
-      const req = { id: row.id };
+      const req = { id: row.id, cancelReason: '' };
       let setPublishStatusReq = Institution.publishInstitution;
       if (row.publishStatus === EnumPublishStatus.Type2) {
+        const remarksRes = await ElMessageBox.prompt('璇疯緭鍏ヤ綔搴熺悊鐢�', '浣滃簾', {
+          confirmButtonText: '纭畾',
+          cancelButtonText: '鍙栨秷',
+          inputPattern: /^[\s\S]*.*[^\s][\s\S]*$/,
+          inputErrorMessage: '浣滃簾鐞嗙敱涓嶈兘涓虹┖'
+        }).catch(t => t);
+        if (remarksRes.action !== 'confirm') {
+          return;
+        }
+        req.cancelReason = remarksRes.value;
         setPublishStatusReq = Institution.cancelInstitution;
       }
-      const res = await setPublishStatusReq(req);
-      console.log(res);
+      await setPublishStatusReq(req);
+      ElMessage.success('鎿嶄綔鎴愬姛');
       await getList();
     };
 
+    const onDownloadFiles = async row => {
+      const req = { institutionIdList: [] };
+      if (row) {
+        req.institutionIdList.push(row.id);
+      } else {
+        req.institutionIdList = [...data.multipleSelection.map(t => t.id)];
+      }
+      if (req.institutionIdList.length === 0) {
+        ElMessage.warning('璇峰嬀閫夊埗搴�');
+        return;
+      }
+      const res = await AttachFile.downloadFile(req);
+      if (res) {
+        const resData = await Common.getJsonOrDownloadFile(res);
+        if (resData.code && resData.code !== '00000') {
+          ElMessage({
+            type: 'warning',
+            message: resData.description
+          });
+        }
+      }
+    };
+
+    const onAddAttention = async () => {
+      const req = {
+        institutionIdList: [...data.multipleSelection.map(t => t.id)]
+      };
+      if (req.institutionIdList.length === 0) {
+        ElMessage.warning('璇峰嬀閫夊埗搴�');
+        return;
+      }
+      await Attention.addAttention(req);
+      ElMessage.success('鎿嶄綔鎴愬姛');
+    };
+
+    const onShowHistory = async row => {
+      data.historyList = [];
+      const res = await Institution.getInstitutionLogList({ id: row.id });
+      data.historyList = res.data.map(t => {
+        t.createDate = moment(t.createDate).format('YYYY骞碝M鏈圖D鏃� HH:mm:ss');
+        return t;
+      });
+      data.historydialogVisible = true;
+    };
+
     return {
       ...toRefs(data),
       publishDate,
@@ -390,7 +478,10 @@ export default {
       EnumAuditStatus,
       formartDate,
       getPublishBtnText,
-      setPublishStatus
+      setPublishStatus,
+      onDownloadFiles,
+      onAddAttention,
+      onShowHistory
     };
   }
 };
@@ -426,5 +517,15 @@ export default {
       }
     }
   }
+  .history-item {
+    display: flex;
+    .history-createDate {
+      color: rgb(87, 87, 87);
+    }
+    .history-operatorName {
+      color: #2558ab;
+      margin: 0 10px;
+    }
+  }
 }
 </style>
-- 
GitLab


From c72467ce2d619a9075949c81808761397f04c918 Mon Sep 17 00:00:00 2001
From: qun <gongqun@develop.com>
Date: Mon, 4 Jul 2022 14:16:04 +0800
Subject: [PATCH 2/2] =?UTF-8?q?=E5=88=B6=E5=BA=A6=E6=9F=A5=E8=AF=A2?=
 =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E3=80=81=E6=90=9C=E7=B4=A2=E9=A1=B5=E9=9D=A2?=
 =?UTF-8?q?=E3=80=81=E6=9F=A5=E8=AF=A2=E6=98=8E=E7=BB=86=E9=A1=B5=E9=9D=A2?=
 =?UTF-8?q?=E7=BB=91=E5=AE=9A=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 WebSite/src/App.vue                           |  10 +-
 WebSite/src/api/Institution.js                |   8 +
 WebSite/src/components/Editors/index.vue      |  22 +-
 WebSite/src/core/base/request.js              |  13 +-
 .../components/AppMain/components/Normal.vue  |   3 +-
 WebSite/src/main.js                           |  40 +-
 WebSite/src/utils/Enum.js                     |  43 +-
 .../homepage/component/search-detail.vue      | 173 ++++----
 .../components/FileItems.vue                  |  13 +-
 .../components/FileRelation.vue               |  15 +-
 .../policy-system-library/policy-edit.vue     |  22 +-
 .../policy-system-library/policy-info.vue     | 152 ++++---
 .../policy-system-library/policy-search.vue   | 382 +++++++++++-------
 .../system-management.vue                     |   9 +-
 14 files changed, 585 insertions(+), 320 deletions(-)

diff --git a/WebSite/src/App.vue b/WebSite/src/App.vue
index acb6df3..874dd24 100644
--- a/WebSite/src/App.vue
+++ b/WebSite/src/App.vue
@@ -6,7 +6,7 @@
  * @LastEditTime: 2021-08-18 17:19:17
 -->
 <template>
-  <div id="app-inner">
+  <div id="app-inner" v-loading="appLoading">
     <router-view v-slot="{ Component }">
       <transition name="fade-transform-top" mode="out-in">
         <component :is="Component" />
@@ -16,8 +16,14 @@
 </template>
 
 <script>
+import { computed } from 'vue';
+import { useStore } from 'vuex';
 export default {
   name: 'App',
-  setup() {}
+  setup() {
+    const store = useStore();
+    const appLoading = computed(() => store.state.app.loading);
+    return { appLoading };
+  }
 };
 </script>
diff --git a/WebSite/src/api/Institution.js b/WebSite/src/api/Institution.js
index 40508cb..ef2a308 100644
--- a/WebSite/src/api/Institution.js
+++ b/WebSite/src/api/Institution.js
@@ -53,6 +53,14 @@ class Institution {
   static getInstitutionRelationList(data) {
     return request.post('/institution/getInstitutionRelationList', data);
   }
+  // 鍒跺害瀹℃牳閫氳繃
+  static passInstitutionAudit(data) {
+    return request.post('/institution/passInstitutionAudit', data);
+  }
+  // 鍒跺害瀹℃牳椹冲洖
+  static rejectInstitutionAudit(data) {
+    return request.post('/institution/rejectInstitutionAudit', data);
+  }
 }
 
 export default Institution;
diff --git a/WebSite/src/components/Editors/index.vue b/WebSite/src/components/Editors/index.vue
index 5456da9..71dbb62 100644
--- a/WebSite/src/components/Editors/index.vue
+++ b/WebSite/src/components/Editors/index.vue
@@ -1,5 +1,9 @@
 <template>
-  <div class="editors-container" :class="{ border }" :style="{ height }">
+  <div
+    class="editors-container"
+    :class="{ border }"
+    :style="{ height: maxHeight ? '' : height, 'max-height': maxHeight }"
+  >
     <div class="header-tree" v-if="showHeaderTree">
       <slot name="header-tree-title" />
       <el-tree
@@ -40,7 +44,7 @@
 <script>
 import '@wangeditor/editor/dist/css/style.css'; // 寮曞叆 css
 
-import { computed } from 'vue';
+import { computed, watch } from 'vue';
 import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
 import useConfig from './useConfig';
 import useHeaderTree from './useHeaderTree';
@@ -56,6 +60,10 @@ export default {
       type: String,
       default: '500px'
     },
+    maxHeight: {
+      type: String,
+      default: ''
+    },
     placeholder: {
       type: String,
       default: '璇疯緭鍏ュ唴瀹�'
@@ -97,7 +105,7 @@ export default {
     const handleCreated = editor => {
       editorRef.value = editor; // 璁板綍 editor 瀹炰緥
       refreshHeaders();
-      console.log('handleCreated:', props.modelValue);
+      // console.log('handleCreated:', props.modelValue);
       if (props.modelValue) {
         setHtml(valueHtml.value);
       }
@@ -108,6 +116,9 @@ export default {
       // const toolbar = DomEditor.getToolbar(editor);// 鎷垮埌toolbar
       // console.log(toolbar);
     };
+    watch(valueHtml, value => {
+      setHtml(value);
+    });
 
     return {
       editorRef,
@@ -167,13 +178,14 @@ export default {
     flex: 1;
     display: flex;
     flex-direction: column;
-    // height: 100%;
+    height: 100%;
     .editor {
       flex-grow: 1;
-      height: calc(100% - 45px) !important;
+      height: calc(100% - 500px) !important;
     }
     ::v-deep(.w-e-text-container) {
       height: 100%;
+      // height: calc(100% + 10px);
       word-break: break-all;
     }
     ::v-deep(.w-e-scroll) {
diff --git a/WebSite/src/core/base/request.js b/WebSite/src/core/base/request.js
index 07fb2c8..6d7c94b 100644
--- a/WebSite/src/core/base/request.js
+++ b/WebSite/src/core/base/request.js
@@ -8,6 +8,12 @@
 import axios from 'axios';
 import store from '@/store';
 import { ElNotification } from 'element-plus';
+import { debounce } from '@/utils';
+let currentRequestCount = 0;
+const closeLoading = debounce(() => {
+  currentRequestCount--;
+  currentRequestCount <= 0 && store.dispatch('app/endLoading');
+}, 100);
 
 const axiosInstance = axios.create({
   baseURL: process.env.VUE_APP_BASE_API,
@@ -16,18 +22,19 @@ const axiosInstance = axios.create({
 
 axiosInstance.interceptors.request.use(
   config => {
+    currentRequestCount++;
     store.dispatch('app/startLoading');
     return config;
   },
   error => {
-    store.dispatch('app/endLoading');
+    closeLoading();
     return Promise.reject(error);
   }
 );
 
 axiosInstance.interceptors.response.use(
   response => {
-    store.dispatch('app/endLoading');
+    closeLoading();
     // blob绫诲瀷闇€鍦ㄨ皟鐢╝pi鍙傛暟浣嶇疆浼犲叆鍙傛暟 responseType: 'blob'
     if (response.config.responseType === 'blob') {
       // 杩斿洖鏂囦欢娴佸唴瀹�
@@ -49,7 +56,7 @@ axiosInstance.interceptors.response.use(
     return data;
   },
   error => {
-    store.dispatch('app/endLoading');
+    closeLoading();
     // console.log(error.response);
     ElNotification({
       message: error.response.statusText,
diff --git a/WebSite/src/layout/components/AppMain/components/Normal.vue b/WebSite/src/layout/components/AppMain/components/Normal.vue
index c39f5c0..1af968c 100644
--- a/WebSite/src/layout/components/AppMain/components/Normal.vue
+++ b/WebSite/src/layout/components/AppMain/components/Normal.vue
@@ -6,7 +6,8 @@
  * @LastEditTime: 2021-10-16 11:23:37
 -->
 <template>
-  <router-view v-slot="{ Component }" v-loading="appLoading">
+  <router-view v-slot="{ Component }">
+    <!-- v-loading="appLoading" -->
     <transition name="fade-transform-s" mode="out-in">
       <keep-alive :exclude="destoryRoute">
         <component :is="Component" />
diff --git a/WebSite/src/main.js b/WebSite/src/main.js
index 4235b57..e32a8e4 100644
--- a/WebSite/src/main.js
+++ b/WebSite/src/main.js
@@ -30,8 +30,8 @@ import * as ElementPlusIconsVue from '@element-plus/icons-vue';
 /**others */
 import VueParticles from 'vue-particles';
 /**micro app */
-import { registerMicroApps } from 'qiankun';
-import { microAppOptions, generateMicroAppOptions } from '@/router/micro-app';
+// import { registerMicroApps } from 'qiankun';
+// import { microAppOptions, generateMicroAppOptions } from '@/router/micro-app';
 /**global component */
 import components from '@/components';
 
@@ -69,23 +69,23 @@ function init(props = {}) {
 }
 
 // 鐙珛杩愯
-if (!window.__POWERED_BY_QIANKUN__) {
-  if (microAppOptions && microAppOptions.length > 0) {
-    registerMicroApps(generateMicroAppOptions(microAppOptions));
-  }
+// if (!window.__POWERED_BY_QIANKUN__) {
+//   if (microAppOptions && microAppOptions.length > 0) {
+//     registerMicroApps(generateMicroAppOptions(microAppOptions));
+//   }
 
-  init();
-}
+init();
+// }
 // 浠ュ井搴旂敤鏂瑰紡杩愯鏃剁殑閽╁瓙鍑芥暟
-export async function bootstrap() {
-  console.log(`[${defaultConfig.applicationName}] micro app bootstraped`);
-}
-export async function mount(props) {
-  console.log(`[${defaultConfig.applicationName}] micro app mount`);
-  init(props);
-}
-export async function unmount() {
-  console.log(`[${defaultConfig.applicationName}] micro app unmount`);
-  app.unmount();
-  app = null;
-}
+// export async function bootstrap() {
+//   console.log(`[${defaultConfig.applicationName}] micro app bootstraped`);
+// }
+// export async function mount(props) {
+//   console.log(`[${defaultConfig.applicationName}] micro app mount`);
+//   init(props);
+// }
+// export async function unmount() {
+//   console.log(`[${defaultConfig.applicationName}] micro app unmount`);
+//   app.unmount();
+//   app = null;
+// }
diff --git a/WebSite/src/utils/Enum.js b/WebSite/src/utils/Enum.js
index 7c4d578..7458a11 100644
--- a/WebSite/src/utils/Enum.js
+++ b/WebSite/src/utils/Enum.js
@@ -22,4 +22,45 @@ const EnumAuditStatus = {
     3: { name: '瀹℃牳椹冲洖', value: 3, type: 'danger' }
   }
 };
-export { EnumPublishStatus, EnumAuditStatus };
+// 鎼滅储鏃ユ湡绫诲瀷
+const EnumDateType = {
+  Type1: 0, //鍏ㄩ儴
+  Type2: 1, //涓€澶╁唴
+  Type3: 2, //涓€鍛ㄥ唴
+  Type4: 3, //涓€鏈堝唴
+  properties: {
+    0: { name: '鍏ㄩ儴', value: 0 },
+    1: { name: '涓€澶╁唴', value: 1 },
+    2: { name: '涓€鍛ㄥ唴', value: 2 },
+    3: { name: '涓€鏈堝唴', value: 3 }
+  }
+};
+// 鎼滅储绫诲瀷
+const EnumLibraryType = {
+  Type1: 0, //鍏ㄩ儴
+  Type2: 1, //鍒跺害搴�
+  Type3: 2, //鐭ヨ瘑搴�
+  properties: {
+    0: { name: '鍏ㄩ儴', value: 0 },
+    1: { name: '鍒跺害搴�', value: 1 },
+    2: { name: '鐭ヨ瘑搴�', value: 2 }
+  }
+};
+// 鎼滅储鍐呭绫诲瀷
+const EnumSearchType = {
+  Type1: 0, //鍏ㄩ儴
+  Type2: 1, //鏍囬
+  Type3: 2, //姝f枃
+  properties: {
+    0: { name: '鎵€鏈夌粨鏋�', value: 0 },
+    1: { name: '鏍囬', value: 1 },
+    2: { name: '姝f枃', value: 2 }
+  }
+};
+export {
+  EnumPublishStatus,
+  EnumAuditStatus,
+  EnumDateType,
+  EnumLibraryType,
+  EnumSearchType
+};
diff --git a/WebSite/src/views/homepage/component/search-detail.vue b/WebSite/src/views/homepage/component/search-detail.vue
index 539e9cd..ac1bb67 100644
--- a/WebSite/src/views/homepage/component/search-detail.vue
+++ b/WebSite/src/views/homepage/component/search-detail.vue
@@ -5,10 +5,17 @@
         <el-card class="box-card">
           <template #header>
             <div class="card-header">
-              <el-radio-group v-model="searchInfo.type" @change="onSearch()">
-                <el-radio label="鍏ㄩ儴">鍏ㄩ儴</el-radio>
-                <el-radio label="鍒跺害搴�">鍒跺害搴�</el-radio>
-                <el-radio label="鐭ヨ瘑搴�">鐭ヨ瘑搴�</el-radio>
+              <el-radio-group
+                v-model="searchInfo.libraryType"
+                @change="onSearch()"
+              >
+                <el-radio
+                  v-for="(item, index) in EnumLibraryType.properties"
+                  :key="index"
+                  :label="item.value"
+                >
+                  {{ item.name }}
+                </el-radio>
               </el-radio-group>
             </div>
           </template>
@@ -20,18 +27,21 @@
               class="list-item"
               v-for="(item, index) in listData.data"
               :key="index"
+              @click="toDetail(item)"
             >
               <div class="item-title" v-html="item.title"></div>
               <div class="item-content" v-html="item.content"></div>
               <div class="item-remark">
-                {{ item.date }}&nbsp;&nbsp;鏉ユ簮锛氭斂搴滃埗搴﹀簱
+                {{ formartDate(item.publishDate) }}&nbsp;&nbsp;鏉ユ簮锛歿{
+                  EnumLibraryType.properties[item.libraryType].name
+                }}
               </div>
             </div>
-            <MinPagination
-              v-model="searchInfo.pageIndex"
-              :pageCount="listData.pageCount"
-              @onChange="getList"
-              showPageCount
+            <Pagination
+              class="mt-20"
+              v-model="searchInfo"
+              :dataCount="listData.total"
+              @handleChange="getList"
             />
           </div>
         </el-card>
@@ -41,7 +51,7 @@
           <template #header>
             <div class="card-header">
               <el-input
-                v-model="searchInfo.keywords"
+                v-model="searchInfo.keyword"
                 placeholder="璇疯緭鍏ユ悳绱㈠叧閿瓧"
                 clearable
               />
@@ -60,60 +70,36 @@
               鐑棬鎼滅储锛�
               <el-tag
                 class="search-tag"
-                v-for="(keywords, index) in topSearch"
+                v-for="(keyword, index) in topSearch"
                 :key="index"
                 type="info"
-                @click="onSearch(keywords)"
+                @click="onSearch(keyword)"
               >
-                {{ keywords }}
+                {{ keyword }}
               </el-tag>
             </div>
             <div class="search-box search-content">
               <div class="search-title">鎸夊唴瀹圭瓫閫夛細</div>
               <el-tag
+                v-for="(item, index) in EnumSearchType.properties"
+                :key="index"
                 class="search-tag"
-                type="info"
-                @click="onSearch('', '鎵€鏈夌粨鏋�')"
-              >
-                鎵€鏈夌粨鏋�
-              </el-tag>
-              <el-tag
-                class="search-tag"
-                type="info"
-                @click="onSearch('', '鏍囬')"
-              >
-                鏍囬
-              </el-tag>
-              <el-tag
-                class="search-tag"
-                type="info"
-                @click="onSearch('', '姝f枃')"
+                :type="item.value === searchInfo.searchType ? '' : 'info'"
+                @click="onSearch('', item.value)"
               >
-                姝f枃
+                {{ item.name }}
               </el-tag>
             </div>
             <div class="search-box search-content">
               <div class="search-title">鎸夋椂闂寸瓫閫夛細</div>
               <el-tag
+                v-for="(item, index) in EnumDateType.properties"
+                :key="index"
                 class="search-tag"
-                type="info"
-                @click="onSearch('', null, '涓€澶╁唴')"
-              >
-                涓€澶╁唴
-              </el-tag>
-              <el-tag
-                class="search-tag"
-                type="info"
-                @click="onSearch('', null, '涓€鍛ㄥ唴')"
-              >
-                涓€鍛ㄥ唴
-              </el-tag>
-              <el-tag
-                class="search-tag"
-                type="info"
-                @click="onSearch('', null, '涓€鏈堝唴')"
+                :type="item.value === searchInfo.dateType ? '' : 'info'"
+                @click="onSearch('', null, item.value)"
               >
-                涓€鏈堝唴
+                {{ item.name }}
               </el-tag>
             </div>
           </div>
@@ -127,14 +113,22 @@
 import { onMounted, reactive, toRefs } from 'vue';
 import { useRoute } from 'vue-router';
 // import { ElMessage, ElMessageBox } from 'element-plus';
+import Institution from '@/api/Institution';
+import { EnumDateType, EnumLibraryType, EnumSearchType } from '@/utils/Enum';
+import moment from 'moment';
+import { isEmpty } from '@/utils';
+import { iOrFrameRouterPush } from '@/router';
 export default {
   setup() {
     const route = useRoute();
     const data = reactive({
       searchInfo: {
-        type: '鍏ㄩ儴',
-        keywords: route.query.keywords,
-        pageIndex: 1
+        keyword: route.query.keyword,
+        libraryType: 0,
+        searchType: 0,
+        dateType: 0,
+        pageIndex: 1,
+        pageSize: 10
       },
       topSearch: [],
       listData: {
@@ -144,57 +138,69 @@ export default {
       }
     });
 
-    const getList = () => {
-      data.listData.pageCount = 5;
-      data.listData.total = 121;
-      data.listData.data = [];
-      // todo: get list data
-      for (let index = 0; index < 5; index++) {
-        data.listData.data.push({
-          title: '娌储搴撱€�2020銆�54鍙� 鍏充簬缂栧埗鏈競2020骞村害璐㈠姟閮ㄩ棬鍐崇畻鐨勫彿鐭�',
-          content:
-            '鍒跺害鍐呭鍒跺害瑙勫垝鍐呭鍒跺害鍐呭鍒惰储鍔$殑瀹瑰埗搴﹀唴瀹瑰埗搴﹁储鍔″唴瑙勫垝搴﹀唴瀹瑰喅绠楀埗搴﹀唴瀹瑰埗搴﹀唴瀹瑰埗鍙峰害鍐呭鍒跺害鐨勫唴瀹瑰埗搴﹀唴瀹瑰埗搴﹀唴瀹瑰埗搴﹀唴瀹瑰埗搴﹀唴瀹瑰埗搴﹀唴瀹瑰埗搴﹀唴瀹瑰埗搴﹀唴瀹�',
-          date: '2020-01-01'
-        });
-      }
-      if (data.searchInfo.keywords) {
+    const getList = async () => {
+      const res = await Institution.getInstitutionSearchPage(data.searchInfo);
+      data.listData = res;
+      if (data.searchInfo.keyword) {
         data.listData.data = data.listData.data.map(item => {
           item.title = item.title.replaceAll(
-            data.searchInfo.keywords,
-            `<span class="search-keywords">${data.searchInfo.keywords}</span>`
+            data.searchInfo.keyword,
+            `<span class="search-keyword">${data.searchInfo.keyword}</span>`
           );
           item.content = item.content.replaceAll(
-            data.searchInfo.keywords,
-            `<span class="search-keywords">${data.searchInfo.keywords}</span>`
+            data.searchInfo.keyword,
+            `<span class="search-keyword">${data.searchInfo.keyword}</span>`
           );
           return item;
         });
       }
     };
 
-    const onSearch = (keywords, content, time) => {
-      if (keywords) {
-        data.searchInfo.keywords = keywords;
+    const onSearch = async (keyword, searchType, dateType) => {
+      if (!isEmpty(keyword)) {
+        data.searchInfo.keyword = keyword;
       }
-      if (content) {
-        data.searchInfo.content = content;
+      if (!isEmpty(searchType)) {
+        data.searchInfo.searchType = searchType;
       }
-      if (time) {
-        data.searchInfo.time = time;
+      if (!isEmpty(dateType)) {
+        data.searchInfo.dateType = dateType;
       }
       data.searchInfo.pageIndex = 1;
-      getList();
+      await getList();
     };
 
-    onMounted(() => {
-      data.topSearch = ['鍐崇畻', '璐㈠姟', '瑙勫垝', '鍙�', '鐨�'];
-      getList();
+    onMounted(async () => {
+      const res = await Institution.getSearchLogList();
+      data.topSearch = res.data;
+      await getList();
     });
 
+    const formartDate = value => {
+      return moment(value).format('YYYY骞碝M鏈圖D鏃�');
+    };
+
+    const toDetail = item => {
+      iOrFrameRouterPush({
+        name:
+          item.libraryType === EnumLibraryType.Type2 ? '鍒跺害璇︽儏' : '鐭ヨ瘑璇︽儏',
+        path:
+          item.libraryType === EnumLibraryType.Type2
+            ? '/policy-info'
+            : '/knowledge-detail',
+        query: { id: item.id }
+      });
+    };
+
     return {
       ...toRefs(data),
       onSearch,
-      getList
+      getList,
+      EnumLibraryType,
+      EnumSearchType,
+      EnumDateType,
+      formartDate,
+      toDetail
     };
   }
 };
@@ -233,13 +239,14 @@ export default {
         color: rgb(114, 114, 114);
         margin-top: 10px;
       }
-      ::v-deep(.search-keywords) {
+      ::v-deep(.search-keyword) {
         color: rgba(255, 37, 37, 1);
       }
     }
     .search-box {
       .search-tag {
-        margin-right: 20px;
+        margin-right: 10px;
+        margin-bottom: 10px;
         font-size: 14px;
         cursor: pointer;
       }
diff --git a/WebSite/src/views/policy-system-library/components/FileItems.vue b/WebSite/src/views/policy-system-library/components/FileItems.vue
index 42f4797..d4e3e44 100644
--- a/WebSite/src/views/policy-system-library/components/FileItems.vue
+++ b/WebSite/src/views/policy-system-library/components/FileItems.vue
@@ -8,7 +8,7 @@
       @close="handleClose(file)"
       class="file-item"
     >
-      {{ file.name }}
+      {{ file.fileName }}
     </el-tag>
     <br v-if="fileList.length > 0" />
     <el-button
@@ -84,7 +84,7 @@ export default {
       }
       const res = await AttachFile.uploadFile(req);
       fileList.value.push(
-        ...files.map(file => ({ id: file.uid, name: file.name }))
+        ...files.map(file => ({ id: file.uid, fileName: file.name }))
       );
       fileids.value.push(...res.data);
       data.uploadFileDialog = false;
@@ -101,9 +101,18 @@ export default {
 </script>
 <style lang="scss" scoped>
 .file-container {
+  overflow: hidden;
   .file-item {
     margin-right: 10px;
     margin-bottom: 5px;
+    width: 100%;
+    height: auto;
+    padding: 5px;
+    ::v-deep(.el-tag__content) {
+      width: 100%;
+      white-space: break-spaces;
+      line-height: 1.2;
+    }
   }
 }
 </style>
diff --git a/WebSite/src/views/policy-system-library/components/FileRelation.vue b/WebSite/src/views/policy-system-library/components/FileRelation.vue
index 22cff63..69ee2c0 100644
--- a/WebSite/src/views/policy-system-library/components/FileRelation.vue
+++ b/WebSite/src/views/policy-system-library/components/FileRelation.vue
@@ -8,7 +8,7 @@
       @close="handleClose(file)"
       class="file-item"
     >
-      {{ file.name }}
+      {{ file.title }}
     </el-tag>
     <el-button type="primary" @click="onShowRelation" plain icon="Switch">
       閫夋嫨宸叉湁鍒跺害
@@ -37,7 +37,7 @@
         }"
       >
         <template #default="{ option }">
-          <span>{{ option.name }}</span>
+          <span>{{ option.title }}</span>
         </template>
         <!-- <template #left-footer>
           <el-button class="transfer-footer" size="small">Operation</el-button>
@@ -103,7 +103,7 @@ export default {
       data.selectFileList = [
         ...res.data[0].noRelationInstitutionList,
         ...res.data[0].relationInstitutionList
-      ].map(t => ({ id: t.id, name: t.title }));
+      ];
       const ids = data.selectFileList.map(t => t.id);
       for (let i = 0; i < fileList.value.length; i++) {
         const file = fileList.value[i];
@@ -153,9 +153,18 @@ export default {
 </script>
 <style lang="scss" scoped>
 .file-container {
+  overflow: hidden;
   .file-item {
     margin-right: 10px;
     margin-bottom: 5px;
+    width: 100%;
+    height: auto;
+    padding: 5px;
+    ::v-deep(.el-tag__content) {
+      width: 100%;
+      white-space: break-spaces;
+      line-height: 1.2;
+    }
   }
 }
 </style>
diff --git a/WebSite/src/views/policy-system-library/policy-edit.vue b/WebSite/src/views/policy-system-library/policy-edit.vue
index b4539cd..6d1b149 100644
--- a/WebSite/src/views/policy-system-library/policy-edit.vue
+++ b/WebSite/src/views/policy-system-library/policy-edit.vue
@@ -150,10 +150,15 @@
               </el-form-item>
             </el-col>
             <el-col :span="24">
-              <el-form-item label="鏂囦欢鍐呭" label-position="top">
+              <el-form-item label="鏂囦欢鍐呭">
                 <Editors v-model="editInfo.content" showHeaderTree border />
               </el-form-item>
             </el-col>
+            <el-col :span="24">
+              <el-form-item label="澶囨敞">
+                <el-input v-model="editInfo.remark" placeholder="璇疯緭鍏ュ娉�" />
+              </el-form-item>
+            </el-col>
             <el-col :span="24" class="btn-box">
               <el-button
                 type="primary"
@@ -186,7 +191,7 @@
 import { onMounted, reactive, toRefs, ref } from 'vue';
 import { useRoute } from 'vue-router';
 
-// import { ElMessage, ElMessageBox } from 'element-plus';
+import { ElMessage } from 'element-plus';
 import FileItems from './components/FileItems';
 import FileRelation from './components/FileRelation';
 import { iOrFramerouterGo } from '@/router';
@@ -267,10 +272,20 @@ export default {
         data.editInfo.creatorName = userRes.data[0].name;
         return;
       }
+      // 淇敼銆佸鏍稿埗搴�
       const res = await Institution.getInstitutionById({
         id: data.editInfo.id
       });
       data.editInfo = res.data[0];
+      data.editInfo.institutionFileIdList = data.editInfo.institutionFileList.map(
+        t => t.id
+      );
+      data.editInfo.attachFileIdList = data.editInfo.attachFileList.map(
+        t => t.id
+      );
+      data.editInfo.relationInstitutionIdList = data.editInfo.relationInstitutionList.map(
+        t => t.id
+      );
     };
 
     onMounted(async () => {
@@ -293,7 +308,8 @@ export default {
         return;
       }
       const res = await Institution.saveInstitution(data.editInfo);
-      console.log(res);
+      data.editInfo.id = res.data[0];
+      ElMessage.success('鎿嶄綔鎴愬姛');
       if (isPublish) {
         // 淇濆瓨骞跺彂甯�
         iOrFramerouterGo(-1);
diff --git a/WebSite/src/views/policy-system-library/policy-info.vue b/WebSite/src/views/policy-system-library/policy-info.vue
index ad78d92..b719f67 100644
--- a/WebSite/src/views/policy-system-library/policy-info.vue
+++ b/WebSite/src/views/policy-system-library/policy-info.vue
@@ -1,20 +1,15 @@
 <template>
   <div class="policy-container">
-    <Crumbs
-      :routeList="['鏀跨瓥鍒跺害搴�', '鍒跺害璇︽儏椤�']"
-      showroute
-      back-to-my-home
-    />
     <div class="policy-content">
       <div class="edit-card">
         <div class="content-container">
           <Editors
             class="editors"
-            v-model="editInfo.content"
+            v-model="content"
             showHeaderTree
             placeholder=""
             disabled
-            height="calc(100vh - 84px)"
+            max-height="calc(100vh - 84px)"
           >
             <template #header-tree-title>
               <div class="header-tree-title">
@@ -23,19 +18,17 @@
             </template>
             <div class="title-box">
               <div class="article-title">
-                娴嬭瘯鏍囬{{ id }}
+                {{ title }}
                 <el-icon
                   @click="onStar"
                   class="star-icon"
-                  :class="{ star: editInfo.star }"
+                  :class="{ star: star }"
                 >
-                  <StarFilled v-if="editInfo.star" />
+                  <StarFilled v-if="star" />
                   <Star v-else />
                 </el-icon>
               </div>
-              <div class="article-time">
-                棰佸竷鏃ユ湡锛�2022骞�6鏈�22鏃� 10鐐�54鍒�12绉�
-              </div>
+              <div class="article-time">棰佸竷鏃ユ湡锛歿{ publishDate }}</div>
             </div>
           </Editors>
           <div class="files-container">
@@ -45,12 +38,12 @@
               </div>
               <div
                 class="policy-item"
-                v-for="(item, index) in editInfo.policyList"
+                v-for="(item, index) in policyList"
                 :key="index"
               >
                 <i class="fas fa-link" />
                 <el-link type="primary" @click="toPolicyInfo(item.id)">
-                  {{ item.name }}
+                  {{ item.title }}
                 </el-link>
               </div>
             </div>
@@ -60,24 +53,26 @@
               </div>
               <div
                 class="policy-item"
-                v-for="(item, index) in editInfo.fileList"
+                v-for="(item, index) in fileList"
                 :key="index"
               >
                 <i :class="getFileIcon(item)" />
-                <el-link type="primary" @click="onDownload(item.id)">
-                  {{ item.name }}
+                <el-link type="primary" @click="onDownload(item)">
+                  {{ item.fileName }}
                 </el-link>
               </div>
             </div>
           </div>
         </div>
         <div class="btn-box">
-          <!-- <el-button type="primary" plain>
-            椹冲洖
-          </el-button>
-          <el-button type="primary" plain>
-            閫氳繃
-          </el-button> -->
+          <template v-if="isCurAudit">
+            <el-button type="danger" plain @click="onReject">
+              椹冲洖
+            </el-button>
+            <el-button type="success" plain @click="onPass">
+              閫氳繃
+            </el-button>
+          </template>
           <el-button type="info" plain icon="Back" @click="onBack">
             杩斿洖
           </el-button>
@@ -88,47 +83,63 @@
 </template>
 
 <script>
-import { onMounted, reactive, toRefs } from 'vue';
+import { onMounted, reactive, toRefs, watch } from 'vue';
 import { useRoute } from 'vue-router';
 import { iOrFrameRouterPush, iOrFramerouterGo } from '@/router';
+import Institution from '@/api/Institution';
+import AttachFile from '@/api/AttachFile';
+import Attention from '@/api/Attention';
+import moment from 'moment';
+import Common from '@/utils/Common';
+import { ElMessage, ElMessageBox } from 'element-plus';
 
-// import { ElMessage, ElMessageBox } from 'element-plus';
 export default {
   name: 'PolicyEdit',
   setup() {
     const route = useRoute();
     const data = reactive({
-      id: route.query.id,
-      editInfo: {
-        star: false,
-        content: '',
-        policyList: [],
-        fileList: []
-      }
+      id: '',
+      star: false,
+      title: '',
+      publishDate: '',
+      content: '',
+      policyList: [],
+      fileList: [],
+      isCurAudit: false
     });
     const getData = async () => {
-      data.editInfo.content = `<h2>娴嬭瘯鏍囬</h2><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p><h3>娴嬭瘯鏍囬</h3><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p><p style="text-indent: 2em;"><br></p><p style="text-indent: 2em;"><br></p><h2>娴嬭瘯鏍囬</h2><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p><h3>娴嬭瘯鏍囬</h3><p style="text-indent: 2em;">娴嬭瘯姝f枃娴嬭瘯姝f祴璇曟鏂囨祴璇曟鏂�1</p>`;
-      for (let index = 0; index < 5; index++) {
-        data.editInfo.policyList.push({ id: index, name: 'xxx鍒跺害' });
-      }
-      data.editInfo.fileList = [
-        { id: 1, name: 'xxx闄勪欢.doc' },
-        { id: 1, name: 'xxx闄勪欢.pptx' },
-        { id: 1, name: 'xxx闄勪欢.xlsx' },
-        { id: 1, name: 'xxx闄勪欢.pdf' }
-      ];
+      const res = await Institution.getInstitutionById({
+        id: route.query.id
+      });
+      const info = res.data[0];
+      data.id = info.id;
+      data.star = info.isAttention;
+      data.title = info.title;
+      data.content = info.content;
+      data.publishDate = moment(info.publishDate).format('YYYY骞碝M鏈圖D鏃�');
+      data.fileList = [...info.attachFileList, ...info.institutionFileList];
+      data.policyList = info.relationInstitutionList;
+      data.isCurAudit = info.isCurAudit;
     };
 
     onMounted(async () => {
       await getData();
     });
 
+    watch(
+      () => route.query.id,
+      () => {
+        if (route.query.id) {
+          getData();
+        }
+      }
+    );
+
     const onBack = () => {
       iOrFramerouterGo(-1);
     };
 
     const toPolicyInfo = id => {
-      // router.push({ path: '/policy-info', query: { id } });
       iOrFrameRouterPush({
         id,
         name: '鍒跺害璇︽儏',
@@ -138,8 +149,8 @@ export default {
     };
 
     const getFileIcon = file => {
-      const startIndex = file.name.lastIndexOf('.');
-      const surfixName = file.name.substring(startIndex + 1);
+      const startIndex = file.fileName.lastIndexOf('.');
+      const surfixName = file.fileName.substring(startIndex + 1);
       switch (surfixName) {
         case 'xls':
         case 'xlsx':
@@ -157,12 +168,47 @@ export default {
       }
     };
 
-    const onDownload = file => {
-      console.log(file);
+    const onDownload = async file => {
+      const res = await AttachFile.downloadFile({ id: file.id });
+      if (res) {
+        const resData = await Common.getJsonOrDownloadFile(res);
+        if (resData.code && resData.code !== '00000') {
+          ElMessage({
+            type: 'warning',
+            message: resData.description
+          });
+        }
+      }
     };
 
-    const onStar = () => {
-      data.editInfo.star = !data.editInfo.star;
+    const onStar = async () => {
+      const req = { institutionIdList: [data.id] };
+      const starReq = data.star
+        ? Attention.removeAttention
+        : Attention.addAttention;
+      await starReq(req);
+      ElMessage.success('鎿嶄綔鎴愬姛');
+      data.star = !data.star;
+    };
+
+    const onReject = async () => {
+      const remarksRes = await ElMessageBox.prompt('璇疯緭鍏ラ┏鍥炵悊鐢�', '浣滃簾', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        inputPattern: /^[\s\S]*.*[^\s][\s\S]*$/,
+        inputErrorMessage: '浣滃簾鐞嗙敱涓嶈兘涓虹┖'
+      }).catch(t => t);
+      if (remarksRes.action !== 'confirm') {
+        return;
+      }
+      const req = { id: data.id, rejectReason: remarksRes.rejectReason };
+      await Institution.rejectInstitutionAudit(req);
+      ElMessage.success('鎿嶄綔鎴愬姛');
+    };
+    const onPass = async () => {
+      const req = { id: data.id };
+      await Institution.passInstitutionAudit(req);
+      ElMessage.success('鎿嶄綔鎴愬姛');
     };
 
     return {
@@ -171,7 +217,9 @@ export default {
       toPolicyInfo,
       getFileIcon,
       onDownload,
-      onStar
+      onStar,
+      onReject,
+      onPass
     };
   }
 };
@@ -292,7 +340,7 @@ export default {
       max-width: 1200px;
       margin: 0 auto;
       margin-top: 20px;
-      text-align: right;
+      text-align: center;
     }
   }
 }
diff --git a/WebSite/src/views/policy-system-library/policy-search.vue b/WebSite/src/views/policy-system-library/policy-search.vue
index a899a2c..87bd326 100644
--- a/WebSite/src/views/policy-system-library/policy-search.vue
+++ b/WebSite/src/views/policy-system-library/policy-search.vue
@@ -7,106 +7,73 @@
       back-to-my-home
     />
     <div class="app-content">
-      <el-card class="tree-card">
-        <el-input
-          placeholder="杈撳叆鍏抽敭瀛楄繘琛岃繃婊�"
-          v-model="filterText"
-          clearable
-        />
-        <el-divider></el-divider>
-        <el-tree
-          class="filter-tree mt-20"
-          :data="treeData"
-          :props="defaultProps"
-          default-expand-all
-          highlight-current
-          @node-click="handleNodeClick"
-          :expand-on-click-node="false"
-          :filter-node-method="filterNode"
-          ref="tree"
-        >
-          <template #default="{ node }">
-            <span class="custom-tree-node">
-              <span>{{ node.label }}</span>
-              <!-- <span>
-                  <el-button
-                    type="text"
-                    size="mini"
-                    @click.stop="() => handleEdit(node, data)"
-                  >
-                    缂栬緫
-                  </el-button>
-                </span> -->
-            </span>
-          </template>
-        </el-tree>
-      </el-card>
       <div class="right-box">
         <el-card class="search-card">
-          <el-form label-width="70px" label-position="left">
-            <el-row :gutter="30">
-              <el-col :span="7">
+          <el-form label-width="60px" label-position="left">
+            <el-row :gutter="20">
+              <el-col :span="8">
                 <el-form-item label="鍏抽敭瀛�">
                   <el-input
-                    v-model="searchInfo.keywords"
+                    v-model="searchInfo.title"
                     placeholder="璇疯緭鍏ュ悕绉�/鍏抽敭瀛楁ā绯婃煡璇�"
                     clearable
                   />
                 </el-form-item>
               </el-col>
-              <el-col :span="7">
+              <el-col :span="8">
                 <el-form-item label="鏂囧彿">
                   <el-input
-                    v-model="searchInfo.no"
+                    v-model="searchInfo.documentNo"
                     placeholder="璇疯緭鍏ユ枃鍙锋ā绯婃煡璇�"
                     clearable
                   />
                 </el-form-item>
               </el-col>
-              <el-col :span="7">
+              <el-col :span="8">
                 <el-form-item label="鍒嗙被">
                   <el-tree-select
-                    v-model="searchInfo.type1"
+                    v-model="searchInfo.classifyId"
                     :data="treeData"
                     :props="defaultProps"
                     check-strictly
                     clearable
                     style="width:100%"
+                    filterable
                   >
                     <template #default="{ node }">
                       <span class="custom-tree-node">
                         <span>{{ node.label }}</span>
-                        <!-- <span>
-                  <el-button
-                    type="text"
-                    size="mini"
-                    @click.stop="() => handleEdit(node, data)"
-                  >
-                    缂栬緫
-                  </el-button>
-                </span> -->
                       </span>
                     </template>
                   </el-tree-select>
                 </el-form-item>
               </el-col>
             </el-row>
-            <el-row :gutter="30">
-              <el-col :span="7">
+            <el-row :gutter="20">
+              <el-col :span="8">
                 <el-form-item label="棰佸竷鏃ユ湡">
                   <el-date-picker
                     style="width: 100%"
-                    v-model="searchInfo.date"
+                    v-model="publishDate"
                     type="daterange"
                     range-separator="鑷�"
                     start-placeholder="寮€濮嬫棩鏈�"
                     end-placeholder="缁撴潫鏃ユ湡"
+                    format="YYYY-MM-DD"
+                    value-format="YYYY-MM-DD"
+                  />
+                </el-form-item>
+              </el-col>
+              <el-col :span="8">
+                <el-form-item label="鍙戞枃鍗曚綅">
+                  <el-input
+                    v-model="searchInfo.unit"
+                    placeholder="璇疯緭鍏ュ彂鏂囧崟浣嶆ā绯婃煡璇�"
+                    clearable
                   />
                 </el-form-item>
               </el-col>
-              <el-col :span="7"> </el-col>
-              <el-col :span="7"> </el-col>
-              <el-col :span="3">
+              <el-col :span="8">
                 <el-button type="primary" @click="onSearch" plain icon="Search">
                   鏌ヨ
                 </el-button>
@@ -122,10 +89,20 @@
               </el-button>
             </div>
             <div>
-              <el-button type="info" plain icon="Download">
+              <el-button
+                type="info"
+                plain
+                icon="Download"
+                @click="onDownloadFiles()"
+              >
                 涓嬭浇
               </el-button>
-              <el-button type="primary" plain icon="Star">
+              <el-button
+                type="primary"
+                plain
+                icon="Star"
+                @click="onAddAttention()"
+              >
                 鍔犲叧娉�
               </el-button>
             </div>
@@ -140,18 +117,35 @@
             fit
             border
           >
-            <el-table-column type="selection" width="55" align="center" />
-            <el-table-column label="鍒跺害鍚嶇О">
-              <template #default>涓崕浜烘皯鍏卞拰鍥芥斂搴滈噰璐硶</template>
+            <el-table-column
+              type="selection"
+              width="55"
+              align="center"
+              fixed="left"
+            />
+            <el-table-column label="鏂囨。缂栧彿" width="120" align="center">
+              <template #default="{row}"> {{ row.documentCode }}</template>
             </el-table-column>
-            <el-table-column label="鍒跺害鍒嗙被" width="100">
-              <template #default>鏀垮簻閲囪喘鍒跺害</template>
+            <el-table-column
+              label="鍒跺害鍚嶇О"
+              min-width="200"
+              header-align="center"
+            >
+              <template #default="{row}"> {{ row.title }}</template>
             </el-table-column>
-            <el-table-column label="鏂囧彿" width="70">
-              <template #default> </template>
+            <el-table-column label="鍒跺害鍒嗙被" min-width="100" align="center">
+              <template #default="{row}"> {{ row.classifyId }}</template>
             </el-table-column>
-            <el-table-column label="棰佸竷鏃ユ湡" width="80">
-              <template #default>2022.5.9</template>
+            <el-table-column label="鏂囧彿" width="70" align="center">
+              <template #default="{row}"> {{ row.documentNo }}</template>
+            </el-table-column>
+            <el-table-column label="棰佸竷鏃ユ湡" width="80" align="center">
+              <template #default="{row}">
+                {{ formartDate(row.publishDate) }}
+              </template>
+            </el-table-column>
+            <el-table-column label="鍙戞枃鍗曚綅" min-width="100" align="center">
+              <template #default="{row}"> {{ row.unit }}</template>
             </el-table-column>
             <el-table-column
               label="鎿嶄綔"
@@ -159,33 +153,65 @@
               fixed="right"
               align="center"
             >
-              <template #default>
-                <el-button type="info" plain>
-                  鏌ョ湅
-                </el-button>
-                <el-button type="info" plain>
-                  涓嬭浇
-                </el-button>
-                <el-button type="primary" plain icon="Star"> </el-button>
+              <template #default="{row}">
+                <div class="row-btn-box">
+                  <el-button plain @click="toInfo(row.id)" icon="Search">
+                    鏌ョ湅
+                  </el-button>
+                  <el-button
+                    type="info"
+                    plain
+                    icon="Download"
+                    @click="onDownloadFiles(row)"
+                  >
+                    涓嬭浇
+                  </el-button>
+                  <el-button
+                    type="primary"
+                    plain
+                    icon="Star"
+                    @click="onAddAttention(row)"
+                  >
+                  </el-button>
+                </div>
               </template>
             </el-table-column>
           </el-table>
-
-          <MinPagination
+          <Pagination
             class="mt-20"
-            v-model="searchInfo.pageIndex"
-            :pageCount="listData.pageCount"
-            @onChange="getList"
+            v-model="searchInfo"
+            :dataCount="listData.total"
+            @handleChange="getList"
           />
         </el-card>
       </div>
     </div>
+    <!-- 鎿嶄綔璁板綍寮规 -->
+    <el-dialog v-model="historydialogVisible" title="鎿嶄綔璁板綍" width="600px">
+      <el-timeline>
+        <el-timeline-item v-for="(history, index) in historyList" :key="index">
+          <div class="history-item">
+            <div class="history-createDate">{{ history.createDate }}</div>
+            <div class="history-operatorName">{{ history.operatorName }}</div>
+            <div class="history-content" v-html="history.content"></div>
+          </div>
+        </el-timeline-item>
+      </el-timeline>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { onMounted, reactive, toRefs, watch, ref } from 'vue';
-// import { ElMessage, ElMessageBox } from 'element-plus';
+import { computed, onMounted, reactive, toRefs } from 'vue';
+import { iOrFrameRouterPush } from '@/router';
+import { ElMessage } from 'element-plus';
+import { EnumPublishStatus, EnumAuditStatus } from '@/utils/Enum';
+import Classify from '@/api/Classify';
+import Institution from '@/api/Institution';
+import AttachFile from '@/api/AttachFile';
+import Attention from '@/api/Attention';
+import moment from 'moment';
+import Common from '@/utils/Common';
 export default {
   setup() {
     const data = reactive({
@@ -194,87 +220,145 @@ export default {
         label: 'name',
         value: 'id'
       },
+      treeData: [],
       searchInfo: {
-        type: '鍏ㄩ儴',
-        type1: null,
-        keywords: '',
         pageIndex: 1,
-        date: ''
+        pageSize: 10,
+        title: '',
+        documentNo: '',
+        unit: '',
+        classifyId: '',
+        beginPublishDate: null,
+        endPublishDate: null,
+        publishStatus: '',
+        auditStatus: '',
+        creator: ''
       },
-      filterText: '',
-      treeData: [],
       listData: {
         pageCount: 0,
         total: 0,
         data: []
       },
-      multipleSelection: []
+      multipleSelection: [],
+      historydialogVisible: false,
+      historyList: []
     });
-    const tree = ref(null);
-    watch(
-      () => data.filterText,
-      val => {
-        tree.value.filter(val);
+
+    const publishDate = computed({
+      get() {
+        if (
+          !data.searchInfo.beginPublishDate ||
+          !data.searchInfo.endPublishDate
+        ) {
+          return null;
+        }
+        return [
+          data.searchInfo.beginPublishDate,
+          data.searchInfo.endPublishDate
+        ];
+      },
+      set(value) {
+        if (!value) {
+          data.searchInfo.beginPublishDate = null;
+          data.searchInfo.endPublishDate = null;
+        } else {
+          data.searchInfo.beginPublishDate = value[0];
+          data.searchInfo.endPublishDate = value[1];
+        }
       }
-    );
-    const filterNode = (value, data) => {
-      if (!value) return true;
-      return data.name.indexOf(value) !== -1;
-    };
-    const handleNodeClick = (data, node) => {
-      console.log(data, node);
-    };
+    });
 
     const handleSelectionChange = val => {
       data.multipleSelection = val;
     };
 
-    const getList = () => {
-      data.listData.pageCount = 5;
-      data.listData.total = 121;
-      data.listData.data = [];
-      // todo: get list data
-      for (let index = 0; index < 5; index++) {
-        data.listData.data.push({
-          title: '娌储搴撱€�2020銆�54鍙� 鍏充簬缂栧埗鏈競2020骞村害璐㈠姟閮ㄩ棬鍐崇畻鐨勫彿鐭�',
-          content: '鍒跺害鍐呭鍒跺害瑙勫垝鍐呭',
-          date: '2020-01-01'
-        });
-      }
+    const getList = async () => {
+      const res = await Institution.getInstitutionPage(data.searchInfo);
+      data.listData = res;
     };
 
-    const onSearch = () => {
-      getList();
+    const onSearch = async () => {
+      data.searchInfo.pageIndex = 1;
+      await getList();
     };
 
-    onMounted(() => {
-      data.treeData = [
-        {
-          id: 1,
-          name: '鏀垮簻浼氳鍑嗗垯鍒跺害',
-          children: [
-            { id: 2, name: '浼氳鍒跺害+琛ュ厖瑙勫畾' },
-            { id: 3, name: '鍩烘湰鎸囧紩' },
-            { id: 4, name: '鍩烘湰鍑嗗垯' }
-          ]
-        },
+    onMounted(async () => {
+      const res = await Classify.getClassifyTree();
+      data.treeData = res.data;
+      await getList();
+    });
+
+    const toEdit = id => {
+      iOrFrameRouterPush({
+        name: id ? '缂栬緫鍒跺害' : '鏂板鍒跺害',
+        path: '/policy-edit',
+        query: { id }
+      });
+    };
+
+    const toInfo = id => {
+      iOrFrameRouterPush({
+        name: '鍒跺害璇︽儏',
+        path: '/policy-info',
+        query: { id }
+      });
+    };
+
+    const formartDate = value => {
+      return moment(value).format('YYYY.MM.DD');
+    };
 
-        {
-          id: 5,
-          name: '璐㈠姟棰勭畻绠$悊鍒跺害'
+    const onDownloadFiles = async row => {
+      const req = { institutionIdList: [] };
+      if (row) {
+        req.institutionIdList.push(row.id);
+      } else {
+        req.institutionIdList = [...data.multipleSelection.map(t => t.id)];
+      }
+      if (req.institutionIdList.length === 0) {
+        ElMessage.warning('璇峰嬀閫夊埗搴�');
+        return;
+      }
+      const res = await AttachFile.downloadFile(req);
+      if (res) {
+        const resData = await Common.getJsonOrDownloadFile(res);
+        if (resData.code && resData.code !== '00000') {
+          ElMessage({
+            type: 'warning',
+            message: resData.description
+          });
         }
-      ];
-      getList();
-    });
+      }
+    };
+
+    const onAddAttention = async row => {
+      const req = { institutionIdList: [] };
+      if (row) {
+        req.institutionIdList = [row.id];
+      } else {
+        req.institutionIdList = [...data.multipleSelection.map(t => t.id)];
+        if (req.institutionIdList.length === 0) {
+          ElMessage.warning('璇峰嬀閫夊埗搴�');
+          return;
+        }
+      }
+      await Attention.addAttention(req);
+      ElMessage.success('鎿嶄綔鎴愬姛');
+    };
 
     return {
       ...toRefs(data),
-      tree,
-      filterNode,
-      handleNodeClick,
+      publishDate,
       onSearch,
       getList,
-      handleSelectionChange
+      handleSelectionChange,
+      toEdit,
+      toInfo,
+      EnumPublishStatus,
+      EnumAuditStatus,
+      formartDate,
+      onDownloadFiles,
+      onAddAttention
     };
   }
 };
@@ -283,7 +367,7 @@ export default {
 <style lang="scss" scoped>
 .app-container {
   .app-content {
-    display: flex;
+    // display: flex;
     .tree-card {
       width: 260px;
       .custom-tree-node {
@@ -291,8 +375,8 @@ export default {
       }
     }
     .right-box {
-      width: calc(100% - 260px);
-      padding-left: 20px;
+      // width: calc(100% - 260px);
+      // padding-left: 20px;
       .search-card {
         ::v-deep(.el-card__body) {
           padding-bottom: 0;
@@ -302,6 +386,22 @@ export default {
         display: flex;
         justify-content: space-between;
       }
+      .row-btn-box {
+        margin: 5px 0 0 5px;
+        ::v-deep(.el-button) {
+          margin: 0 5px 5px 0;
+        }
+      }
+    }
+  }
+  .history-item {
+    display: flex;
+    .history-createDate {
+      color: rgb(87, 87, 87);
+    }
+    .history-operatorName {
+      color: #2558ab;
+      margin: 0 10px;
     }
   }
 }
diff --git a/WebSite/src/views/policy-system-library/system-management.vue b/WebSite/src/views/policy-system-library/system-management.vue
index 0455066..a12cbe0 100644
--- a/WebSite/src/views/policy-system-library/system-management.vue
+++ b/WebSite/src/views/policy-system-library/system-management.vue
@@ -196,7 +196,7 @@
                 </el-tag>
               </template>
             </el-table-column>
-            <el-table-column label="瀹℃牳鐘舵€�" width="80" align="center">
+            <el-table-column label="瀹℃牳鐘舵€�" width="85" align="center">
               <template #default="{row}">
                 <el-tag
                   :type="EnumAuditStatus.properties[row.auditStatus].type"
@@ -223,6 +223,7 @@
                     鏌ョ湅
                   </el-button>
                   <el-button
+                    v-if="row.isShowEditBtn"
                     type="primary"
                     plain
                     @click="toEdit(row.id)"
@@ -231,7 +232,7 @@
                     缂栬緫
                   </el-button>
                   <el-popconfirm
-                    v-if="row.publishStatus !== EnumPublishStatus.Type2"
+                    v-if="row.isShowPublishBtn || row.isShowRecoverBtn"
                     :title="`鏄惁${getPublishBtnText(row)}?`"
                     @confirm="setPublishStatus(row)"
                   >
@@ -242,7 +243,7 @@
                     </template>
                   </el-popconfirm>
                   <el-button
-                    v-else
+                    v-if="row.isShowCancelBtn"
                     type="danger"
                     plain
                     icon="CircleClose"
@@ -397,7 +398,7 @@ export default {
     };
 
     const getPublishBtnText = row => {
-      return row.publishStatus === EnumPublishStatus.Type1 ? '鍙戝竷' : '鎭㈠';
+      return row.isShowPublishBtn ? '鍙戝竷' : '鎭㈠';
     };
 
     const setPublishStatus = async row => {
-- 
GitLab