Browse Source

修改显示字段

zs 8 tháng trước cách đây
mục cha
commit
8578218bed

+ 186 - 0
package-lock.json

@@ -31,6 +31,7 @@
         "postcss-px2rem": "^0.3.0",
         "qrcode.vue": "^3.4.1",
         "relation-graph-vue3": "^2.2.1",
+        "stompjs": "^2.3.3",
         "universal-cookie": "^7.1.0",
         "vue": "^3.4.15",
         "vue-i18n": "^9.9.1",
@@ -2011,6 +2012,19 @@
         "node": ">=8"
       }
     },
+    "node_modules/bufferutil": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/bufferutil/-/bufferutil-4.0.8.tgz",
+      "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
+      "hasInstallScript": true,
+      "optional": true,
+      "dependencies": {
+        "node-gyp-build": "^4.3.0"
+      },
+      "engines": {
+        "node": ">=6.14.2"
+      }
+    },
     "node_modules/bundle-name": {
       "version": "4.1.0",
       "resolved": "https://registry.npmmirror.com/bundle-name/-/bundle-name-4.1.0.tgz",
@@ -4019,6 +4033,12 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
+      "optional": true
+    },
     "node_modules/is-url": {
       "version": "1.2.4",
       "resolved": "https://registry.npmmirror.com/is-url/-/is-url-1.2.4.tgz",
@@ -4665,6 +4685,17 @@
       "resolved": "https://registry.npmmirror.com/next-tick/-/next-tick-1.1.0.tgz",
       "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
     },
+    "node_modules/node-gyp-build": {
+      "version": "4.8.1",
+      "resolved": "https://registry.npmmirror.com/node-gyp-build/-/node-gyp-build-4.8.1.tgz",
+      "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==",
+      "optional": true,
+      "bin": {
+        "node-gyp-build": "bin.js",
+        "node-gyp-build-optional": "optional.js",
+        "node-gyp-build-test": "build-test.js"
+      }
+    },
     "node_modules/normalize-path": {
       "version": "3.0.0",
       "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -6268,6 +6299,14 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/stompjs": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmmirror.com/stompjs/-/stompjs-2.3.3.tgz",
+      "integrity": "sha512-5l/Ogz0DTFW7TrpHF0LAETGqM/so8UxNJvYZjJKqcX31EVprSQgnGkO80tZctPC/lFBDUrSFiTG3xd0R27XAIA==",
+      "optionalDependencies": {
+        "websocket": "latest"
+      }
+    },
     "node_modules/strict-uri-encode": {
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
@@ -6826,6 +6865,15 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/typedarray-to-buffer": {
+      "version": "3.1.5",
+      "resolved": "https://registry.npmmirror.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+      "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+      "optional": true,
+      "dependencies": {
+        "is-typedarray": "^1.0.0"
+      }
+    },
     "node_modules/ufo": {
       "version": "1.5.3",
       "resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.5.3.tgz",
@@ -7182,6 +7230,19 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/utf-8-validate": {
+      "version": "5.0.10",
+      "resolved": "https://registry.npmmirror.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
+      "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
+      "hasInstallScript": true,
+      "optional": true,
+      "dependencies": {
+        "node-gyp-build": "^4.3.0"
+      },
+      "engines": {
+        "node": ">=6.14.2"
+      }
+    },
     "node_modules/util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -7471,6 +7532,38 @@
       "integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==",
       "dev": true
     },
+    "node_modules/websocket": {
+      "version": "1.0.35",
+      "resolved": "https://registry.npmmirror.com/websocket/-/websocket-1.0.35.tgz",
+      "integrity": "sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q==",
+      "optional": true,
+      "dependencies": {
+        "bufferutil": "^4.0.1",
+        "debug": "^2.2.0",
+        "es5-ext": "^0.10.63",
+        "typedarray-to-buffer": "^3.1.5",
+        "utf-8-validate": "^5.0.2",
+        "yaeti": "^0.0.6"
+      },
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/websocket/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "optional": true,
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/websocket/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "optional": true
+    },
     "node_modules/which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
@@ -7505,6 +7598,15 @@
         "node": ">=12"
       }
     },
+    "node_modules/yaeti": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmmirror.com/yaeti/-/yaeti-0.0.6.tgz",
+      "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==",
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.32"
+      }
+    },
     "node_modules/yallist": {
       "version": "4.0.0",
       "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
@@ -8810,6 +8912,15 @@
         "fill-range": "^7.0.1"
       }
     },
+    "bufferutil": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/bufferutil/-/bufferutil-4.0.8.tgz",
+      "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
+      "optional": true,
+      "requires": {
+        "node-gyp-build": "^4.3.0"
+      }
+    },
     "bundle-name": {
       "version": "4.1.0",
       "resolved": "https://registry.npmmirror.com/bundle-name/-/bundle-name-4.1.0.tgz",
@@ -10291,6 +10402,12 @@
       "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
       "dev": true
     },
+    "is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
+      "optional": true
+    },
     "is-url": {
       "version": "1.2.4",
       "resolved": "https://registry.npmmirror.com/is-url/-/is-url-1.2.4.tgz",
@@ -10802,6 +10919,12 @@
       "resolved": "https://registry.npmmirror.com/next-tick/-/next-tick-1.1.0.tgz",
       "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
     },
+    "node-gyp-build": {
+      "version": "4.8.1",
+      "resolved": "https://registry.npmmirror.com/node-gyp-build/-/node-gyp-build-4.8.1.tgz",
+      "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==",
+      "optional": true
+    },
     "normalize-path": {
       "version": "3.0.0",
       "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -11961,6 +12084,14 @@
         }
       }
     },
+    "stompjs": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmmirror.com/stompjs/-/stompjs-2.3.3.tgz",
+      "integrity": "sha512-5l/Ogz0DTFW7TrpHF0LAETGqM/so8UxNJvYZjJKqcX31EVprSQgnGkO80tZctPC/lFBDUrSFiTG3xd0R27XAIA==",
+      "requires": {
+        "websocket": "latest"
+      }
+    },
     "strict-uri-encode": {
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
@@ -12391,6 +12522,15 @@
       "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
       "dev": true
     },
+    "typedarray-to-buffer": {
+      "version": "3.1.5",
+      "resolved": "https://registry.npmmirror.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+      "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+      "optional": true,
+      "requires": {
+        "is-typedarray": "^1.0.0"
+      }
+    },
     "ufo": {
       "version": "1.5.3",
       "resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.5.3.tgz",
@@ -12641,6 +12781,15 @@
       "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
       "dev": true
     },
+    "utf-8-validate": {
+      "version": "5.0.10",
+      "resolved": "https://registry.npmmirror.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
+      "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
+      "optional": true,
+      "requires": {
+        "node-gyp-build": "^4.3.0"
+      }
+    },
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -12821,6 +12970,37 @@
       "integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==",
       "dev": true
     },
+    "websocket": {
+      "version": "1.0.35",
+      "resolved": "https://registry.npmmirror.com/websocket/-/websocket-1.0.35.tgz",
+      "integrity": "sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q==",
+      "optional": true,
+      "requires": {
+        "bufferutil": "^4.0.1",
+        "debug": "^2.2.0",
+        "es5-ext": "^0.10.63",
+        "typedarray-to-buffer": "^3.1.5",
+        "utf-8-validate": "^5.0.2",
+        "yaeti": "^0.0.6"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "optional": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "optional": true
+        }
+      }
+    },
     "which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
@@ -12846,6 +13026,12 @@
       "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
       "dev": true
     },
+    "yaeti": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmmirror.com/yaeti/-/yaeti-0.0.6.tgz",
+      "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==",
+      "optional": true
+    },
     "yallist": {
       "version": "4.0.0",
       "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",

+ 1 - 0
package.json

@@ -34,6 +34,7 @@
     "postcss-px2rem": "^0.3.0",
     "qrcode.vue": "^3.4.1",
     "relation-graph-vue3": "^2.2.1",
+    "stompjs": "^2.3.3",
     "universal-cookie": "^7.1.0",
     "vue": "^3.4.15",
     "vue-i18n": "^9.9.1",

+ 40 - 0
src/store/api/user/incubatorYear.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/incubatorYear'
+const axios = new AxiosWrapper()
+
+export const IncubatorYearStore = defineStore('incubatorYear', () => {
+  const query = async ({ skip = 0, limit = undefined, ...info } = {}) => {
+    let cond = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${url}`, cond)
+    return res
+  }
+  const fetch = async (payload) => {
+    const res = await axios.$get(`${url}/${payload}`)
+    return res
+  }
+  const create = async (payload) => {
+    const res = await axios.$post(`${url}`, payload)
+    return res
+  }
+  const update = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload) => {
+    const res = await axios.$delete(`${url}/${payload}`)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 7 - 7
src/views/center/achievement.vue

@@ -5,9 +5,9 @@
         <el-col :span="24" class="one">
           <div class="one_left">
             <div class="button" @click="toAdd">发布成果</div>
-            <div class="button" @click="toTemplate">下载导模板</div>
-            <el-upload class="button" action="/files/web/cxyy_import/upload" :show-file-list="false" :on-success="onSuccess" accept=".xlsx"> 选择excel模板文件 </el-upload>
-            <div class="button" @click="toDownload">下载Excel</div>
+            <div class="button" @click="toTemplate">下载导模板</div>
+            <el-upload class="button" action="/files/web/cxyy_import/upload" :show-file-list="false" :on-success="onSuccess" accept=".xlsx"> 选择导入文件 </el-upload>
+            <div class="button" @click="toDownload">导出数据</div>
           </div>
           <div class="one_right">
             <el-input v-model="searchForm.name" style="width: 250px" size="large" placeholder="搜索" @change="search" :suffix-icon="Search" />
@@ -310,7 +310,7 @@ const checkedExportChange = (value) => {
   checkAll.value = checkedCount === formFields.value.length
   isIndeterminate.value = checkedCount > 0 && checkedCount < formFields.value.length
 }
-// 下载导模板
+// 下载导模板
 const toTemplate = () => {
   window.open('/cxyyWeb/产学研用成果模板.xlsx')
 }
@@ -335,12 +335,12 @@ const onSuccess = async (response, file) => {
     msgbox.close()
   }
 }
-// 下载Excel
+// 导出数据
 const toDownload = () => {
-  dialog.value = { type: '3', show: true, title: '下载Excel' }
+  dialog.value = { type: '3', show: true, title: '导出数据' }
 }
 
-// 导出Excel
+// 导出数据
 const toFile = async () => {
   if (checkedExport.value.length > 0) {
     const reqData = { table: 'achievement', config: checkedExport.value, user: user.value.id }

+ 10 - 1
src/views/center/attestation.vue

@@ -78,7 +78,8 @@ const cardTypeList = ref([])
 const contributionList = ref([])
 const plateList = ref([])
 const modeList = ref([])
-
+const statusList = ref([])
+const yearList = ref([])
 // 请求
 onMounted(async () => {
   loading.value = true
@@ -133,6 +134,12 @@ const searchOther = async () => {
   // 盈利模式
   result = await dictDataStore.query({ code: 'modeType', is_use: '0' })
   if ($checkRes(result)) modeList.value = result.data
+  // 状态
+  result = await dictDataStore.query({ code: 'examStatus', is_use: '0' })
+  if ($checkRes(result)) statusList.value = result.data
+  // 年度
+  result = await dictDataStore.query({ code: 'year', is_use: '0' })
+  if ($checkRes(result)) yearList.value = result.data
 }
 const search = async () => {
   if (user.value.id) {
@@ -156,6 +163,8 @@ provide('cardTypeList', cardTypeList)
 provide('contributionList', contributionList)
 provide('plateList', plateList)
 provide('modeList', modeList)
+provide('yearList', yearList)
+provide('statusList', statusList)
 </script>
 <style scoped lang="scss">
 .main {

+ 7 - 7
src/views/center/demand.vue

@@ -5,9 +5,9 @@
         <el-col :span="24" class="one">
           <div class="one_left">
             <div class="button" @click="toAdd">发布需求</div>
-            <div class="button" @click="toTemplate">下载导模板</div>
-            <el-upload class="button" action="/files/web/cxyy_import/upload" :show-file-list="false" :on-success="onSuccess" accept=".xlsx"> 选择excel模板文件 </el-upload>
-            <div class="button" @click="toDownload">下载Excel</div>
+            <div class="button" @click="toTemplate">下载导模板</div>
+            <el-upload class="button" action="/files/web/cxyy_import/upload" :show-file-list="false" :on-success="onSuccess" accept=".xlsx"> 选择导入文件 </el-upload>
+            <div class="button" @click="toDownload">导出数据</div>
           </div>
           <div class="one_right">
             <el-input v-model="searchForm.name" style="width: 250px" size="large" placeholder="搜索" @change="search" :suffix-icon="Search" />
@@ -366,7 +366,7 @@ const checkedExportChange = (value) => {
   checkAll.value = checkedCount === formFields.value.length
   isIndeterminate.value = checkedCount > 0 && checkedCount < formFields.value.length
 }
-// 下载导模板
+// 下载导模板
 const toTemplate = () => {
   window.open('/cxyyWeb/产学研用需求模板.xlsx')
 }
@@ -391,12 +391,12 @@ const onSuccess = async (response, file) => {
     msgbox.close()
   }
 }
-// 下载Excel
+// 导出数据
 const toDownload = () => {
-  dialog.value = { type: '3', show: true, title: '下载Excel' }
+  dialog.value = { type: '3', show: true, title: '导出数据' }
 }
 
-// 导出Excel
+// 导出数据
 const toFile = async () => {
   if (checkedExport.value.length > 0) {
     const reqData = { table: 'demand', config: checkedExport.value, user: user.value.id }

+ 2 - 2
src/views/center/notice.vue

@@ -8,13 +8,13 @@
               <el-empty description="暂无数据" />
             </template>
             <el-table-column prop="type" align="center" label="通知类型" width="100">
-              <template #="{ row }">
+              <template #default="{ row }">
                 {{ getDict(row, 'type') }}
               </template>
             </el-table-column>
             <el-table-column prop="content" align="center" label="内容" />
             <el-table-column prop="is_read" align="center" label="是否已读" width="100">
-              <template #="{ row }">
+              <template #default="{ row }">
                 {{ getDict(row, 'is_read') }}
               </template>
             </el-table-column>

+ 366 - 68
src/views/center/parts/incubator.vue

@@ -1,93 +1,256 @@
 <template>
   <div class="index">
-    <el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="auto" class="form" label-position="left">
-      <el-row>
-        <el-form-item label="Logo" prop="logo">
-          <custom-upload model="logo" :list="form.logo" :limit="1" url="/files/web/cxyy_incubator/upload" @change="onUpload" listType="picture-card"></custom-upload>
-        </el-form-item>
-      </el-row>
-      <el-row :gutter="20">
-        <el-col :span="12">
-          <el-form-item label="孵化基地名称" prop="name">
-            <el-input size="large" clearable v-model="form.name" placeholder="请输入孵化基地名称" />
-          </el-form-item>
+    <el-tabs v-model="activeName" type="card">
+      <el-tab-pane label="基本信息" name="first">
+        <el-form ref="ruleFormRef" :model="form" :rules="rules" class="form" label-position="left">
+          <el-row>
+            <el-form-item label="Logo" prop="logo">
+              <custom-upload model="logo" :list="form.logo" :limit="1" url="/files/web/cxyy_incubator/upload" @change="onUpload" listType="picture-card"></custom-upload>
+            </el-form-item>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="孵化基地名称" prop="name">
+                <el-input size="large" clearable v-model="form.name" placeholder="请输入孵化基地名称" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="运营单位名称" prop="unit">
+                <el-input size="large" clearable v-model="form.unit" placeholder="请输入运营单位名称" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="负责人姓名" prop="person">
+                <el-input size="large" clearable v-model="form.person" placeholder="请输入负责人姓名" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="负责人电话" prop="person_phone">
+                <el-input size="large" clearable v-model="form.person_phone" placeholder="请输入负责人电话" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="所在地区" prop="area">
+                <el-cascader size="large" v-model="form.area" :props="{ value: 'name', label: 'name' }" :options="cityList" clearable placeholder="请选择所在地区" style="width: 100%" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="地址" prop="address">
+                <el-input size="large" v-model="form.address" :autosize="{ minRows: 2, maxRows: 4 }" type="textarea" placeholder="请输入地址" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="占地面积(平方米)" prop="cover_area">
+                <el-input size="large" clearable v-model="form.cover_area" placeholder="请输入占地面积(平方米)" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="建筑面积(平方米)" prop="build_area">
+                <el-input size="large" clearable v-model="form.build_area" placeholder="请输入建筑面积(平方米)" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="剩余面积(平方米)" prop="residue_area">
+                <el-input size="large" clearable v-model="form.residue_area" placeholder="请输入剩余面积(平方米)" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="房租(元/平方米/月)" prop="rent">
+                <el-input size="large" clearable v-model="form.rent" placeholder="请输入房租(元/平方米/月)" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="物业费(元/平方米/月)" prop="wy_money">
+                <el-input size="large" clearable v-model="form.wy_money" placeholder="请输入物业费(元/平方米/月)" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="是否具备中试场地" prop="is_have">
+                <el-radio-group size="large" v-model="form.is_have">
+                  <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{ i.label }}</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="载体运营单位人数" prop="unit_num">
+                <el-input size="large" type="number" clearable v-model="form.unit_num" placeholder="请输入载体运营单位人数" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="载体运营单位的省级以上导师数" prop="teacher_num">
+                <el-input size="large" type="number" clearable v-model="form.teacher_num" placeholder="请输入载体运营单位的省级以上导师数" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="中试场地面积(平方米)" prop="site_area">
+                <el-input size="large" clearable v-model="form.site_area" placeholder="请输入中试场地面积(平方米)" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="累计参加活动人次" prop="activity_num">
+                <el-input size="large" type="number" clearable v-model="form.activity_num" placeholder="请输入累计参加活动人次" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="累计参加活动企业数量" prop="actCompany_num">
+                <el-input size="large" type="number" clearable v-model="form.actCompany_num" placeholder="请输入累计参加活动企业数量" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="市级以上活动数" prop="actCity_num">
+                <el-input size="large" type="number" clearable v-model="form.actCity_num" placeholder="请输入市级以上活动数" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="培训辅导类活动数" prop="actTrain_num">
+                <el-input size="large" type="number" clearable v-model="form.actTrain_num" placeholder="请输入培训辅导类活动数" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="高校院所类活动数" prop="actSchool_num">
+                <el-input size="large" type="number" clearable v-model="form.actSchool_num" placeholder="请输入高校院所类活动数" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="投资机构类活动数" prop="actInstitution_num">
+                <el-input size="large" type="number" clearable v-model="form.actInstitution_num" placeholder="请输入投资机构类活动数" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="中介服务类活动数" prop="actService_num">
+                <el-input size="large" type="number" clearable v-model="form.actService_num" placeholder="请输入中介服务类活动数" />
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-col :span="24">
+            <el-form-item label="入驻企业数" prop="company_num">
+              <el-input size="large" type="number" clearable v-model="form.company_num" placeholder="请输入入驻企业数" />
+            </el-form-item>
+          </el-col>
+          <el-row :gutter="20">
+            <el-col :span="12">
+              <el-form-item label="是否公开" prop="is_show">
+                <el-radio-group size="large" v-model="form.is_show">
+                  <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{ i.label }}</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="是否和平台合作标识" prop="cooperate">
+                <el-radio-group v-model="form.cooperate" disabled>
+                  <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-col :span="24">
+            <el-form-item label="简介" prop="brief">
+              <WangEditor v-model="form.brief" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24" class="button">
+            <el-button type="primary" @click="submitForm(ruleFormRef)">保存</el-button>
+          </el-col>
+        </el-form>
+      </el-tab-pane>
+      <el-tab-pane label="年度信息" name="second" v-if="form && form.id">
+        <el-col :span="24" class="one">
+          <div class="one_left">
+            <div class="button" @click="toAdd">发布年度信息</div>
+          </div>
+          <div class="one_right">
+            <el-input v-model="searchForm.year" style="width: 250px" size="large" placeholder="搜索年度" @change="search" :suffix-icon="Search" />
+          </div>
         </el-col>
-        <el-col :span="12">
-          <el-form-item label="负责人姓名" prop="person">
-            <el-input size="large" clearable v-model="form.person" placeholder="请输入负责人姓名" />
-          </el-form-item>
+        <el-col :span="24" class="two">
+          <el-table :data="list" style="width: 100%" size="large" :header-cell-style="{ backgroundColor: '#edf3ff' }">
+            <template #empty>
+              <el-empty description="暂无数据" />
+            </template>
+            <el-table-column prop="year" align="center" label="年度" />
+            <el-table-column prop="act_num" align="center" label="活动总数" width="180" />
+            <el-table-column prop="time" align="center" label="填写时间" width="180" />
+            <el-table-column prop="is_use" align="center" label="是否使用" width="180">
+              <template #default="scope">
+                <div>{{ getDict(scope.row.is_use, 'is_use') }}</div>
+              </template>
+            </el-table-column>
+            <el-table-column prop="status" align="center" label="状态" width="180">
+              <template #default="scope">
+                <div>{{ getDict(scope.row.status, 'status') }}</div>
+              </template>
+            </el-table-column>
+            <el-table-column align="center" label="操作" width="180">
+              <template #default="{ row }">
+                <el-link v-if="row.status == '-2'" :underline="false" type="warning" size="mini" @click="toExam(row)" style="margin-right: 10px">提交审核</el-link>
+                <el-link :underline="false" type="primary" size="mini" @click="toEdit(row)" style="margin-right: 10px">修改</el-link>
+                <el-link :underline="false" type="danger" size="mini" @click="toDelete(row)"> 删除 </el-link>
+              </template>
+            </el-table-column>
+          </el-table>
         </el-col>
-      </el-row>
-      <el-row :gutter="20">
-        <el-col :span="12">
-          <el-form-item label="负责人电话" prop="person_phone">
-            <el-input size="large" clearable v-model="form.person_phone" placeholder="请输入负责人电话" />
-          </el-form-item>
+        <el-col :span="24" class="thr">
+          <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
         </el-col>
-        <el-col :span="12">
-          <el-form-item label="是否公开" prop="is_show">
-            <el-radio-group size="large" v-model="form.is_show">
-              <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{ i.label }}</el-radio>
-            </el-radio-group>
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-row :gutter="20">
-        <el-col :span="12">
-          <el-form-item label="所属行业" prop="industry">
-            <el-select size="large" clearable v-model="form.industry" placeholder="请选择所属行业">
-              <el-option v-for="(item, index) in plateList" :key="index" :label="item.title" :value="item.title" />
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item label="是否和平台合作标识" prop="cooperate">
-            <el-radio-group v-model="form.cooperate" disabled>
-              <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
-            </el-radio-group>
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-row :gutter="20">
-        <el-col :span="12">
-          <el-form-item label="所在地区" prop="area">
-            <el-cascader size="large" v-model="form.area" :props="{ value: 'name', label: 'name' }" :options="cityList" clearable placeholder="请选择所在地区" style="width: 100%" />
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item label="地址" prop="address">
-            <el-input size="large" v-model="form.address" :autosize="{ minRows: 2, maxRows: 4 }" type="textarea" placeholder="请输入地址" />
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-col :span="24">
-        <el-form-item label="简介" prop="brief">
-          <WangEditor v-model="form.brief" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="24" class="button">
-        <el-button type="primary" @click="submitForm(ruleFormRef)">保存</el-button>
-      </el-col>
-    </el-form>
+      </el-tab-pane>
+    </el-tabs>
   </div>
+  <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose" :width="width">
+    <el-row>
+      <el-col :span="24" v-if="dialog.type == '1'">
+        <custom-form v-model="yearForm" :fields="formFields" :rules="yearRules" @save="toSave" @draftSave="toDraftSave">
+          <template #is_use>
+            <el-radio v-for="i in isUseList" :key="i.id" :label="i.value">{{ i.label }}</el-radio>
+          </template>
+          <template #year>
+            <el-option v-for="i in yearList" :key="i.id" :label="i.label" :value="i.label"></el-option>
+          </template>
+        </custom-form>
+      </el-col>
+    </el-row>
+  </el-dialog>
 </template>
 <script setup>
 // 基础
+import { cloneDeep, get } from 'lodash-es'
 const $checkRes = inject('$checkRes')
-const cloneDeep = inject('cloneDeep')
 // 用户信息
 import { UserStore } from '@/store/user'
 const userStore = UserStore()
 const user = computed(() => userStore.user)
 // 表单
 const ruleFormRef = ref()
+const activeName = ref('first')
 // 字典表
 const isUseList = inject('isUseList')
-const plateList = inject('plateList')
+const statusList = inject('statusList')
+const yearList = inject('yearList')
 const cityList = inject('cityList')
 // 接口
 import { IncubatorStore } from '@/store/api/user/incubator'
+import { IncubatorYearStore } from '@/store/api/user/incubatorYear'
 const incubatorStore = IncubatorStore()
+const yearStore = IncubatorYearStore()
 const form = ref({ logo: [] })
 const rules = reactive({
   // nick_name: [{ required: true, message: '请输入昵称', trigger: 'blur' }],
@@ -97,6 +260,29 @@ const rules = reactive({
   // password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
   // refpassword: [{ required: true, validator: validatePassword, trigger: 'blur' }]
 })
+const yearForm = ref({})
+const dialog = ref({ type: '1', show: false, title: '发布年度信息' })
+const formFields = ref([
+  { label: '年度', model: 'year', type: 'select' },
+  { label: '活动总数', model: 'act_num', type: 'number' },
+  { label: '企业实现收入(万元)', model: 'income_money', type: 'number' },
+  { label: '企业利润(万元)', model: 'profit_money', type: 'number' },
+  { label: '企业税金(万元)', model: 'tax_money', type: 'number' },
+  { label: '企业预计收入(万元)', model: 'esincome_money', type: 'number' },
+  { label: '企业预计利润(万元)', model: 'esprofit_money', type: 'number' },
+  { label: '企业预计税金(万元)', model: 'estax_money', type: 'number' },
+  { label: '获得荣誉情况', model: 'content', type: 'textarea' },
+  { label: '是否使用', model: 'is_use', type: 'radio', mark: 'dict', code: 'isUse' }
+])
+const yearRules = reactive({ year: [{ required: true, message: '请选择年度', trigger: 'blur' }] })
+// 列表
+const list = ref([])
+let skip = 0
+let limit = inject('limit')
+const total = ref(0)
+const currentPage = ref(1)
+const searchForm = ref({})
+
 // 上传图片
 const onUpload = (e) => {
   const { model, value } = e
@@ -123,6 +309,7 @@ const submitForm = async (formEl) => {
 // 请求
 onMounted(async () => {
   await search()
+  await searchYear()
 })
 const search = async () => {
   if (user.value.id) {
@@ -133,11 +320,122 @@ const search = async () => {
     }
   }
 }
+const searchYear = async (query = { skip, limit }) => {
+  skip = query.skip
+  limit = query.limit
+  const info = {
+    skip: query.skip,
+    limit: query.limit,
+    incubator: form.value.id,
+    ...searchForm.value
+  }
+  if (form.value.id) {
+    const res = await yearStore.query(info)
+    if (res.errcode == '0') {
+      list.value = res.data
+      total.value = res.total
+    }
+  }
+}
+// 字典数据转换
+const getDict = (data, model) => {
+  if (data) {
+    let res
+    if (model == 'status') res = statusList.value.find((f) => f.value == data)
+    else if (model == 'is_use') res = isUseList.value.find((f) => f.value == data)
+    return get(res, 'label')
+  }
+}
+// 添加
+const toAdd = () => {
+  dialog.value = { type: '1', show: true, title: '发布年度信息' }
+}
+// 修改
+const toEdit = (data) => {
+  yearForm.value = data
+  dialog.value = { type: '1', show: true, title: '修改年度信息' }
+}
+// 删除
+const toDelete = (data) => {
+  ElMessageBox.confirm(`您确认删除该数据?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
+    .then(async () => {
+      const res = await yearStore.del(data.id)
+      if ($checkRes(res, true)) {
+        search({ skip, limit })
+      }
+    })
+    .catch(() => {})
+}
+const toSave = async () => {
+  const data = cloneDeep(yearForm.value)
+  const other = { status: '0', user: user.value.id, incubator: form.value.id }
+  let res
+  if (get(data, 'id')) res = await yearStore.update({ ...data, ...other })
+  else res = await yearStore.create({ ...data, ...other })
+  if ($checkRes(res, true)) {
+    await search({ skip, limit })
+    await toClose()
+  }
+}
+const toDraftSave = async () => {
+  const data = cloneDeep(yearForm.value)
+  const other = { status: '-2', user: user.value.id, incubator: form.value.id }
+  let res
+  if (get(data, 'id')) res = await yearStore.update({ ...data, ...other })
+  else res = await yearStore.create({ ...data, ...other })
+  if ($checkRes(res, true)) {
+    await search({ skip, limit })
+    await toClose()
+  }
+}
+// 审核保存
+const toExam = async (row) => {
+  ElMessageBox.confirm(`您确认保存并提交审核该数据?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
+    .then(async () => {
+      const data = cloneDeep(row)
+      let res = await yearStore.update({ id: data.id, status: '0', user: user.value.id, incubator: form.value.id })
+      if ($checkRes(res, true)) {
+        await search({ skip, limit })
+        await toClose()
+      }
+    })
+    .catch(() => {})
+}
+const toClose = () => {
+  form.value = {}
+  dialog.value = { show: false }
+}
 </script>
 <style scoped lang="scss">
 .index {
   .button {
     text-align: center;
   }
+  .one {
+    height: 50px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin: 0 0 10px 0;
+    .one_left {
+      display: flex;
+      font-size: 16px;
+      .button {
+        background: #1875df;
+        padding: 0 10px;
+        height: 30px;
+        color: #fff;
+        line-height: 30px;
+        text-align: center;
+        cursor: default;
+        margin: 0 10px 0 0;
+      }
+    }
+  }
+  .thr {
+    display: flex;
+    justify-content: center;
+    margin: 20px 0 0 0;
+  }
 }
 </style>

+ 7 - 7
src/views/center/project.vue

@@ -5,9 +5,9 @@
         <el-col :span="24" class="one">
           <div class="one_left">
             <div class="button" @click="toAdd">发布项目</div>
-            <div class="button" @click="toTemplate">下载导模板</div>
-            <el-upload class="button" action="/files/web/cxyy_import/upload" :show-file-list="false" :on-success="onSuccess" accept=".xlsx"> 选择excel模板文件 </el-upload>
-            <div class="button" @click="toDownload">下载Excel</div>
+            <div class="button" @click="toTemplate">下载导模板</div>
+            <el-upload class="button" action="/files/web/cxyy_import/upload" :show-file-list="false" :on-success="onSuccess" accept=".xlsx"> 选择导入文件 </el-upload>
+            <div class="button" @click="toDownload">导出数据</div>
           </div>
           <div class="one_right">
             <el-input v-model="searchForm.name" style="width: 250px" size="large" placeholder="搜索" @change="search" :suffix-icon="Search" />
@@ -374,7 +374,7 @@ const checkedExportChange = (value) => {
   checkAll.value = checkedCount === formFields.value.length
   isIndeterminate.value = checkedCount > 0 && checkedCount < formFields.value.length
 }
-// 下载导模板
+// 下载导模板
 const toTemplate = () => {
   window.open('/cxyyWeb/产学研用项目模板.xlsx')
 }
@@ -399,12 +399,12 @@ const onSuccess = async (response, file) => {
     msgbox.close()
   }
 }
-// 下载Excel
+// 导出数据
 const toDownload = () => {
-  dialog.value = { type: '3', show: true, title: '下载Excel' }
+  dialog.value = { type: '3', show: true, title: '导出数据' }
 }
 
-// 导出Excel
+// 导出数据
 const toFile = async () => {
   if (checkedExport.value.length > 0) {
     const reqData = { table: 'project', config: checkedExport.value, user: user.value.id }

+ 7 - 7
src/views/center/supply.vue

@@ -5,9 +5,9 @@
         <el-col :span="24" class="one">
           <div class="one_left">
             <div class="button" @click="toAdd">发布供给</div>
-            <div class="button" @click="toTemplate">下载导模板</div>
-            <el-upload class="button" action="/files/web/cxyy_import/upload" :show-file-list="false" :on-success="onSuccess" accept=".xlsx"> 选择excel模板文件 </el-upload>
-            <div class="button" @click="toDownload">下载Excel</div>
+            <div class="button" @click="toTemplate">下载导模板</div>
+            <el-upload class="button" action="/files/web/cxyy_import/upload" :show-file-list="false" :on-success="onSuccess" accept=".xlsx"> 选择导入文件 </el-upload>
+            <div class="button" @click="toDownload">导出数据</div>
           </div>
           <div class="one_right">
             <el-input v-model="searchForm.name" style="width: 250px" size="large" placeholder="搜索" @change="search" :suffix-icon="Search" />
@@ -364,7 +364,7 @@ const checkedExportChange = (value) => {
   checkAll.value = checkedCount === formFields.value.length
   isIndeterminate.value = checkedCount > 0 && checkedCount < formFields.value.length
 }
-// 下载导模板
+// 下载导模板
 const toTemplate = () => {
   window.open('/cxyyWeb/产学研用供给模板.xlsx')
 }
@@ -389,12 +389,12 @@ const onSuccess = async (response, file) => {
     msgbox.close()
   }
 }
-// 下载Excel
+// 导出数据
 const toDownload = () => {
-  dialog.value = { type: '3', show: true, title: '下载Excel' }
+  dialog.value = { type: '3', show: true, title: '导出数据' }
 }
 
-// 导出Excel
+// 导出数据
 const toFile = async () => {
   if (checkedExport.value.length > 0) {
     const reqData = { table: 'supply', config: checkedExport.value, user: user.value.id }

+ 6 - 1
src/views/five/index.vue

@@ -71,7 +71,11 @@
         </div>
         <el-col :span="24" class="two_2">
           <div class="list" v-for="(item, index) in list" :key="index">
-            <el-image class="image" :src="getUrl(item.file)" fit="cover"> </el-image>
+            <el-image class="image" :src="getUrl(item.file)" fit="cover">
+              <template v-slot:error>
+                <el-image class="image" :src="match_3" fit="fill" />
+              </template>
+            </el-image>
             <div class="name">{{ item.name || '暂无' }}</div>
             <div class="other">
               <div class="time">
@@ -92,6 +96,7 @@
 
 <script setup>
 // 图片引入
+import match_3 from '/images/match_3.jpg'
 import lists from '/images/bg-act-list.jpg'
 import time1 from '/images/time-dary.png'
 const $checkRes = inject('$checkRes')