zs há 1 ano atrás
commit
c287a32987
99 ficheiros alterados com 17010 adições e 0 exclusões
  1. 7 0
      .env.development
  2. 7 0
      .env.production
  3. 28 0
      .eslintrc.cjs
  4. 28 0
      .gitignore
  5. 8 0
      .prettierrc.json
  6. 8 0
      .vscode/extensions.json
  7. 46 0
      README.md
  8. 5 0
      env.d.ts
  9. 16 0
      index.html
  10. 9779 0
      package-lock.json
  11. 49 0
      package.json
  12. BIN
      public/favicon.ico
  13. 33 0
      src/App.vue
  14. BIN
      src/assets/achieve.png
  15. 0 0
      src/assets/base.css
  16. BIN
      src/assets/code.png
  17. BIN
      src/assets/demand.png
  18. BIN
      src/assets/detail.png
  19. BIN
      src/assets/hdbg.png
  20. BIN
      src/assets/hdbg2.png
  21. 95 0
      src/assets/icon/iconfont.css
  22. 1 0
      src/assets/icon/iconfont.js
  23. 149 0
      src/assets/icon/iconfont.json
  24. BIN
      src/assets/icon/iconfont.ttf
  25. BIN
      src/assets/icon/iconfont.woff
  26. BIN
      src/assets/icon/iconfont.woff2
  27. BIN
      src/assets/kf.png
  28. BIN
      src/assets/login.jpeg
  29. BIN
      src/assets/loginbg.jpg
  30. BIN
      src/assets/logo.png
  31. 1 0
      src/assets/logo.svg
  32. 19 0
      src/assets/main.css
  33. BIN
      src/assets/menu_1.png
  34. BIN
      src/assets/menu_2.png
  35. BIN
      src/assets/menu_3.png
  36. BIN
      src/assets/menu_4.png
  37. BIN
      src/assets/menu_5.png
  38. BIN
      src/assets/menu_6.png
  39. BIN
      src/assets/menu_7.png
  40. BIN
      src/assets/menubg.png
  41. BIN
      src/assets/one.png
  42. BIN
      src/assets/service1.png
  43. BIN
      src/assets/service10.png
  44. BIN
      src/assets/service2.png
  45. BIN
      src/assets/service3.png
  46. BIN
      src/assets/service4.png
  47. BIN
      src/assets/service5.png
  48. BIN
      src/assets/service6.png
  49. BIN
      src/assets/service7.png
  50. BIN
      src/assets/service8.png
  51. BIN
      src/assets/service9.png
  52. BIN
      src/assets/service_1.jpg
  53. BIN
      src/assets/service_2.jpg
  54. BIN
      src/assets/service_3.jpg
  55. BIN
      src/assets/service_4.jpg
  56. BIN
      src/assets/service_5.jpg
  57. BIN
      src/assets/thr.png
  58. BIN
      src/assets/two.png
  59. BIN
      src/assets/unit.png
  60. BIN
      src/assets/video.mp4
  61. BIN
      src/assets/video_1.png
  62. BIN
      src/assets/video_2.jpg
  63. BIN
      src/assets/videobg.png
  64. 176 0
      src/components/head.vue
  65. 9 0
      src/components/index.ts
  66. 169 0
      src/components/search.vue
  67. 187 0
      src/components/video.vue
  68. 16 0
      src/layout/site.ts
  69. 49 0
      src/main.ts
  70. 102 0
      src/router/index.ts
  71. 12 0
      src/stores/counter.ts
  72. 150 0
      src/util/axios-wrapper.ts
  73. 29 0
      src/util/types.util.ts
  74. 228 0
      src/views/achieve/detail.vue
  75. 214 0
      src/views/achieve/index.vue
  76. 208 0
      src/views/activity/index.vue
  77. 152 0
      src/views/activity/new.vue
  78. 93 0
      src/views/activity/video.vue
  79. 223 0
      src/views/demand/detail.vue
  80. 228 0
      src/views/demand/index.vue
  81. 254 0
      src/views/home/components/achievement.vue
  82. 605 0
      src/views/home/components/activity.vue
  83. 253 0
      src/views/home/components/demand.vue
  84. 358 0
      src/views/home/components/service.vue
  85. 601 0
      src/views/home/components/transaction.vue
  86. 56 0
      src/views/home/index.vue
  87. 246 0
      src/views/login/index.vue
  88. 102 0
      src/views/policy/detail.vue
  89. 241 0
      src/views/policy/index.vue
  90. 401 0
      src/views/register/index.vue
  91. 246 0
      src/views/service/detail.vue
  92. 235 0
      src/views/service/index.vue
  93. 266 0
      src/views/trade/detail.vue
  94. 280 0
      src/views/trade/one.vue
  95. 238 0
      src/views/trade/two.vue
  96. 14 0
      tsconfig.app.json
  97. 37 0
      tsconfig.json
  98. 18 0
      tsconfig.node.json
  99. 35 0
      vite.config.ts

+ 7 - 0
.env.development

@@ -0,0 +1,7 @@
+VITE_BASE_URL = "/"
+VITE_OUT_DIR = "fieldweb"
+VITE_REQUEST_BASE = ''
+VITE_APP_HOST="https://broadcast.waityou24.cn"
+VITE_APP_PAGE_SIZE=12
+VITE_APP_ROUTER="web"
+VITE_APP_ENV = 'development'

+ 7 - 0
.env.production

@@ -0,0 +1,7 @@
+VITE_BASE_URL = "/"
+VITE_OUT_DIR = "fieldweb"
+VITE_REQUEST_BASE = ''
+VITE_APP_HOST="https://broadcast.waityou24.cn"
+VITE_APP_PAGE_SIZE=12
+VITE_APP_ROUTER="web"
+VITE_APP_ENV = 'production'

+ 28 - 0
.eslintrc.cjs

@@ -0,0 +1,28 @@
+/* eslint-env node */
+require('@rushstack/eslint-patch/modern-module-resolution');
+
+module.exports = {
+  root: true,
+  extends: ['plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-typescript', '@vue/eslint-config-prettier'],
+  parserOptions: {
+    ecmaVersion: 'latest'
+  },
+  rules: {
+    'vue/multi-word-component-names': 0,
+    'max-len': [
+      'warn',
+      {
+        code: 10000
+      }
+    ],
+    'prettier/prettier': [
+      'warn',
+      {
+        singleQuote: true,
+        bracketSpacing: true,
+        jsxBracketSameLine: true,
+        printWidth: 160
+      }
+    ]
+  }
+};

+ 28 - 0
.gitignore

@@ -0,0 +1,28 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+.DS_Store
+dist
+dist-ssr
+coverage
+*.local
+
+/cypress/videos/
+/cypress/screenshots/
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 8 - 0
.prettierrc.json

@@ -0,0 +1,8 @@
+{
+  "$schema": "https://json.schemastore.org/prettierrc",
+  "semi": true,
+  "tabWidth": 2,
+  "singleQuote": true,
+  "printWidth": 100,
+  "trailingComma": "none"
+}

+ 8 - 0
.vscode/extensions.json

@@ -0,0 +1,8 @@
+{
+  "recommendations": [
+    "Vue.volar",
+    "Vue.vscode-typescript-vue-plugin",
+    "dbaeumer.vscode-eslint",
+    "esbenp.prettier-vscode"
+  ]
+}

+ 46 - 0
README.md

@@ -0,0 +1,46 @@
+# field_web
+
+This template should help get you started developing with Vue 3 in Vite.
+
+## Recommended IDE Setup
+
+[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
+
+## Type Support for `.vue` Imports in TS
+
+TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
+
+If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
+
+1. Disable the built-in TypeScript Extension
+    1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
+    2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
+2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
+
+## Customize configuration
+
+See [Vite Configuration Reference](https://vitejs.dev/config/).
+
+## Project Setup
+
+```sh
+npm install
+```
+
+### Compile and Hot-Reload for Development
+
+```sh
+npm run dev
+```
+
+### Type-Check, Compile and Minify for Production
+
+```sh
+npm run build
+```
+
+### Lint with [ESLint](https://eslint.org/)
+
+```sh
+npm run lint
+```

+ 5 - 0
env.d.ts

@@ -0,0 +1,5 @@
+/// <reference types="vite/client" />
+interface ImportMetaEnv {
+  VITE_BASE_URL: string;
+  VITE_OUT_DIR: string;
+}

+ 16 - 0
index.html

@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <link rel="icon" href="/favicon.ico">
+  <meta name="viewport" content="width=device-width,user-scalable=yes,initial-scale=0.1">
+  <title>加载中...</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="module" src="/src/main.ts"></script>
+</body>
+
+</html>

Diff do ficheiro suprimidas por serem muito extensas
+ 9779 - 0
package-lock.json


+ 49 - 0
package.json

@@ -0,0 +1,49 @@
+{
+  "name": "field_web",
+  "version": "0.0.0",
+  "private": true,
+  "scripts": {
+    "dev": "vite",
+    "build": "run-p type-check \"build-only {@}\" --",
+    "preview": "vite preview",
+    "build-only": "vite build",
+    "type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
+    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
+    "format": "prettier --write src/"
+  },
+  "dependencies": {
+    "@element-plus/icons-vue": "^2.1.0",
+    "@wangeditor/editor": "^5.1.23",
+    "@wangeditor/editor-for-vue": "^5.1.12",
+    "animate.css": "^4.1.1",
+    "ant-design-vue": "^4.0.8",
+    "axios": "^1.4.0",
+    "echarts": "^5.4.2",
+    "element-plus": "^2.3.4",
+    "lodash": "^4.17.21",
+    "moment": "^2.29.4",
+    "naf-core": "^0.1.2",
+    "pinia": "^2.0.36",
+    "vue": "^3.3.2",
+    "vue-router": "^4.2.0",
+    "vue3-seamless-scroll": "^2.0.1",
+    "vuex": "^4.1.0"
+  },
+  "devDependencies": {
+    "@rushstack/eslint-patch": "^1.2.0",
+    "@types/node": "^18.14.2",
+    "@vitejs/plugin-vue": "^4.0.0",
+    "@vue/eslint-config-prettier": "^7.1.0",
+    "@vue/eslint-config-typescript": "^11.0.2",
+    "@vue/tsconfig": "^0.1.3",
+    "eslint": "^8.34.0",
+    "eslint-plugin-vue": "^9.9.0",
+    "npm-run-all": "^4.1.5",
+    "prettier": "^2.8.4",
+    "sass": "^1.62.1",
+    "sass-loader": "^13.2.2",
+    "typescript": "~4.8.4",
+    "vite": "^4.1.4",
+    "vue-tsc": "^1.2.0"
+  }
+}

BIN
public/favicon.ico


+ 33 - 0
src/App.vue

@@ -0,0 +1,33 @@
+<script setup lang="ts">
+//注意这里引用中文包的路径与上方不同,这里不需要做其他操作,直接复制代码即可
+import zhCN from 'ant-design-vue/es/locale/zh_CN';
+import dayjs from 'dayjs';
+import 'dayjs/locale/zh-cn';
+dayjs.locale('zh-cn');
+</script>
+
+<template>
+  <a-config-provider :locale="zhCN">
+    <RouterView />
+  </a-config-provider>
+</template>
+<style>
+body {
+  margin: 0;
+}
+.w_1200 {
+  width: 1200px;
+  margin: 0 auto;
+}
+
+p {
+  margin: 0;
+  padding: 0;
+}
+
+.textOver {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+</style>

BIN
src/assets/achieve.png


+ 0 - 0
src/assets/base.css


BIN
src/assets/code.png


BIN
src/assets/demand.png


BIN
src/assets/detail.png


BIN
src/assets/hdbg.png


BIN
src/assets/hdbg2.png


+ 95 - 0
src/assets/icon/iconfont.css

@@ -0,0 +1,95 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 4079354 */
+  src: url('iconfont.woff2?t=1685509924120') format('woff2'),
+       url('iconfont.woff?t=1685509924120') format('woff'),
+       url('iconfont.ttf?t=1685509924120') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-dengji:before {
+  content: "\e610";
+}
+
+.icon-shenhezhong:before {
+  content: "\e682";
+}
+
+.icon-dkw_shenheweitongguo:before {
+  content: "\e604";
+}
+
+.icon-shenhetongguo:before {
+  content: "\e668";
+}
+
+.icon-hearts-fill:before {
+  content: "\e702";
+}
+
+.icon-xiaoyouhui:before {
+  content: "\e601";
+}
+
+.icon-youjiantou-copy:before {
+  content: "\e654";
+}
+
+.icon-6ruxueshijian:before {
+  content: "\e88a";
+}
+
+.icon-zhuanyezhuanyeke:before {
+  content: "\e6a1";
+}
+
+.icon-commpany:before {
+  content: "\e612";
+}
+
+.icon-zhiwuguanli:before {
+  content: "\e60f";
+}
+
+.icon-guanzhu:before {
+  content: "\e611";
+}
+
+.icon-guanzhu1:before {
+  content: "\e600";
+}
+
+.icon-edu-line:before {
+  content: "\e63a";
+}
+
+.icon-gender:before {
+  content: "\e63e";
+}
+
+.icon-xingming:before {
+  content: "\e640";
+}
+
+.icon-jibenxinxi:before {
+  content: "\e67c";
+}
+
+.icon-iocn_be_concern:before {
+  content: "\e607";
+}
+
+.icon-tupianshangchuan:before {
+  content: "\e639";
+}
+
+.icon-wodeguanzhu:before {
+  content: "\e8bc";
+}
+

Diff do ficheiro suprimidas por serem muito extensas
+ 1 - 0
src/assets/icon/iconfont.js


+ 149 - 0
src/assets/icon/iconfont.json

@@ -0,0 +1,149 @@
+{
+  "id": "4079354",
+  "name": "校友信息登记",
+  "font_family": "iconfont",
+  "css_prefix_text": "icon-",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "1327399",
+      "name": "登记",
+      "font_class": "dengji",
+      "unicode": "e610",
+      "unicode_decimal": 58896
+    },
+    {
+      "icon_id": "1480896",
+      "name": "审核中",
+      "font_class": "shenhezhong",
+      "unicode": "e682",
+      "unicode_decimal": 59010
+    },
+    {
+      "icon_id": "2078809",
+      "name": "dkw_审核未通过",
+      "font_class": "dkw_shenheweitongguo",
+      "unicode": "e604",
+      "unicode_decimal": 58884
+    },
+    {
+      "icon_id": "10087856",
+      "name": "审核通过",
+      "font_class": "shenhetongguo",
+      "unicode": "e668",
+      "unicode_decimal": 58984
+    },
+    {
+      "icon_id": "35094512",
+      "name": "关心",
+      "font_class": "hearts-fill",
+      "unicode": "e702",
+      "unicode_decimal": 59138
+    },
+    {
+      "icon_id": "2726796",
+      "name": "校友会",
+      "font_class": "xiaoyouhui",
+      "unicode": "e601",
+      "unicode_decimal": 58881
+    },
+    {
+      "icon_id": "10515596",
+      "name": "右箭头",
+      "font_class": "youjiantou-copy",
+      "unicode": "e654",
+      "unicode_decimal": 58964
+    },
+    {
+      "icon_id": "518145",
+      "name": "6 入学时间",
+      "font_class": "6ruxueshijian",
+      "unicode": "e88a",
+      "unicode_decimal": 59530
+    },
+    {
+      "icon_id": "16365912",
+      "name": "专业 专业课",
+      "font_class": "zhuanyezhuanyeke",
+      "unicode": "e6a1",
+      "unicode_decimal": 59041
+    },
+    {
+      "icon_id": "376346",
+      "name": "工作单位",
+      "font_class": "commpany",
+      "unicode": "e612",
+      "unicode_decimal": 58898
+    },
+    {
+      "icon_id": "11672365",
+      "name": "职务管理",
+      "font_class": "zhiwuguanli",
+      "unicode": "e60f",
+      "unicode_decimal": 58895
+    },
+    {
+      "icon_id": "8712978",
+      "name": "关注",
+      "font_class": "guanzhu",
+      "unicode": "e611",
+      "unicode_decimal": 58897
+    },
+    {
+      "icon_id": "9714399",
+      "name": "关注",
+      "font_class": "guanzhu1",
+      "unicode": "e600",
+      "unicode_decimal": 58880
+    },
+    {
+      "icon_id": "6119296",
+      "name": "学历",
+      "font_class": "edu-line",
+      "unicode": "e63a",
+      "unicode_decimal": 58938
+    },
+    {
+      "icon_id": "6183156",
+      "name": "性别",
+      "font_class": "gender",
+      "unicode": "e63e",
+      "unicode_decimal": 58942
+    },
+    {
+      "icon_id": "20764666",
+      "name": "姓名",
+      "font_class": "xingming",
+      "unicode": "e640",
+      "unicode_decimal": 58944
+    },
+    {
+      "icon_id": "6856906",
+      "name": "基本信息",
+      "font_class": "jibenxinxi",
+      "unicode": "e67c",
+      "unicode_decimal": 59004
+    },
+    {
+      "icon_id": "1048854",
+      "name": "被关注",
+      "font_class": "iocn_be_concern",
+      "unicode": "e607",
+      "unicode_decimal": 58887
+    },
+    {
+      "icon_id": "2506206",
+      "name": "图片上传",
+      "font_class": "tupianshangchuan",
+      "unicode": "e639",
+      "unicode_decimal": 58937
+    },
+    {
+      "icon_id": "11372718",
+      "name": "我的关注",
+      "font_class": "wodeguanzhu",
+      "unicode": "e8bc",
+      "unicode_decimal": 59580
+    }
+  ]
+}

BIN
src/assets/icon/iconfont.ttf


BIN
src/assets/icon/iconfont.woff


BIN
src/assets/icon/iconfont.woff2


BIN
src/assets/kf.png


BIN
src/assets/login.jpeg


BIN
src/assets/loginbg.jpg


BIN
src/assets/logo.png


+ 1 - 0
src/assets/logo.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

+ 19 - 0
src/assets/main.css

@@ -0,0 +1,19 @@
+body {
+  margin: 0;
+}
+
+.w_1200 {
+  width: 1200px;
+  margin: 0 auto;
+}
+
+p {
+  margin: 0;
+  padding: 0;
+}
+
+.textOver {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}

BIN
src/assets/menu_1.png


BIN
src/assets/menu_2.png


BIN
src/assets/menu_3.png


BIN
src/assets/menu_4.png


BIN
src/assets/menu_5.png


BIN
src/assets/menu_6.png


BIN
src/assets/menu_7.png


BIN
src/assets/menubg.png


BIN
src/assets/one.png


BIN
src/assets/service1.png


BIN
src/assets/service10.png


BIN
src/assets/service2.png


BIN
src/assets/service3.png


BIN
src/assets/service4.png


BIN
src/assets/service5.png


BIN
src/assets/service6.png


BIN
src/assets/service7.png


BIN
src/assets/service8.png


BIN
src/assets/service9.png


BIN
src/assets/service_1.jpg


BIN
src/assets/service_2.jpg


BIN
src/assets/service_3.jpg


BIN
src/assets/service_4.jpg


BIN
src/assets/service_5.jpg


BIN
src/assets/thr.png


BIN
src/assets/two.png


BIN
src/assets/unit.png


BIN
src/assets/video.mp4


BIN
src/assets/video_1.png


BIN
src/assets/video_2.jpg


BIN
src/assets/videobg.png


+ 176 - 0
src/components/head.vue

@@ -0,0 +1,176 @@
+<template>
+  <div id="head">
+    <el-row>
+      <el-col :span="24" class="head">
+        <div class="w_1200">
+          <el-row :gutter="20" class="one">
+            <el-row :gutter="10" class="left">
+              <el-col :span="4">
+                <el-image class="image" :src="siteInfo.logoUrl" fit="fill" />
+              </el-col>
+              <el-col :span="20">
+                <div class="title">{{ siteInfo.zhTitle }}</div>
+                <div class="English">{{ siteInfo.zhEnglish }}</div>
+              </el-col>
+            </el-row>
+            <el-col :span="8" class="right">
+              <a-input-search v-model:value="input" placeholder="请输入您想搜索的内容" enter-button @search="onSearch" />
+            </el-col>
+            <el-col :span="4" class="button">
+              <a-space wrap>
+                <a-button type="primary">登录</a-button>
+                <a-button>注册</a-button>
+              </a-space>
+            </el-col>
+          </el-row>
+        </div>
+        <el-col :span="24" class="two">
+          <a-menu @select="selectMenu" v-model:selectedKeys="current" mode="horizontal" theme="dark" :items="menuList" />
+        </el-col>
+        <el-col :span="24" class="thr">
+          <slot name="info"></slot>
+        </el-col>
+        <div class="foot">
+          <div class="w_1200 footflex">
+            <el-image class="image" src="/src/assets/unit.png" fit="fill" />
+            <el-col :span="12" class="foot_1">
+              <div class="footTitle"><span>业务洽谈:0431-81165166</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>企业邮箱:jlpstm@126.com</span></div>
+              <div class="footTitle">地 址:长春朝阳区前进大街1244号(吉林省科技厅科研园)</div>
+              <div class="footTitle">版权所有:Copyright©2007-2023 吉林省创新指导中心 │ 吉ICP备14005689号</div>
+              <div class="footTitle">技术支持:长春市福瑞科技有限公司</div>
+            </el-col>
+            <el-col :span="3" class="foot_2">
+              <div class="footTop">关于我们</div>
+              <div class="footTitle footflex1"><span class="footSpan">关于我们</span> <span class="footSpan">意见反馈</span></div>
+              <div class="footTitle footflex1"><span class="footSpan">联系我们</span> <span class="footSpan">法律条款</span></div>
+            </el-col>
+            <el-col :span="4" class="foot_3 footflex">
+              <el-image class="image" src="/src/assets/code.png" fit="fill" />
+              <el-image class="image" src="/src/assets/code.png" fit="fill" />
+            </el-col>
+          </div>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+<script setup lang="ts">
+import type { Ref } from 'vue';
+import { ref } from 'vue';
+import { siteInfo } from '@/layout/site';
+import { MenuProps } from 'ant-design-vue';
+const current = ref<string[]>(['tran']);
+const menuList = ref<MenuProps['items']>([
+  {
+    key: 'tran',
+    label: '交易大厅',
+    title: '交易大厅'
+  },
+  {
+    key: 'achieve',
+    label: '成果大厅',
+    title: '成果大厅'
+  },
+  {
+    key: 'demand',
+    label: '需求大厅',
+    title: '需求大厅'
+  },
+  {
+    key: 'service',
+    label: '服务大厅',
+    title: '服务大厅'
+  },
+  {
+    key: 'activity',
+    label: '活动大厅',
+    title: '活动大厅'
+  }
+]);
+const input: Ref<any> = ref('');
+// 选择菜单
+const emit = defineEmits(['selectMenu']);
+const selectMenu = (item) => {
+  emit('selectMenu', item);
+};
+// 查询
+const onSearch = (searchValue: string) => {
+  console.log('use value', searchValue);
+  console.log('or use this.value', input.value);
+};
+</script>
+<style scoped lang="scss">
+.head {
+  .one {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 20px 0;
+    .left {
+      .title {
+        font-family: Helvetica, Arial, 'Hiragino Sans GB', 'Microsoft Yahei', '微软雅黑', STHeiti, '华文细黑', sans-serif;
+        font-size: 28px;
+        color: #121834;
+        line-height: 32px;
+        font-weight: 500;
+        padding-bottom: 8px;
+      }
+      .English {
+        font-size: 15px;
+      }
+    }
+  }
+  .two {
+    display: flex;
+    justify-content: center;
+    width: 100%;
+    padding: 10px 0;
+    background: #001529;
+    position: sticky;
+    top: 0;
+    width: 100%;
+    z-index: 99999;
+  }
+}
+.foot {
+  padding: 5px 0;
+  font-size: 13px;
+  background-color: #2e3546;
+  color: #f0f2f5;
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
+    'Segoe UI Symbol', 'Noto Color Emoji';
+  font-variant: tabular-nums;
+  line-height: 1.5715;
+  font-feature-settings: 'tnum', 'tnum';
+
+  .image {
+    width: 78px;
+    height: 78px;
+  }
+
+  .footTitle {
+    margin: 5px 0 0 0;
+
+    .footSpan {
+      margin-bottom: 3px;
+    }
+  }
+
+  .footTop {
+    font-size: 18px;
+    margin-bottom: 12px;
+  }
+}
+
+.footflex {
+  display: flex;
+  align-items: center;
+  justify-content: space-evenly;
+}
+
+.footflex1 {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+</style>

+ 9 - 0
src/components/index.ts

@@ -0,0 +1,9 @@
+import type { Component } from 'vue';
+import cVideo from './video.vue';
+import cHead from './head.vue';
+import cSearch from './search.vue';
+const components: {
+  [propName: string]: Component;
+} = { cHead, cVideo, cSearch };
+
+export default components;

+ 169 - 0
src/components/search.vue

@@ -0,0 +1,169 @@
+<template>
+  <div id="search">
+    <el-row>
+      <el-col :span="24" class="title" v-if="is_title">
+        <el-col :span="24" class="title_1">
+          <span>{{ title || $route.meta.title }}</span>
+          <span>{{ tip }}</span>
+        </el-col>
+        <el-col :span="24" class="title_2">
+          <span>{{ remark }}</span>
+        </el-col>
+      </el-col>
+      <el-col :span="24" class="search" v-if="is_search">
+        <el-form ref="formRef" :model="form" label-width="auto">
+          <el-col :span="24" class="form">
+            <template v-for="(item, index) in fields">
+              <el-col :span="8" class="form_1" :key="'form-field-' + index" v-if="item.isSearch == true">
+                <el-form-item :label="getField('label', item)" :prop="item.model">
+                  <template v-if="!item.custom">
+                    <template v-if="item.type === 'select'">
+                      <el-select v-model="form[item.model]" v-bind="item.options" filterable clearable @change="dataChange(item.model)">
+                        <slot :name="item.model" v-bind="{ item }"></slot>
+                      </el-select>
+                    </template>
+                    <template v-else>
+                      <el-input
+                        v-model="form[item.model]"
+                        :type="getField('type', item)"
+                        :placeholder="getField('place', item)"
+                        clearable
+                        v-bind="item.options"
+                        @change="dataChange(item.model)"
+                      ></el-input>
+                    </template>
+                  </template>
+                  <template v-else>
+                    <slot :name="item.model" v-bind="{ item }"></slot>
+                    <!-- <el-input v-model="form[item.model]" clearable :placeholder="`输入${item.label}`"></el-input> -->
+                  </template>
+                </el-form-item>
+              </el-col>
+            </template>
+          </el-col>
+          <el-col :span="24" class="btn">
+            <el-button type="primary" @click="toSubmit()">查询</el-button>
+            <el-button type="danger" @click="toReset()">重置</el-button>
+          </el-col>
+        </el-form>
+      </el-col>
+      <el-col :span="24" class="back" v-if="is_back">
+        <el-button type="primary" @click="toBack()">返回</el-button>
+      </el-col>
+      <el-col :span="24" class="slot"><slot name="isslot"></slot></el-col>
+    </el-row>
+  </div>
+</template>
+<script lang="ts" setup>
+import { ref, toRefs } from 'vue';
+import type { Ref } from 'vue';
+import _ from 'lodash';
+interface fieldsItem {
+  model: string;
+  type: string;
+  // readonly: string;
+  options: object;
+  custom: string;
+  // required: string;
+  // limit: number | undefined;
+  isSearch: boolean;
+}
+const props = defineProps({
+  is_title: { type: Boolean, default: true },
+  is_search: { type: Boolean, default: false },
+  is_back: { type: Boolean, default: false },
+  fields: { type: Array<fieldsItem> },
+  title: { type: String },
+  tip: { type: String },
+  remark: { type: String }
+});
+const { is_title } = toRefs(props);
+const { is_search } = toRefs(props);
+const { is_back } = toRefs(props);
+const { fields } = toRefs(props);
+const { title } = toRefs(props);
+const { tip } = toRefs(props);
+const { remark } = toRefs(props);
+
+let form: Ref<{}> = ref({});
+const emit = defineEmits(['search', 'toReset', 'toBack', 'dataChange']);
+const toSubmit = () => {
+  const obj = _.pickBy(form.value);
+  emit('search', { ...obj });
+};
+// 重置
+const toReset = () => {
+  form.value = {};
+  emit('search', form.value);
+};
+// 文字描述
+const getField = (item: any, data: any) => {
+  let res = _.get(data, item, null);
+  if (item === 'type') res = res === null ? `text` : res;
+  if (item === 'place') res = res === null ? `请输入${data.label}` : res;
+  if (item === 'required') res = res === null ? false : res;
+  if (item === `error`) res = res === null ? `${data.label}错误` : res;
+  return res;
+};
+// 获取输入值
+const dataChange = (model: string) => {
+  const value = form.value[model];
+  emit('dataChange', { model, value });
+};
+// 返回
+const toBack = () => {
+  emit('toBack');
+};
+</script>
+
+<style lang="scss" scoped>
+.title {
+  margin: 0 0 5px 0;
+  .title_1 {
+    margin: 0 0 5px 0;
+    span:first-child {
+      font-size: 20px;
+      font-weight: 700;
+      margin-right: 10px;
+    }
+    span:last-child {
+      font-size: 14px;
+      color: #979797;
+    }
+  }
+  .title_2 {
+    span {
+      color: #8baae7;
+      font-size: 14px;
+      margin-top: 10px;
+    }
+  }
+}
+.search {
+  margin: 0 0 10px 0;
+  .form {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    .form_1 {
+      padding: 0 0 0 10px;
+      .el-form-item {
+        float: left;
+        width: 100%;
+        margin: 0 0 10px 0;
+      }
+      .el-select {
+        width: 100%;
+      }
+    }
+  }
+
+  .btn {
+    text-align: right;
+  }
+}
+.back {
+  text-align: left;
+  margin: 0 0 10px 0;
+}
+</style>

+ 187 - 0
src/components/video.vue

@@ -0,0 +1,187 @@
+<script setup lang="ts">
+import { ref, onMounted } from 'vue';
+interface Props {
+  src: string; // 视频文件地址,支持网络地址 https 和相对地址
+  poster?: string; // 视频封面地址,支持网络地址 https 和相对地址
+  second?: number; // 在未设置封面时,自动截取视频第 second 秒对应帧作为视频封面
+  width?: number; // 视频播放器宽度,单位px
+  height?: number; // 视频播放器高度,单位px
+  autoplay?: boolean; // 视频就绪后是否马上播放,优先级高于preload
+  controls?: boolean; // 是否向用户显示控件,比如进度条,全屏等
+  loop?: boolean; // 视频播放完成后,是否循环播放
+  muted?: boolean; // 是否静音
+  preload?: 'auto' | 'metadata' | 'none'; // 是否在页面加载后载入视频,如果设置了autoplay属性,则preload将被忽略
+  showPlay?: boolean; // 播放暂停时是否显示播放器中间的暂停图标
+  fit?: 'none' | 'fill' | 'contain' | 'cover'; // video的poster默认图片和视频内容缩放规则
+}
+const props = withDefaults(defineProps<Props>(), {
+  src: '',
+  poster: '',
+  second: 0.5,
+  width: 1200,
+  height: 500,
+  /*
+    参考 MDN 自动播放指南:https://developer.mozilla.org/zh-CN/docs/Web/Media/Autoplay_guide
+    Autoplay 功能
+    据新政策,媒体内容将在满足以下至少一个的条件下自动播放:
+    1.音频被静音或其音量设置为 0
+    2.用户和网页已有交互行为(包括点击、触摸、按下某个键等等)
+    3.网站已被列入白名单;如果浏览器确定用户经常与媒体互动,这可能会自动发生,也可能通过首选项或其他用户界面功能手动发生
+    4.自动播放策略应用到<iframe>或者其文档上
+    autoplay:由于目前在最新版的Chrome浏览器(以及所有以Chromium为内核的浏览器)中,
+    已不再允许自动播放音频和视频。就算你为video或audio标签设置了autoplay属性也一样不能自动播放!
+    解决方法:设置视频 autoplay 时,视频必须设置为静音 muted: true 即可实现自动播放,
+    然后用户可以使用控制栏开启声音,类似某宝商品自动播放的宣传视频逻辑
+  */
+  autoplay: false,
+  controls: true,
+  loop: false,
+  muted: false,
+  /*
+    preload可选属性:
+    auto: 一旦页面加载,则开始加载视频;
+    metadata: 当页面加载后仅加载视频的元数据(例如长度),建议使用metadata,以便视频自动获取第一帧作为封面poster
+    none: 页面加载后不应加载视频
+  */
+  preload: 'auto',
+  showPlay: true,
+  /*
+    fit可选属性:
+    none: 保存原有内容,不进行缩放;
+    fill: 不保持原有比例,内容拉伸填充整个内容容器;
+    contain: 保存原有比例,内容以包含方式缩放;
+    cover: 保存原有比例,内容以覆盖方式缩放
+  */
+  fit: 'contain'
+});
+// 参考文档:https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/video
+const veoPoster = ref(props.poster);
+const originPlay = ref(true);
+const hidden = ref(false); // 是否隐藏播放器中间的播放按钮
+// 为模板引用标注类型
+const veo = ref();
+// const veo = ref<HTMLVideoElement | null>(null) // 声明一个同名的模板引用
+/*
+  loadeddata 事件在媒体当前播放位置的视频帧(通常是第一帧)加载完成后触发
+  preload为none时不会触发
+*/
+function getPoster() {
+  // 在未设置封面时,自动截取视频0.5s对应帧作为视频封面
+  // 由于不少视频第一帧为黑屏,故设置视频开始播放时间为0.5s,即取该时刻帧作为封面图
+  veo.value.currentTime = props.second;
+  // 创建canvas元素
+  const canvas = document.createElement('canvas');
+  const ctx = canvas.getContext('2d');
+  // canvas画图
+  canvas.width = veo.value.videoWidth;
+  canvas.height = veo.value.videoHeight;
+  ctx?.drawImage(veo.value, 0, 0, canvas.width, canvas.height);
+  // 把canvas转成base64编码格式
+  veoPoster.value = canvas.toDataURL('image/png');
+}
+function onPlay() {
+  if (originPlay.value) {
+    veo.value.currentTime = 0;
+    originPlay.value = false;
+  }
+  if (props.autoplay) {
+    veo.value?.pause();
+  } else {
+    hidden.value = true;
+    veo.value?.play();
+  }
+}
+function onPause() {
+  hidden.value = false;
+}
+function onPlaying() {
+  hidden.value = true;
+}
+onMounted(() => {
+  if (props.autoplay) {
+    hidden.value = true;
+    originPlay.value = false;
+  }
+  /*
+    自定义设置播放速度,经测试:
+    在vue2中需设置:this.$refs.veo.playbackRate = 2
+    在vue3中需设置:veo.value.defaultPlaybackRate = 2
+  */
+  // veo.value.defaultPlaybackRate = 2
+});
+</script>
+<template>
+  <div class="m-video" :class="{ 'u-video-hover': !hidden }" :style="`width: ${width}px; height: ${height}px;`">
+    <video
+      ref="veo"
+      :style="`object-fit: ${fit};`"
+      :src="src"
+      :poster="veoPoster"
+      :width="width"
+      :height="height"
+      :autoplay="autoplay"
+      :controls="!originPlay && controls"
+      :loop="loop"
+      :muted="autoplay || muted"
+      :preload="preload"
+      crossorigin="anonymous"
+      @loadeddata="poster ? () => false : getPoster()"
+      @pause="showPlay ? onPause() : () => false"
+      @playing="showPlay ? onPlaying() : () => false"
+      @click.prevent.once="onPlay"
+      v-bind="$attrs"
+    >
+      您的浏览器不支持video标签。
+    </video>
+    <span v-show="originPlay || showPlay" class="m-icon-play" :class="{ hidden: hidden }">
+      <svg class="u-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 34 34">
+        <path
+          d="M28.26,11.961L11.035,0.813C7.464-1.498,3,1.391,3,6.013v21.974c0,4.622,4.464,7.511,8.035,5.2L28.26,22.039
+          C31.913,19.675,31.913,14.325,28.26,11.961z"
+        ></path>
+      </svg>
+    </span>
+  </div>
+</template>
+<style lang="scss" scoped>
+.m-video {
+  display: inline-block;
+  position: relative;
+  background: #000;
+  cursor: pointer;
+  .m-icon-play {
+    display: inline-block;
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    left: 0;
+    margin: auto;
+    width: 80px;
+    height: 80px;
+    border-radius: 50%;
+    background: rgba(0, 0, 0, 0.7);
+    pointer-events: none;
+    opacity: 0.8;
+    transition: opacity 0.3s;
+    .u-svg {
+      display: inline-block;
+      fill: #fff;
+      width: 29px;
+      height: 34px;
+      margin-top: 23px;
+      margin-left: 27px;
+    }
+  }
+  .hidden {
+    opacity: 0;
+  }
+}
+.u-video-hover {
+  &:hover {
+    .m-icon-play {
+      opacity: 1;
+    }
+  }
+}
+</style>

+ 16 - 0
src/layout/site.ts

@@ -0,0 +1,16 @@
+// 网站基本设置
+export const siteInfo = {
+  display: false,
+  zhTitle: '吉林省重点领域技术转移平台',
+  zhEnglish: 'Jilin Province Key Field Technology Transfer Platform',
+  zhPhone: '400-469-1899',
+  logoUrl: '/src/assets/logo.png'
+};
+// 菜单设置
+export const menuList = [
+  { title: '交易大厅', route: '/', href: 'transaction', English: 'Technology Trading' },
+  { title: '成果大厅', route: '/', href: 'achievement', English: 'Technology Showcase' },
+  { title: '需求大厅', route: '/', href: 'demand', English: 'Cooperation Demand' },
+  { title: '服务大厅', route: '/', href: 'service', English: 'Services' },
+  { title: '活动大厅', route: '/', href: 'activity', English: 'Activities' }
+];

+ 49 - 0
src/main.ts

@@ -0,0 +1,49 @@
+import { createApp } from 'vue';
+import { createPinia } from 'pinia';
+import App from './App.vue';
+import router from './router';
+// 样式
+import '@/assets/main.css';
+// 动画
+import 'animate.css';
+// element
+import ElementPlus from 'element-plus';
+import 'element-plus/dist/index.css';
+import locale from 'element-plus/es/locale/lang/zh-cn';
+import * as ElementPlusIconsVue from '@element-plus/icons-vue';
+
+// 自动滚动
+import vue3SeamlessScroll from 'vue3-seamless-scroll';
+
+// 图标
+import '@/assets/icon/iconfont.css';
+
+// moment
+import moment from 'moment';
+
+// lodash
+import _ from 'lodash';
+
+import Antd from 'ant-design-vue';
+import 'ant-design-vue/dist/reset.css';
+
+// 组件
+import frameComponents from '@/components/index';
+const app = createApp(App);
+app.use(createPinia());
+app.use(router);
+app.use(vue3SeamlessScroll);
+app.use(ElementPlus, { locale });
+app.use(Antd);
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+  app.component(key, component);
+}
+app.config.globalProperties.$moment = moment;
+app.config.globalProperties._ = _;
+
+for (const componentItme in frameComponents) {
+  app.component(componentItme, frameComponents[componentItme]);
+}
+app.config.globalProperties.$limit = parseInt(import.meta.env.VITE_APP_PAGE_SIZE) || 12;
+
+app.mount('#app');

+ 102 - 0
src/router/index.ts

@@ -0,0 +1,102 @@
+import { createRouter, createWebHistory } from 'vue-router';
+const router = createRouter({
+  history: createWebHistory(import.meta.env.BASE_URL),
+  routes: [
+    {
+      path: '/',
+      redirect: '/home'
+    },
+    {
+      path: '/home',
+      name: 'home',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/home/index.vue')
+    },
+    {
+      path: '/login',
+      name: 'login',
+      meta: { title: '吉林省重点领域技术转移平台-用户登录' },
+      component: () => import('@/views/login/index.vue')
+    },
+    {
+      path: '/register',
+      name: 'register',
+      meta: { title: '吉林省重点领域技术转移平台-用户注册' },
+      component: () => import('@/views/register/index.vue')
+    },
+    {
+      path: '/trade/one',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/trade/one.vue')
+    },
+    {
+      path: '/trade/two',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/trade/two.vue')
+    },
+    {
+      path: '/trade/detail',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/trade/detail.vue')
+    },
+    {
+      path: '/achieve',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/achieve/index.vue')
+    },
+    {
+      path: '/achieve/detail',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/achieve/detail.vue')
+    },
+    {
+      path: '/activity',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/activity/index.vue')
+    },
+    {
+      path: '/activity/new',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/activity/new.vue')
+    },
+    {
+      path: '/activity/video',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/activity/video.vue')
+    },
+    {
+      path: '/demand',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/demand/index.vue')
+    },
+    {
+      path: '/demand/detail',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/demand/detail.vue')
+    },
+    {
+      path: '/service',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/service/index.vue')
+    },
+    {
+      path: '/service/detail',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/service/detail.vue')
+    },
+    {
+      path: '/policy',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/policy/index.vue')
+    },
+    {
+      path: '/policy/detail',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/policy/detail.vue')
+    }
+  ]
+});
+router.beforeEach(async (to) => {
+  document.title = `${to.meta.title} `;
+});
+export default router;

+ 12 - 0
src/stores/counter.ts

@@ -0,0 +1,12 @@
+import { ref, computed } from 'vue'
+import { defineStore } from 'pinia'
+
+export const useCounterStore = defineStore('counter', () => {
+  const count = ref(0)
+  const doubleCount = computed(() => count.value * 2)
+  function increment() {
+    count.value++
+  }
+
+  return { count, doubleCount, increment }
+})

+ 150 - 0
src/util/axios-wrapper.ts

@@ -0,0 +1,150 @@
+/* eslint-disable no-console */
+/* eslint-disable no-param-reassign */
+
+import _ from 'lodash';
+import Axios from 'axios';
+import { Util, Error } from 'naf-core';
+// import { Indicator } from 'mint-ui';
+import type { IOptionsType, IQueryType, IRequestResult } from './types.util';
+
+const { trimData, isNullOrUndefined } = Util;
+const { ErrorCode } = Error;
+
+let currentRequests = 0;
+
+// // 参数类型设置
+// type valueType = string | number | object | boolean | Array<any>;
+// type queryType = string | number | boolean;
+
+// export interface IQueryType {
+//   [props: string]: queryType;
+// }
+// export interface IOptionsType {
+//   [props: string]: valueType;
+// }
+
+// export interface IRequestResult {
+//   errcode: string | number;
+//   errmsg: string | number;
+//   details?: string;
+//   [props: string]: any;
+// }
+
+export class AxiosWrapper {
+  constructor({ baseUrl = import.meta.env.VITE_REQUEST_BASE, unwrap = true } = {}) {
+    this.baseUrl = baseUrl;
+    this.unwrap = unwrap;
+  }
+  baseUrl: string;
+  unwrap: boolean;
+
+  // 替换uri中的参数变量
+  static merge(uri: string, query: IQueryType) {
+    if (!uri.includes(':')) {
+      return uri;
+    }
+    const keys = [];
+    const regexp = /\/:([a-z0-9_]+)/gi;
+    let res;
+    // eslint-disable-next-line no-cond-assign
+    while ((res = regexp.exec(uri)) != null) {
+      keys.push(res[1]);
+    }
+    keys.forEach((key) => {
+      const val = _.get(query, key);
+      if (!isNullOrUndefined(val)) {
+        uri = uri.replace(`:${key}`, `${val}`);
+      }
+    });
+    return uri;
+  }
+
+  $get(uri: string, query?: IQueryType, options?: IOptionsType) {
+    return this.$request(uri, undefined, query, options);
+  }
+
+  $post(uri: string, data: object = {}, query?: IQueryType, options?: IOptionsType) {
+    return this.$request(uri, data, query, options);
+  }
+  $delete(uri: string, data: object = {}, query?: IQueryType, options: IOptionsType = {}) {
+    options = { ...options, method: 'delete' };
+    return this.$request(uri, data, query, options);
+  }
+  async $request(uri: string, data?: object, query?: IQueryType, options?: IOptionsType) {
+    if (query && _.isObject(query)) {
+      const keys = Object.keys(query);
+      for (const key of keys) {
+        const val = _.get(query, key);
+        if (val === '') {
+          delete query[key];
+        }
+      }
+    }
+    if (_.isObject(query) && _.isObject(options)) {
+      options = { ...options, params: query, method: 'get' };
+    } else if (_.isObject(query) && !query.params) {
+      options = { params: query };
+    } else if (_.isObject(query) && query.params) {
+      options = query;
+    }
+    if (!options) options = {};
+    if (options.params) options.params = trimData(options.params, null, null);
+    const params = _.get(options, 'params');
+    const url = AxiosWrapper.merge(uri, params as IQueryType);
+    currentRequests += 1;
+    // Indicator.open({
+    //   spinnerType: 'fading-circle',
+    // });
+    try {
+      let returnData: any;
+      const axios = Axios.create({
+        baseURL: this.baseUrl
+      });
+      // if (util.token && util.token !== null) axios.defaults.headers.common.Authorization = util.token;
+      const token = localStorage.getItem('token');
+      const apiToken = localStorage.getItem('apiToken');
+      if (token) axios.defaults.headers.common['token'] = token;
+      if (apiToken) axios.defaults.headers.common['api-token'] = apiToken;
+      const res = await axios.request({
+        method: isNullOrUndefined(data) ? 'get' : 'post',
+        url,
+        data,
+        responseType: 'json',
+        ...options
+      });
+      const returnRes: IRequestResult = res.data;
+      const { errcode, errmsg, details } = returnRes;
+      if (errcode) {
+        console.warn(`[${uri}] fail: ${errcode}-${errmsg} ${details}`);
+        return returnRes;
+      }
+      // unwrap data
+      if (this.unwrap) {
+        returnData = returnRes;
+      }
+      // 处理apiToken
+      const { apiToken: at, ...others } = returnData;
+      if (at) localStorage.setItem('apiToken', at);
+      return others;
+    } catch (err: any) {
+      let errmsg = '接口请求失败,请稍后重试';
+      if (err.response) {
+        const { status } = err.response;
+        if (status === 401) errmsg = '用户认证失败,请重新登录';
+        if (status === 403) errmsg = '当前用户不允许执行该操作';
+      }
+      console.error(
+        `[AxiosWrapper] 接口请求失败: ${err.config && err.config.url} - 
+        ${err.message}`
+      );
+      return { errcode: ErrorCode.SERVICE_FAULT, errmsg, details: err.message };
+    } finally {
+      /* eslint-disable */
+      currentRequests -= 1;
+      if (currentRequests <= 0) {
+        currentRequests = 0;
+        // Indicator.close();
+      }
+    }
+  }
+}

+ 29 - 0
src/util/types.util.ts

@@ -0,0 +1,29 @@
+// 参数类型设置
+type valueType = string | number | Object | boolean | Array<any>;
+type queryType = string | number | boolean;
+
+export interface IQueryType {
+  [props: string]: queryType;
+}
+export interface IOptionsType {
+  [props: string]: valueType;
+}
+
+export interface IRequestResult {
+  errcode: string | number;
+  errmsg: string | number;
+  details?: string;
+  [props: string]: any;
+}
+export interface IQueryResult {
+  errcode?: string | number;
+  errmsg?: string | number;
+  data: valueType;
+  total: number;
+}
+
+export interface IQueryParams {
+  skip?: number;
+  limit?: number;
+  [props: string]: any;
+}

+ 228 - 0
src/views/achieve/detail.vue

@@ -0,0 +1,228 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <cHead>
+          <template v-slot:info>
+            <div class="w_1200">
+              <el-col :span="24" class="one">
+                <el-row :span="24" class="one_1">
+                  <el-col :span="20" class="title">{{ info.title || '暂无标题' }}</el-col>
+                  <el-col :span="4" class="file">
+                    <el-icon>
+                      <Download />
+                    </el-icon>
+                    附件下载
+                  </el-col>
+                </el-row>
+                <el-row :span="24" class="one_2"> 普通许可 </el-row>
+              </el-col>
+              <el-col :span="24" class="two">
+                <a-descriptions bordered title="简介">
+                  <a-descriptions-item label="行业分类">行业分类</a-descriptions-item>
+                  <a-descriptions-item label="成果属性">成果属性</a-descriptions-item>
+                  <a-descriptions-item label="出让方式">出让方式</a-descriptions-item>
+                  <a-descriptions-item label="成熟度">成熟度</a-descriptions-item>
+                  <a-descriptions-item label="技术分类">技术分类</a-descriptions-item>
+                  <a-descriptions-item label="成果地区">成果地区</a-descriptions-item>
+                  <a-descriptions-item label="发布时间">发布时间</a-descriptions-item>
+                </a-descriptions>
+              </el-col>
+              <el-col :span="24" class="thr">
+                <el-col :span="24" class="thr_1">单位信息</el-col>
+                <el-row :span="24" class="thr_2">
+                  <el-col :span="17" class="left">
+                    <el-col :span="24" class="name">
+                      {{ info.unit || '暂无' }}
+                    </el-col>
+                    <el-col :span="24" class="other"> <span>联系人</span>{{ info.unit || '暂无' }} </el-col>
+                  </el-col>
+                  <el-col :span="4" class="right">
+                    <a-button type="primary">
+                      <template #icon>
+                        <MessageOutlined />
+                      </template>
+                      点击在线洽谈
+                    </a-button>
+                  </el-col>
+                </el-row>
+              </el-col>
+              <a-divider />
+              <el-col :span="24" class="four">
+                <a-tabs>
+                  <a-tab-pane tab="成果描述">{{ info.brief || '暂无' }}</a-tab-pane>
+                </a-tabs>
+              </el-col>
+            </div>
+          </template>
+        </cHead>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+import { useRoute } from 'vue-router';
+import { MessageOutlined } from '@ant-design/icons-vue';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+
+// 路由
+const route = useRoute();
+
+// 加载中
+const loading: Ref<any> = ref(false);
+const info: Ref<any> = ref({
+  unit: '舟山海韵机械制造有限公司',
+  title: '双头颗粒灌装机',
+  time: '2024-01-05 09:12:23',
+  end_time: '2024-01-05 09:12:23',
+  money: '3',
+  brief: '一种双头颗粒的灌装机'
+});
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search();
+  loading.value = false;
+});
+const search = async () => {
+  //   let id = route.query.id;
+  //   if (id) {
+  //     let res: IQueryResult = await userCheckAxios.fetch(id);
+  //     if (res.errcode == '0') {
+  //       let info: any = res.data as {};
+  //       form.value = info;
+  //       dataChange({ value: info.work_status, model: 'work_status' });
+  //     }
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/src/assets/detail.png) right top no-repeat;
+  background-size: 100%;
+
+  .one {
+    margin: 10px 0;
+
+    .one_1 {
+      margin: 20px 0 10px 0;
+
+      .title {
+        font-size: 18px;
+        font-weight: 700;
+        color: #383b40;
+      }
+
+      .file {
+        display: flex;
+        align-items: center;
+        justify-content: end;
+        font-family: PingFangSC-Regular;
+        font-size: 14px;
+        color: #2374ff;
+        text-align: right;
+      }
+    }
+
+    .one_2 {
+      display: inline-block;
+      font-size: 12px;
+      background: rgba(18, 172, 117, .05);
+      color: #12ac75;
+      padding: 0 15px;
+      height: 20px;
+      line-height: 20px;
+      border-radius: 10px;
+      margin-bottom: 2px;
+    }
+  }
+
+  .two {
+    background: #f9fafb;
+    border-radius: 2px;
+    padding: 30px;
+    margin: 34px 0 20px;
+    font-family: PingFangSC-Medium;
+    font-size: 14px;
+    color: #383b40;
+    line-height: 14px;
+  }
+
+  .thr {
+    margin: 0 0 10px 0;
+
+    .thr_1 {
+      margin-bottom: 20px;
+      font-size: 18px;
+      font-weight: 700;
+      color: #383b40;
+    }
+
+    .thr_2 {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      background: #fff;
+      border: 1px solid #edeff2;
+      box-shadow: 0 4px 10px 0 rgba(0, 0, 0, .03);
+      border-radius: 2px;
+      padding: 30px 20px;
+
+      .left {
+        .name {
+          height: 20px;
+          font-family: PingFangSC-Semibold;
+          font-size: 18px;
+          color: #383b40;
+          line-height: 20px;
+          font-weight: 700;
+          margin-bottom: 8px;
+        }
+
+        .other {
+          height: 14px;
+          font-family: PingFangSC-Medium;
+          font-size: 14px;
+          color: #383b40;
+          line-height: 14px;
+          font-weight: 700;
+
+          span {
+            height: 14px;
+            font-family: PingFangSC-Regular;
+            font-size: 14px;
+            color: #7e8288;
+            line-height: 14px;
+            font-weight: 400;
+            margin-right: 16px;
+          }
+        }
+      }
+
+      .right {
+        display: flex;
+        justify-content: space-between;
+      }
+    }
+  }
+
+  .four {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 214 - 0
src/views/achieve/index.vue

@@ -0,0 +1,214 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <cSearch :is_title="false" :is_search="true" :fields="fields" @search="toSearch"> </cSearch>
+          </el-col>
+          <el-col :span="24" class="two">
+            <a-list :loading="loading" :grid="{ gutter: 16, column: 4 }" :data-source="list">
+              <template #renderItem="{ item }">
+                <el-col :span="24" class="list" @click="toView(item)">
+                  <el-col :span="24" class="name textOver">
+                    <el-tooltip effect="dark" :content="item.name" placement="top">
+                      {{ item.name || '暂无名称' }}
+                    </el-tooltip>
+                  </el-col>
+                  <el-col :span="24" class="two_1"> <span>技术领域: </span>{{ item.area || '暂无技术领域' }} </el-col>
+                  <el-col :span="24" class="two_1"> <span>成果地区: </span>{{ item.city || '暂无成果地区' }} </el-col>
+                  <el-col :span="24" class="two_1"> <span>单位: </span>{{ item.unit || '暂无单位' }} </el-col>
+                </el-col>
+              </template>
+            </a-list>
+          </el-col>
+          <el-col :span="24" class="thr">
+            <a-pagination v-model:page-size="limit" show-size-changer :page-size-options="pageSizeOptions" :total="total" @showSizeChange="onShowSizeChange" />
+          </el-col>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, getCurrentInstance, ref } from 'vue';
+import { useRouter } from 'vue-router';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+const { proxy } = getCurrentInstance() as any;
+
+// 路由
+const router = useRouter();
+// 加载中
+const loading: Ref<any> = ref(false);
+
+let list: Ref<any> = ref([
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  }
+]);
+let total: Ref<number> = ref(12);
+let skip = 0;
+let limit: number = proxy.$limit;
+const pageSizeOptions = ref<string[]>(['12', '24', '60', '120']);
+// 查询数据
+let searchForm: Ref<any> = ref({});
+let fields: Ref<any[]> = ref([
+  { label: '行业分市场', model: 'type', isSearch: true },
+  { label: '技术领域', model: 'label', isSearch: true },
+  { label: '成熟度', model: 'value', isSearch: true },
+  { label: '出让方式', model: 'sort', isSearch: true },
+  { label: '交易价格', model: 'sort', isSearch: true },
+  { label: '成果地区', model: 'sort', isSearch: true }
+]);
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search({ skip, limit });
+  loading.value = false;
+});
+const search = async (e: { skip: number; limit: number }) => {
+  const info = { skip: e.skip, limit: e.limit };
+  //   const res: IQueryResult = await userCheckAxios.query(info);
+  //   if (res.errcode == '0') {
+  //     list.value = res.data;
+  //     total.value = res.total;
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+const toSearch = (query) => {
+  searchForm.value = query;
+  search({ skip, limit });
+};
+// 成果大厅查看详情
+const toView = (item) => {
+  router.push({ path: '/achieve/detail', query: { id: item.id || item._id } });
+};
+const onShowSizeChange = (current: number, pageSize: number) => {
+  console.log(current, pageSize);
+  limit = pageSize;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/src/assets/detail.png) right top no-repeat;
+  background-size: 100%;
+
+  .one {}
+
+  .two {
+    .list {
+      background: #fff;
+      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.03);
+      border-radius: 2px;
+      width: 282px;
+      height: 194px;
+      margin-bottom: 30px;
+      cursor: pointer;
+      transition: all 0.3s;
+      padding: 20px;
+
+      .name {
+        font-size: 16px;
+        color: #121834;
+        height: 16px;
+        line-height: 13px;
+        font-weight: 500;
+        margin: 10px 0;
+      }
+
+      .name:hover {
+        color: #2374ff;
+      }
+
+      .two_1 {
+        font-size: 12px;
+        text-align: justify;
+        line-height: 12px;
+        font-weight: 400;
+        letter-spacing: 0;
+        color: #8f97a3;
+        margin-top: 15px;
+
+        span:last-child {
+          color: #525a68;
+        }
+      }
+    }
+
+    .list:hover {
+      background: #f0f7ff;
+      box-shadow: 0 0 16px rgba(205, 205, 205, 0.6);
+    }
+  }
+
+  .thr {
+    display: flex;
+    flex-direction: row-reverse;
+    padding: 0 0 10px 0;
+  }
+}
+</style>

+ 208 - 0
src/views/activity/index.vue

@@ -0,0 +1,208 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <el-tabs v-model="activeName" @tab-click="handleClick">
+              <el-tab-pane label="全部报名" name="0"></el-tab-pane>
+              <el-tab-pane label="会议报名" name="1"></el-tab-pane>
+              <el-tab-pane label="培训报名" name="2"></el-tab-pane>
+              <el-tab-pane label="通知公告" name="3"></el-tab-pane>
+            </el-tabs>
+          </el-col>
+          <el-col :span="24" class="two">
+            <el-col :span="24" class="list" v-for="(item, index) in list" :key="index" @click="toView(item)">
+              <el-col :span="17" class="left textOver">
+                <span class="value" :class="[item.status == '0' ? 'status0' : 'status1']">{{ item.status == '0' ? '会议' : '培训' }}</span>
+                {{ item.title || '暂无标题' }}
+              </el-col>
+              <el-col :span="7" class="right">
+                <span class="time">{{ moment(item.time).format('MM-DD HH:mm') }}</span>
+                &nbsp;
+                <span class="time">{{ item.status == '0' ? '报名已截止' : '报名已截止' }}</span>
+              </el-col>
+            </el-col>
+          </el-col>
+          <el-col :span="24" class="thr">
+            <a-pagination v-model:page-size="limit" show-size-changer :page-size-options="pageSizeOptions" :total="total" @showSizeChange="onShowSizeChange" />
+          </el-col>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { TabsPaneContext } from 'element-plus';
+import type { Ref } from 'vue';
+import { onMounted, getCurrentInstance, ref } from 'vue';
+import { useRouter } from 'vue-router';
+import moment from 'moment';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+const { proxy } = getCurrentInstance() as any;
+
+// 路由
+const router = useRouter();
+// 加载中
+const loading: Ref<any> = ref(false);
+let list: Ref<any> = ref([
+  {
+    title: '关于浙江大学衢州研究院1件技术秘密转让的公示',
+    time: '2023-07-31',
+    status: '0'
+  },
+  {
+    title: '浙江省科学技术厅 关于第七届中国创新挑战赛(浙江)暨 2022年浙江省技术需求“揭榜挂帅”大赛技术需求公告',
+    time: '2023-07-31',
+    status: '1'
+  },
+  {
+    title: '关于浙江大学衢州研究院1件技术秘密转让的公示',
+    time: '2023-07-31',
+    status: '0'
+  },
+  {
+    title: '关于浙江大学衢州研究院1件技术秘密转让的公示',
+    time: '2023-07-31',
+    status: '0'
+  },
+  {
+    title: '关于浙江大学衢州研究院1件技术秘密转让的公示',
+    time: '2023-07-31',
+    status: '0'
+  },
+  {
+    title: '关于浙江大学衢州研究院1件技术秘密转让的公示',
+    time: '2023-07-31',
+    status: '1'
+  },
+  {
+    title: '关于浙江大学衢州研究院1件技术秘密转让的公示',
+    time: '2023-07-31',
+    status: '1'
+  },
+  {
+    title: '关于浙江大学衢州研究院1件技术秘密转让的公示',
+    time: '2023-07-31',
+    status: '1'
+  },
+  {
+    title: '关于浙江大学衢州研究院1件技术秘密转让的公示',
+    time: '2023-07-31',
+    status: '0'
+  }
+]);
+let total: Ref<number> = ref(12);
+let skip = 0;
+let limit: number = proxy.$limit;
+const pageSizeOptions = ref<string[]>(['12', '24', '60', '120']);
+const activeName = ref('0');
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search({ skip, limit });
+  loading.value = false;
+});
+const search = async (e: { skip: number; limit: number }) => {
+  const info = { skip: e.skip, limit: e.limit };
+  //   const res: IQueryResult = await userCheckAxios.query(info);
+  //   if (res.errcode == '0') {
+  //     list.value = res.data;
+  //     total.value = res.total;
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+// 活动大厅报告通知查看详情
+const toView = (item) => {
+  router.push({ path: '/activity/new', query: { id: item.id || item._id } });
+};
+const onShowSizeChange = (current: number, pageSize: number) => {
+  console.log(current, pageSize);
+  limit = pageSize;
+};
+const handleClick = (tab: TabsPaneContext, event: Event) => {
+  console.log(tab, event);
+}
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/src/assets/detail.png) right top no-repeat;
+  background-size: 100%;
+
+  .two {
+    .list:hover {
+      box-shadow: 0 0 16px rgba(35, 116, 255, 0.6);
+    }
+
+    .list {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 30px;
+      padding: 20px;
+      border-bottom: 1px solid #dcdfe6;
+
+      .left {
+        font-size: 16px;
+        color: #383b40;
+        letter-spacing: 0;
+        line-height: 24px;
+        cursor: pointer;
+
+        .value {
+          padding: 2px 10px;
+          border-radius: 12px;
+          margin-right: 5px;
+          font-size: 12px;
+          line-height: 20px;
+          text-align: center;
+        }
+
+        .status0 {
+          background: rgba(35, 116, 255, 0.05);
+          color: #2374ff;
+        }
+
+        .status1 {
+          background: rgba(18, 172, 117, 0.05);
+          color: #12ac75;
+        }
+      }
+
+      .left:hover {
+        color: #2374ff;
+      }
+
+      .right {
+        text-align: center;
+
+        .time {
+          color: #aaaaaa;
+        }
+
+        .date {
+          color: #525a68;
+        }
+      }
+    }
+  }
+
+  .thr {
+    display: flex;
+    flex-direction: row-reverse;
+    padding: 10px 0;
+  }
+}
+</style>

+ 152 - 0
src/views/activity/new.vue

@@ -0,0 +1,152 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <cHead>
+          <template v-slot:info>
+            <div class="w_1200">
+              <el-col :span="24" class="one">
+                <el-row :span="24" class="one_1">
+                  <el-col :span="24" class="title">{{ info.title || '暂无标题' }}</el-col>
+                </el-row>
+                <el-row :span="24" class="one_4">
+                  <el-col :span="24" class="other"><span>发布时间</span>{{ info.time || '暂无' }}</el-col>
+                </el-row>
+              </el-col>
+              <a-divider />
+              <el-col :span="24" class="two">
+                <a-tabs>
+                  <a-tab-pane tab="简介">
+                    <el-col :span="24" class="two_1">{{ info.brief1 || '暂无' }}</el-col>
+                    <el-col :span="24" class="two_1">{{ info.brief2 || '暂无' }}</el-col>
+                    <el-col :span="24" class="two_1">{{ info.brief3 || '暂无' }}</el-col>
+                    <el-col :span="24" class="two_1">{{ info.brief4 || '暂无' }}</el-col>
+                    <el-col :span="24" class="two_1">{{ info.brief5 || '暂无' }}</el-col>
+                    <el-col :span="24" class="two_1">{{ info.brief6 || '暂无' }}</el-col>
+                  </a-tab-pane>
+                </a-tabs>
+              </el-col>
+              <el-col :span="24" class="thr">
+                <a-button type="primary"> 我要报名 </a-button>
+              </el-col>
+            </div>
+          </template>
+        </cHead>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+import { useRoute } from 'vue-router';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+
+// 路由
+const route = useRoute();
+
+// 加载中
+const loading: Ref<any> = ref(false);
+const info: Ref<any> = ref({
+  title: '关于2023“浙江拍”科创平台专场活动调整的通知',
+  time: '2023-11-29 15:40:43',
+  brief1: '各竞价(拍卖) 相关单位:',
+  brief2: '根据2023年中国浙江网上技术市场活动周开幕式暨首届浙江科技创新合作大会具体工作安排,对2023浙江拍科创平台专场活动进行调整,具体如下:',
+  brief3: '1、活动时间: 与中国浙江网上技术市场活动周开幕式同期,具体时间另行通知',
+  brief4: '2、活动地点:浙江创新馆(杭州未来科技城学术交流中心)中国浙江网上技术市场(https://51iishu.com) ',
+  brief5: '联系人: 沈丽英',
+  brief6: '联系电话: 13588873166'
+});
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search();
+  loading.value = false;
+});
+const search = async () => {
+  //   let id = route.query.id;
+  //   if (id) {
+  //     let res: IQueryResult = await userCheckAxios.fetch(id);
+  //     if (res.errcode == '0') {
+  //       let info: any = res.data as {};
+  //       form.value = info;
+  //       dataChange({ value: info.work_status, model: 'work_status' });
+  //     }
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/src/assets/detail.png) right top no-repeat;
+  background-size: 100%;
+
+  .one {
+    margin: 20px 0 10px 0;
+
+    .one_1 {
+      margin: 5px 0;
+
+      .title {
+        font-size: 18px;
+        font-weight: 700;
+        color: #383b40;
+      }
+
+      .file {
+        display: flex;
+        align-items: center;
+        justify-content: end;
+        font-family: PingFangSC-Regular;
+        font-size: 14px;
+        color: #2374ff;
+        text-align: right;
+      }
+    }
+
+    .one_4 {
+      .other {
+        color: #383b40;
+        margin-top: 13px;
+        line-height: 20px;
+
+        span:first-child {
+          color: #7e8288;
+          margin: 0 15px 0 0;
+        }
+      }
+    }
+  }
+
+  .two {
+    background: #f9fafb;
+    border-radius: 2px;
+    padding: 30px;
+    margin: 34px 0 20px;
+    font-family: PingFangSC-Medium;
+    font-size: 14px;
+    color: #383b40;
+    line-height: 14px;
+
+    .two_1 {
+      padding: 10px 0 0 0;
+    }
+  }
+
+  .thr {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 93 - 0
src/views/activity/video.vue

@@ -0,0 +1,93 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <el-col :span="24" class="name">{{ info.title || '暂无标题' }}</el-col>
+            <el-col :span="24" class="time"><span>发布时间</span> {{ info.time || '暂无发布时间' }}</el-col>
+            <el-col :span="24" class="video">
+              <cVideo :src="info.file" :second="3" />
+            </el-col>
+          </el-col>
+        </div>
+        <cFoot style="background-color: #2e3546; color: #f0f2f5"></cFoot>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, getCurrentInstance, ref } from 'vue';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+const { proxy } = getCurrentInstance() as any;
+
+// 加载中
+const loading: Ref<any> = ref(false);
+const info: Ref<any> = ref({
+  file: '/src/assets/video.mp4',
+  title: '2022年杭州市技术经纪人培训班-第1课',
+  time: '2024-01-05 09:12:23'
+});
+
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search();
+  loading.value = false;
+});
+const search = async () => {
+  //   const res: IQueryResult = await userCheckAxios.query(info);
+  //   if (res.errcode == '0') {
+  //     list.value = res.data;
+  //     total.value = res.total;
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/src/assets/videobg.png) right top no-repeat;
+  background-size: 100%;
+
+  .one {
+    .name {
+      font-size: 24px;
+      font-weight: 600;
+      padding: 12px 0;
+      color: #ffffff;
+    }
+
+    .time {
+      font-size: 14px;
+      color: rgb(108, 127, 163);
+
+      span {
+        padding: 0 10px;
+        line-height: 24px;
+        border-radius: 10px;
+        text-align: center;
+        background-color: rgb(120, 137, 162);
+        color: white;
+      }
+    }
+
+    .video {
+      width: 100%;
+      margin: 20px 0;
+    }
+  }
+}
+</style>

+ 223 - 0
src/views/demand/detail.vue

@@ -0,0 +1,223 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <cHead>
+          <template v-slot:info>
+            <div class="w_1200">
+              <el-col :span="24" class="one">
+                <el-row :span="24" class="one_1">
+                  <el-col :span="20" class="title">{{ info.title || '暂无标题' }}</el-col>
+                  <el-col :span="4" class="file">
+                    <el-icon>
+                      <Download />
+                    </el-icon>
+                    附件下载
+                  </el-col>
+                </el-row>
+                <el-row :span="24" class="one_2"> 普通许可 </el-row>
+              </el-col>
+              <el-col :span="24" class="two">
+                <a-descriptions bordered title="简介">
+                  <a-descriptions-item label="行业领域">行业领域</a-descriptions-item>
+                  <a-descriptions-item label="需求紧急度">需求紧急度</a-descriptions-item>
+                  <a-descriptions-item label="合作方式">合作方式</a-descriptions-item>
+                  <a-descriptions-item label="有效期">有效期</a-descriptions-item>
+                  <a-descriptions-item label="地区">地区</a-descriptions-item>
+                </a-descriptions>
+              </el-col>
+              <el-col :span="24" class="thr">
+                <el-col :span="24" class="thr_1">单位信息</el-col>
+                <el-row :span="24" class="thr_2">
+                  <el-col :span="17" class="left">
+                    <el-col :span="24" class="name">
+                      {{ info.unit || '暂无' }}
+                    </el-col>
+                    <el-col :span="24" class="other"> <span>联系人</span>{{ info.unit || '暂无' }} </el-col>
+                  </el-col>
+                  <el-col :span="4" class="right">
+                    <a-button type="primary">
+                      <template #icon>
+                        <MessageOutlined />
+                      </template>
+                      点击在线洽谈
+                    </a-button>
+                  </el-col>
+                </el-row>
+              </el-col>
+              <a-divider />
+              <el-col :span="24" class="four">
+                <a-tabs>
+                  <a-tab-pane tab="需求详情">{{ info.brief || '暂无' }}</a-tab-pane>
+                </a-tabs>
+              </el-col>
+            </div>
+          </template>
+        </cHead>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+import { useRoute } from 'vue-router';
+import { MessageOutlined } from '@ant-design/icons-vue';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+
+// 路由
+const route = useRoute();
+
+// 加载中
+const loading: Ref<any> = ref(false);
+const info: Ref<any> = ref({
+  unit: '舟山海韵机械制造有限公司',
+  title: '异戊烯醇产品后续加工需要技术支持',
+  brief: '异戊烯醇产品完成之后后续加工需要技术支持'
+});
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search();
+  loading.value = false;
+});
+const search = async () => {
+  //   let id = route.query.id;
+  //   if (id) {
+  //     let res: IQueryResult = await userCheckAxios.fetch(id);
+  //     if (res.errcode == '0') {
+  //       let info: any = res.data as {};
+  //       form.value = info;
+  //       dataChange({ value: info.work_status, model: 'work_status' });
+  //     }
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/src/assets/detail.png) right top no-repeat;
+  background-size: 100%;
+
+  .one {
+    margin: 10px 0;
+
+    .one_1 {
+      margin: 20px 0 10px 0;
+
+      .title {
+        font-size: 18px;
+        font-weight: 700;
+        color: #383b40;
+      }
+
+      .file {
+        display: flex;
+        align-items: center;
+        justify-content: end;
+        font-family: PingFangSC-Regular;
+        font-size: 14px;
+        color: #2374ff;
+        text-align: right;
+      }
+    }
+
+    .one_2 {
+      display: inline-block;
+      font-size: 12px;
+      background: rgba(18, 172, 117, .05);
+      color: #12ac75;
+      padding: 0 15px;
+      height: 20px;
+      line-height: 20px;
+      border-radius: 10px;
+      margin-bottom: 2px;
+    }
+  }
+
+  .two {
+    background: #f9fafb;
+    border-radius: 2px;
+    padding: 30px;
+    margin: 34px 0 20px;
+    font-family: PingFangSC-Medium;
+    font-size: 14px;
+    color: #383b40;
+    line-height: 14px;
+  }
+
+  .thr {
+    margin: 0 0 10px 0;
+
+    .thr_1 {
+      margin-bottom: 20px;
+      font-size: 18px;
+      font-weight: 700;
+      color: #383b40;
+    }
+
+    .thr_2 {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      background: #fff;
+      border: 1px solid #edeff2;
+      box-shadow: 0 4px 10px 0 rgba(0, 0, 0, .03);
+      border-radius: 2px;
+      padding: 30px 20px;
+
+      .left {
+        .name {
+          height: 20px;
+          font-family: PingFangSC-Semibold;
+          font-size: 18px;
+          color: #383b40;
+          line-height: 20px;
+          font-weight: 700;
+          margin-bottom: 8px;
+        }
+
+        .other {
+          height: 14px;
+          font-family: PingFangSC-Medium;
+          font-size: 14px;
+          color: #383b40;
+          line-height: 14px;
+          font-weight: 700;
+
+          span {
+            height: 14px;
+            font-family: PingFangSC-Regular;
+            font-size: 14px;
+            color: #7e8288;
+            line-height: 14px;
+            font-weight: 400;
+            margin-right: 16px;
+          }
+        }
+      }
+
+      .right {
+        display: flex;
+        justify-content: space-between;
+      }
+    }
+  }
+
+  .four {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 228 - 0
src/views/demand/index.vue

@@ -0,0 +1,228 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <cSearch :is_title="false" :is_search="true" :fields="fields" @search="toSearch"> </cSearch>
+          </el-col>
+          <el-col :span="24" class="two">
+            <a-list :loading="loading" :grid="{ gutter: 16, column: 4 }" :data-source="list">
+              <template #renderItem="{ item }">
+                <el-col :span="24" class="list" @click="toView(item)">
+                  <el-col :span="24" class="name textOver">
+                    <el-tooltip effect="dark" :content="item.name" placement="top">
+                      {{ item.name || '暂无名称' }}
+                    </el-tooltip>
+                  </el-col>
+                  <el-col :span="24" class="two_1"> <span>技术领域: </span>{{ item.area || '暂无技术领域' }} </el-col>
+                  <el-col :span="24" class="two_1"> <span>需求地区: </span>{{ item.city || '暂无需求地区' }} </el-col>
+                  <el-col :span="24" class="two_1"> <span>单位: </span>{{ item.unit || '暂无单位' }} </el-col>
+                </el-col>
+              </template>
+            </a-list>
+          </el-col>
+          <el-col :span="24" class="thr">
+            <a-pagination v-model:page-size="limit" show-size-changer :page-size-options="pageSizeOptions" :total="total" @showSizeChange="onShowSizeChange" />
+          </el-col>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, getCurrentInstance, ref } from 'vue';
+import { useRouter } from 'vue-router';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+const { proxy } = getCurrentInstance() as any;
+
+// 路由
+const router = useRouter();
+// 加载中
+const loading: Ref<any> = ref(false);
+let list: Ref<any> = ref([
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  }
+]);
+let total: Ref<number> = ref(12);
+let skip = 0;
+let limit: number = proxy.$limit;
+const pageSizeOptions = ref<string[]>(['12', '24', '60', '120']);
+// 查询数据
+let searchForm: Ref<any> = ref({});
+let fields: Ref<any[]> = ref([
+  { label: '技术领域', model: 'type', isSearch: true },
+  { label: '合作方式', model: 'label', isSearch: true },
+  { label: '需求地区', model: 'value', isSearch: true },
+  { label: '需求状态', model: 'sort', isSearch: true }
+]);
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search({ skip, limit });
+  loading.value = false;
+});
+const search = async (e: { skip: number; limit: number }) => {
+  const info = { skip: e.skip, limit: e.limit };
+  //   const res: IQueryResult = await userCheckAxios.query(info);
+  //   if (res.errcode == '0') {
+  //     list.value = res.data;
+  //     total.value = res.total;
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+const toSearch = (query) => {
+  searchForm.value = query;
+  search({ skip, limit });
+};
+// 需求大厅查看详情
+const toView = (item) => {
+  router.push({ path: '/demand/detail', query: { id: item.id || item._id } });
+};
+const onShowSizeChange = (current: number, pageSize: number) => {
+  console.log(current, pageSize);
+  limit = pageSize;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/src/assets/detail.png) right top no-repeat;
+  background-size: 100%;
+  .one {}
+
+  .two {
+    .list {
+      background: #fff;
+      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.03);
+      border-radius: 2px;
+      width: 282px;
+      height: 194px;
+      margin-bottom: 30px;
+      cursor: pointer;
+      transition: all 0.3s;
+      padding: 20px;
+
+      .name {
+        font-size: 16px;
+        color: #121834;
+        height: 16px;
+        line-height: 13px;
+        font-weight: 500;
+        margin: 10px 0;
+      }
+
+      .name:hover {
+        color: #2374ff;
+      }
+
+      .two_1 {
+        font-size: 12px;
+        text-align: justify;
+        line-height: 12px;
+        font-weight: 400;
+        letter-spacing: 0;
+        color: #8f97a3;
+        margin-top: 15px;
+
+        span:last-child {
+          color: #525a68;
+        }
+      }
+    }
+
+    .list:hover {
+      background: #f0f7ff;
+      box-shadow: 0 0 16px rgba(205, 205, 205, 0.6);
+    }
+  }
+
+  .thr {
+    display: flex;
+    flex-direction: row-reverse;
+    padding: 0 0 10px 0;
+  }
+}
+</style>

+ 254 - 0
src/views/home/components/achievement.vue

@@ -0,0 +1,254 @@
+<template>
+  <div id="achievement">
+    <el-row>
+      <el-col :span="24" class="achievement">
+        <el-col :span="24" class="one">
+          <el-col :span="20" class="left">
+            <el-image class="image" src="/src/assets/achieve.png" fit="fill" />
+            <span>成果信息</span>
+          </el-col>
+          <el-col :span="4" class="right" @click="toMore"> 更多 > </el-col>
+        </el-col>
+        <el-col :span="24" class="two">
+          <el-col :span="24" class="two_1">
+            <el-col :span="10" class="title">成果名称</el-col>
+            <el-col :span="4" class="title">技术领域</el-col>
+            <el-col :span="4" class="title">成果地区</el-col>
+            <el-col :span="6" class="title">单位</el-col>
+          </el-col>
+          <el-col :span="24" class="two_2" id="tableRef">
+            <vue3-seamless-scroll :list="list" :hover="true" :step="0.8" :wheel="true" :isWatch="true">
+              <el-col :span="24" class="list" v-for="(item, index) in list" :key="index" @click="toView(item)">
+                <el-col :span="10" class="content textOver">
+                  <el-tooltip effect="dark" :content="item.name" placement="top">
+                    {{ item.name || '暂无成果名称' }}
+                  </el-tooltip>
+                </el-col>
+                <el-col :span="4" class="content textOver"> {{ item.area || '暂无技术领域' }} </el-col>
+                <el-col :span="4" class="content textOver"> {{ item.city || '暂无成果地区' }} </el-col>
+                <el-col :span="6" class="content textOver"> {{ item.unit || '暂无单位' }} </el-col>
+              </el-col>
+            </vue3-seamless-scroll>
+          </el-col>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+import type { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { useRouter } from 'vue-router';
+// 路由
+const router = useRouter();
+const { proxy } = getCurrentInstance() as any;
+// 加载中
+const loading: Ref<any> = ref(false);
+// 列表
+const list: Ref<any> = ref([
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  }
+]);
+let total: Ref<number> = ref(12);
+let skip = 0;
+let limit: number = proxy.$limit;
+// 查看更多
+const toMore = () => {
+  router.push({ path: `/achieve` });
+};
+// 查看
+const toView = (item) => {
+  router.push({ path: '/achieve/detail', query: { id: item.id || item._id } });
+};
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search({ skip, limit });
+  loading.value = false;
+});
+const search = async (e: { skip: number; limit: number }) => {
+  const info = { skip: e.skip, limit: e.limit };
+  //   const res: IQueryResult = await userCheckAxios.query(info);
+  //   if (res.errcode == '0') {
+  //     list.value = res.data;
+  //     total.value = res.total;
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+</script>
+<style lang="scss" scoped>
+.achievement {
+  width: 1200px;
+  padding: 20px;
+  min-height: 423px;
+
+  .one {
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin: 0 0 10px 0;
+
+    .left {
+      display: flex;
+      align-items: center;
+
+      span {
+        font-size: 20px;
+        color: #333;
+        font-weight: bold;
+        margin: 0 0 0 5px;
+      }
+
+      .image {
+        width: 40px;
+        height: 40px;
+      }
+    }
+
+    .right {
+      text-align: right;
+      font-size: 12px;
+    }
+    .right:hover {
+      color: #2374ff;
+    }
+  }
+
+  .two {
+    width: 100%;
+
+    .two_1 {
+      display: flex;
+      justify-content: center;
+      height: 50px;
+      background-image: linear-gradient(#dbebf8, #fafafa);
+      line-height: 50px;
+      color: #333;
+      font-size: 16px;
+
+      .title {
+        text-align: center;
+      }
+    }
+
+    .two_2 {
+      max-height: 300px;
+      overflow: hidden;
+      border: 1px solid #b2c1ff;
+
+      .list {
+        display: flex;
+        justify-content: center;
+        height: 50px;
+        line-height: 50px;
+        font-size: 16px;
+        color: #666;
+        background: #fff;
+
+        .content {
+          text-align: center;
+        }
+
+        .content:hover {
+          color: #2374ff;
+        }
+      }
+
+      .list:nth-child(2n) {
+        background: #f4f4f4;
+      }
+    }
+  }
+}
+</style>

Diff do ficheiro suprimidas por serem muito extensas
+ 605 - 0
src/views/home/components/activity.vue


+ 253 - 0
src/views/home/components/demand.vue

@@ -0,0 +1,253 @@
+<template>
+  <div id="demand">
+    <el-row>
+      <el-col :span="24" class="demand">
+        <el-col :span="24" class="one">
+          <el-col :span="20" class="left">
+            <el-image class="image" src="/src/assets/demand.png" fit="fill" />
+            <span>需求信息</span>
+          </el-col>
+          <el-col :span="4" class="right" @click="toMore"> 更多 > </el-col>
+        </el-col>
+        <el-col :span="24" class="two">
+          <el-col :span="24" class="two_1">
+            <el-col :span="10" class="title">需求名称</el-col>
+            <el-col :span="4" class="title">技术领域</el-col>
+            <el-col :span="4" class="title">需求地区</el-col>
+            <el-col :span="6" class="title">单位</el-col>
+          </el-col>
+          <el-col :span="24" class="two_2" id="tableRef">
+            <vue3-seamless-scroll :list="list" :hover="true" :step="0.8" :wheel="true" :isWatch="true">
+              <el-col :span="24" class="list" v-for="(item, index) in list" :key="index" @click="toView(item)">
+                <el-col :span="10" class="content textOver">
+                  <el-tooltip effect="dark" :content="item.name" placement="top">
+                    {{ item.name || '暂无成果名称' }}
+                  </el-tooltip>
+                </el-col>
+                <el-col :span="4" class="content textOver"> {{ item.area || '暂无技术领域' }} </el-col>
+                <el-col :span="4" class="content textOver"> {{ item.city || '暂无成果地区' }} </el-col>
+                <el-col :span="6" class="content textOver"> {{ item.unit || '暂无单位' }} </el-col>
+              </el-col>
+            </vue3-seamless-scroll>
+          </el-col>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+import type { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { useRouter } from 'vue-router';
+// 路由
+const router = useRouter();
+const { proxy } = getCurrentInstance() as any;
+// 加载中
+const loading: Ref<any> = ref(false);
+// 列表
+const list: Ref<any> = ref([
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司'
+  }
+]);
+let total: Ref<number> = ref(12);
+let skip = 0;
+let limit: number = proxy.$limit;
+// 查看更多
+const toMore = () => {
+  router.push({ path: `/demand` });
+};
+// 查看
+const toView = (item) => {
+  router.push({ path: '/demand/detail', query: { id: item.id || item._id } });
+};
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search({ skip, limit });
+  loading.value = false;
+});
+const search = async (e: { skip: number; limit: number }) => {
+  const info = { skip: e.skip, limit: e.limit };
+  //   const res: IQueryResult = await userCheckAxios.query(info);
+  //   if (res.errcode == '0') {
+  //     list.value = res.data;
+  //     total.value = res.total;
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+</script>
+<style lang="scss" scoped>
+.demand {
+  width: 1200px;
+  padding: 20px;
+  min-height: 423px;
+  .one {
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin: 0 0 10px 0;
+
+    .left {
+      display: flex;
+      align-items: center;
+
+      span {
+        font-size: 20px;
+        color: #333;
+        font-weight: bold;
+        margin: 0 0 0 5px;
+      }
+
+      .image {
+        width: 40px;
+        height: 40px;
+      }
+    }
+
+    .right {
+      text-align: right;
+      font-size: 12px;
+    }
+    .right:hover {
+      color: #2374ff;
+    }
+  }
+
+  .two {
+    width: 100%;
+
+    .two_1 {
+      display: flex;
+      justify-content: center;
+      height: 50px;
+      background-image: linear-gradient(#dbebf8, #fafafa);
+      line-height: 50px;
+      color: #333;
+      font-size: 16px;
+
+      .title {
+        text-align: center;
+      }
+    }
+
+    .two_2 {
+      max-height: 300px;
+      overflow: hidden;
+      border: 1px solid #b2c1ff;
+
+      .list {
+        display: flex;
+        justify-content: center;
+        height: 50px;
+        line-height: 50px;
+        font-size: 16px;
+        color: #666;
+        background: #fff;
+
+        .content {
+          text-align: center;
+        }
+
+        .content:hover {
+          color: #2374ff;
+        }
+      }
+
+      .list:nth-child(2n) {
+        background: #f4f4f4;
+      }
+    }
+  }
+}
+</style>

Diff do ficheiro suprimidas por serem muito extensas
+ 358 - 0
src/views/home/components/service.vue


+ 601 - 0
src/views/home/components/transaction.vue

@@ -0,0 +1,601 @@
+<template>
+  <div id="transaction">
+    <el-row>
+      <el-col :span="24" class="transaction">
+        <a-tabs v-model:activeKey="activeKey" size="large" type="card">
+          <a-tab-pane key="1" tab="协议定价">
+            <a-list :grid="{ gutter: 16, column: 4 }" :data-source="oneList">
+              <template #renderItem="{ item }">
+                <el-col :span="24" class="list" @click="toView(item)">
+                  <el-tag v-if="item.status == '1'" type="success" round>自主挂牌</el-tag>
+                  <el-tag v-if="item.status == '2'" type="warning" round>线下拍卖</el-tag>
+                  <el-col :span="24" class="name textOver">
+                    <span class="font_5" :class="[item.status == '0' ? 'color0' : item.status == '1' ? 'color1' : 'color2']">●</span>
+                    <el-tooltip effect="dark" :content="item.name" placement="top">
+                      {{ item.name }}
+                    </el-tooltip>
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.unit">
+                    <span>依托单位:</span>
+                    {{ item.unit }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.service">
+                    <span>服务机构:</span>
+                    {{ item.service }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.no">
+                    <span>项目编号: </span>
+                    {{ item.no }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.number">
+                    <span>成果数量:</span>
+                    {{ item.number }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.notice_time">
+                    <span>公告时间:</span>
+                    {{ item.notice_time }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.end_time">
+                    <span>截上时间:</span>
+                    {{ item.end_time }}
+                  </el-col>
+                </el-col>
+              </template>
+            </a-list>
+          </a-tab-pane>
+          <a-tab-pane key="2" tab="挂牌交易">
+            <a-list :grid="{ gutter: 16, column: 4 }" :data-source="twoList">
+              <template #renderItem="{ item }">
+                <el-col :span="24" class="list" @click="toView(item)">
+                  <el-tag v-if="item.status == '1'" type="success" round>自主挂牌</el-tag>
+                  <el-tag v-if="item.status == '2'" type="warning" round>线下拍卖</el-tag>
+                  <el-col :span="24" class="name textOver">
+                    <span class="font_5" :class="[item.status == '0' ? 'color0' : item.status == '1' ? 'color1' : 'color2']">●</span>
+                    <el-tooltip effect="dark" :content="item.name" placement="top">
+                      {{ item.name }}
+                    </el-tooltip>
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.unit">
+                    <span>依托单位:</span>
+                    {{ item.unit }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.service">
+                    <span>服务机构:</span>
+                    {{ item.service }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.no">
+                    <span>项目编号: </span>
+                    {{ item.no }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.number">
+                    <span>成果数量:</span>
+                    {{ item.number }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.notice_time">
+                    <span>公告时间:</span>
+                    {{ item.notice_time }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.end_time">
+                    <span>截上时间:</span>
+                    {{ item.end_time }}
+                  </el-col>
+                </el-col>
+              </template>
+            </a-list>
+          </a-tab-pane>
+          <a-tab-pane key="3" tab="竞价(拍卖)">
+            <a-list :grid="{ gutter: 16, column: 4 }" :data-source="thrList">
+              <template #renderItem="{ item }">
+                <el-col :span="24" class="list" @click="toView(item)">
+                  <el-tag v-if="item.status == '1'" type="success" round>自主挂牌</el-tag>
+                  <el-tag v-if="item.status == '2'" type="warning" round>线下拍卖</el-tag>
+                  <el-col :span="24" class="name textOver">
+                    <span class="font_5" :class="[item.status == '0' ? 'color0' : item.status == '1' ? 'color1' : 'color2']">●</span>
+                    <el-tooltip effect="dark" :content="item.name" placement="top">
+                      {{ item.name }}
+                    </el-tooltip>
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.unit">
+                    <span>依托单位:</span>
+                    {{ item.unit }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.service">
+                    <span>服务机构:</span>
+                    {{ item.service }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.no">
+                    <span>项目编号: </span>
+                    {{ item.no }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.number">
+                    <span>成果数量:</span>
+                    {{ item.number }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.notice_time">
+                    <span>公告时间:</span>
+                    {{ item.notice_time }}
+                  </el-col>
+                  <el-col :span="24" class="other" v-if="item.end_time">
+                    <span>截上时间:</span>
+                    {{ item.end_time }}
+                  </el-col>
+                </el-col>
+              </template>
+            </a-list>
+          </a-tab-pane>
+        </a-tabs>
+        <el-col :span="24" class="one">
+          <a-pagination v-model:page-size="limit" show-size-changer :page-size-options="pageSizeOptions" :total="total" @showSizeChange="onShowSizeChange" />
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+import type { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { useRouter } from 'vue-router';
+// 路由
+const router = useRouter();
+const { proxy } = getCurrentInstance() as any;
+// 加载中
+const loading: Ref<any> = ref(false);
+const activeKey = ref('1');
+// 交易大厅列表
+const oneList: Ref<any> = ref([
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  }
+]);
+const twoList: Ref<any> = ref([
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    number: '1',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    number: '2',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    number: '5',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    number: '8',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    number: '1',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    number: '2',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    number: '5',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    number: '8',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    number: '1',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    number: '2',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    number: '5',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    number: '8',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '1'
+  }
+]);
+const thrList: Ref<any> = ref([
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    number: '1',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    number: '2',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    number: '5',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    number: '8',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  },
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    number: '1',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    number: '2',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    number: '5',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    number: '8',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  }, {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    number: '1',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    number: '2',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    number: '5',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    number: '8',
+    service: '浙江省人民医院',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '2'
+  }
+]);
+let total: Ref<number> = ref(12);
+let skip = 0;
+let limit: number = proxy.$limit;
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search({ skip, limit });
+  loading.value = false;
+});
+const search = async (e: { skip: number; limit: number }) => {
+  const info = { skip: e.skip, limit: e.limit };
+  //   const res: IQueryResult = await userCheckAxios.query(info);
+  //   if (res.errcode == '0') {
+  //     list.value = res.data;
+  //     total.value = res.total;
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+// 查看
+const toView = (item) => {
+  router.push({ path: '/trade/detail', query: { id: item.id || item._id } });
+};
+const onShowSizeChange = (current: number, pageSize: number) => {
+  console.log(current, pageSize);
+  limit = pageSize;
+};
+</script>
+<style lang="scss" scoped>
+.transaction {
+  min-height: 423px;
+
+  :deep(.ant-tabs-content-holder) {
+    padding-left: 70px;
+  }
+  :deep(.ant-row) {
+    width: 100%;
+  }
+
+  .one {
+    display: flex;
+    flex-direction: row-reverse;
+    padding: 20px;
+  }
+
+  .list {
+    background: #fff;
+    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.03);
+    border-radius: 2px;
+    width: 300px;
+    height: 220px;
+    margin-bottom: 30px;
+    cursor: pointer;
+    transition: all 0.3s;
+    padding: 20px;
+
+    .name {
+      font-size: 14px;
+      color: #121834;
+      line-height: 22px;
+      font-weight: 600;
+      margin-bottom: 12px;
+
+      .font_5 {
+        font-size: 14px;
+        font-family: Microsoft YaHei;
+        line-height: 26px;
+        margin-right: 6px;
+      }
+
+      .color0 {
+        color: #e6a23c;
+      }
+
+      .color1 {
+        color: #2374ff;
+      }
+
+      .color2 {
+        color: #909399;
+      }
+    }
+
+    .name:hover {
+      color: #2374ff;
+    }
+
+    .other {
+      margin-bottom: 8px;
+      padding-left: 15px;
+      font-size: 12px;
+      color: #525a68;
+      letter-spacing: 0;
+      text-align: justify;
+      line-height: 12px;
+      font-weight: 400;
+
+      span {
+        color: #8f97a3;
+      }
+    }
+  }
+
+  .list:hover {
+    background: #f0f7ff;
+    box-shadow: 0 0 16px rgba(205, 205, 205, 0.6);
+  }
+}
+</style>

+ 56 - 0
src/views/home/index.vue

@@ -0,0 +1,56 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <cHead @selectMenu="selectMenu">
+          <template v-slot:info>
+            <component v-show="current == 'tran'" :is="transaction"> </component>
+            <component v-show="current == 'achieve'" :is="achievement"> </component>
+            <component v-show="current == 'demand'" :is="demand"> </component>
+            <component v-show="current == 'service'" :is="service"> </component>
+            <component v-show="current == 'activity'" :is="activity"> </component>
+          </template>
+        </cHead>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util'
+// const toolsAxios = ToolsStore();
+// 组件
+import transaction from './components/transaction.vue';
+import achievement from './components/achievement.vue';
+import demand from './components/demand.vue';
+import service from './components/service.vue';
+import activity from './components/activity.vue';
+
+// 加载中
+const loading: Ref<any> = ref(false);
+const current: Ref<any> = ref('tran');
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  search();
+  loading.value = false;
+});
+const search = async () => {
+  // let res: IQueryResult = await toolsAxios.dataCount();
+  // if (res.errcode == '0') {
+  //   info.value = res.data;
+  // }
+};
+// 菜单选择
+const selectMenu = async (item) => {
+  current.value = item.key;
+};
+</script>
+<style scoped lang="scss">
+.main {}
+</style>

+ 246 - 0
src/views/login/index.vue

@@ -0,0 +1,246 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <cHead :siteInfo="siteInfo"></cHead>
+        <el-col :span="24" class="two">
+          <div class="logo">
+            <el-image class="image" src="/src/assets/login.jpeg" fit="fill" />
+          </div>
+          <div class="loginform">
+            <el-col :span="24" class="tab">
+              <el-col :span="6" class="title" @click="toTab(0)" :class="[activeName == '0' ? 'tab0' : 'tab1']">个人登录</el-col>
+              <el-col :span="6" class="title" @click="toTab(1)" :class="[activeName == '1' ? 'tab0' : 'tab1']">法人登录</el-col>
+            </el-col>
+            <el-col :span="24" class="content" v-show="activeName == '0'">
+              <el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="60px" class="form" label-position="left">
+                <el-form-item label="账号" prop="account">
+                  <el-input v-model="form.account" placeholder="请输入账号">
+                    <template #prefix>
+                      <el-icon><User /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="密码" prop="password">
+                  <el-input v-model="form.password" type="password" show-password placeholder="请输入登录密码">
+                    <template #prefix>
+                      <el-icon><Unlock /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-col :span="24" class="remark">
+                  <span>其他方式登录</span>
+                  <span>忘记密码?</span>
+                </el-col>
+                <el-col :span="24" class="button">
+                  <el-button type="primary" @click="submitForm(ruleFormRef)">登录</el-button>
+                </el-col>
+                <el-col :span="24" class="agree">
+                  <span>登录即表示您同意</span><span @click="toRegister">《{{ siteInfo.zhTitle }}使用协议》</span>
+                </el-col>
+                <el-col :span="24" class="other"><span>还没有账号?</span> &nbsp; &nbsp;<span @click="toRegister">去注册</span></el-col>
+              </el-form>
+            </el-col>
+            <el-col :span="24" class="content" v-show="activeName == '1'">
+              <el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="60px" class="form" label-position="left">
+                <el-form-item label="账号" prop="account">
+                  <el-input v-model="form.account" placeholder="请输入账号">
+                    <template #prefix>
+                      <el-icon><User /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="密码" prop="password">
+                  <el-input v-model="form.password" type="password" show-password placeholder="请输入登录密码">
+                    <template #prefix>
+                      <el-icon><Unlock /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-col :span="24" class="remark">
+                  <span>其他方式登录</span>
+                  <span>忘记密码?</span>
+                </el-col>
+                <el-col :span="24" class="button">
+                  <el-button type="primary" @click="submitForm(ruleFormRef)">登录</el-button>
+                </el-col>
+                <el-col :span="24" class="agree">
+                  <span>登录即表示您同意</span><span @click="toRegister">《{{ siteInfo.zhTitle }}使用协议》</span>
+                </el-col>
+                <el-col :span="24" class="other"><span>还没有账号?</span> &nbsp; &nbsp;<span @click="toRegister">去注册</span></el-col>
+              </el-form>
+            </el-col>
+          </div>
+        </el-col>
+        <cFoot></cFoot>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref, reactive } from 'vue';
+import type { FormInstance, FormRules } from 'element-plus';
+import { useRoute, useRouter } from 'vue-router';
+import { siteInfo } from '@/layout/site';
+// // 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+// 路由
+const router = useRouter();
+const route = useRoute();
+// 加载中
+const loading: Ref<any> = ref(false);
+const form: Ref<any> = ref({});
+interface RuleForm {
+  account: string;
+  password: string;
+}
+const ruleFormRef = ref<FormInstance>();
+const rules = reactive<FormRules<RuleForm>>({
+  account: [{ required: true, message: '请输入账号', trigger: 'blur' }],
+  password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
+});
+const activeName: Ref<any> = ref(0);
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  search();
+  loading.value = false;
+});
+const search = async () => {
+  activeName.value = route.query.status || '0';
+  // let res: IQueryResult = await toolsAxios.dataCount();
+  // if (res.errcode == '0') {
+  //     info.value = res.data;
+  // }
+};
+// 选择
+const toTab = async (active) => {
+  activeName.value = active;
+};
+// 登录
+const submitForm = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+      console.log('submit!');
+    } else {
+      console.log('error submit!', fields);
+    }
+  });
+};
+// 去注册
+const toRegister = () => {
+  router.push({ path: '/register' });
+};
+</script>
+<style scoped lang="scss">
+.main {
+  .two {
+    background-image: url(/src/assets/loginbg.jpg);
+    background-position: center center;
+    background-repeat: no-repeat;
+    height: 500px;
+    width: 100%;
+    background-size: cover;
+    display: flex;
+    justify-content: space-evenly;
+    .logo {
+      margin: 50px 0px 0px 0;
+      height: 420px;
+      opacity: 0.8;
+      .image {
+        width: 100%;
+        height: 100%;
+      }
+    }
+    .loginform {
+      margin: 50px 0 0 0;
+      padding: 20px 0 0 0;
+      width: 380px;
+      height: 400px;
+      background-color: #ffffff;
+      border-radius: 3px;
+      .tab {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        .title {
+          text-align: center;
+          margin: 0 40px;
+          font-family: PingFangSC-Semibold !important;
+          font-size: 20px;
+          letter-spacing: -0.14px;
+          line-height: 32px;
+          font-weight: bold;
+        }
+        .tab0 {
+          color: #1492ff;
+          border-bottom: 2px solid;
+          border-bottom-color: #1492ff;
+          padding-bottom: 10px;
+        }
+        .tab1 {
+          color: #333333;
+          padding-bottom: 10px;
+        }
+      }
+
+      .content {
+        margin: 35px 50px 0px;
+        .remark {
+          display: flex;
+          justify-content: space-between;
+          span {
+            cursor: pointer;
+            font-family: PingFangSC-Regular;
+            font-size: 14px;
+            color: #333333;
+            letter-spacing: -0.09px;
+            text-align: right;
+            line-height: 32px;
+          }
+          span:hover {
+            color: #2374ff;
+          }
+        }
+        .button {
+          padding: 10px 0;
+          :deep(.el-button) {
+            width: 285px !important;
+            height: 44px !important;
+            border: 0 !important;
+            color: #f8f8f8 !important;
+            font-size: 16px !important;
+            text-align: center !important;
+            line-height: 40px !important;
+            cursor: pointer !important;
+            font-family: PingFangSC-Regular !important;
+            background-color: #1492ff !important;
+          }
+        }
+        .agree {
+          padding: 0 0 40px 0;
+          color: #999;
+          font-size: 12px;
+          span:last-child {
+            color: #2374ff;
+          }
+        }
+        .other {
+          text-align: center;
+          font-family: PingFangSC-Regular;
+          font-size: 14px;
+          color: #333333;
+          span:last-child {
+            color: #2374ff;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

Diff do ficheiro suprimidas por serem muito extensas
+ 102 - 0
src/views/policy/detail.vue


Diff do ficheiro suprimidas por serem muito extensas
+ 241 - 0
src/views/policy/index.vue


+ 401 - 0
src/views/register/index.vue

@@ -0,0 +1,401 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <cHead :siteInfo="siteInfo"></cHead>
+        <el-col :span="24" class="two">
+          <div class="logo">
+            <el-image class="image" src="/src/assets/login.jpeg" fit="fill" />
+          </div>
+          <div class="loginform">
+            <el-col :span="24" class="tab">
+              <el-col :span="5" class="title" @click="toTab(0)" :class="[activeName == '0' ? 'tab0' : 'tab1']">个人用户</el-col>
+              <el-col :span="5" class="title" @click="toTab(1)" :class="[activeName == '1' ? 'tab0' : 'tab1']">企业用户</el-col>
+              <el-col :span="5" class="title" @click="toTab(2)" :class="[activeName == '2' ? 'tab0' : 'tab1']">科研单位</el-col>
+            </el-col>
+            <el-col :span="24" class="content" v-show="activeName == '0'">
+              <el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="80px" class="form" label-position="left">
+                <el-form-item label="账号" prop="account">
+                  <el-input v-model="form.account" placeholder="请输入账号">
+                    <template #prefix>
+                      <el-icon><User /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="用户名" prop="nick_name">
+                  <el-input v-model="form.nick_name" placeholder="请输入用户名">
+                    <template #prefix>
+                      <el-icon><Avatar /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="工作单位" prop="unit">
+                  <el-input v-model="form.tel" placeholder="请输入工作单位">
+                    <template #prefix>
+                      <el-icon><OfficeBuilding /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="联系电话" prop="tel">
+                  <el-input v-model="form.tel" placeholder="请输入联系电话">
+                    <template #prefix>
+                      <el-icon><Iphone /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="身份证号" prop="id_card">
+                  <el-input v-model="form.id_card" placeholder="请输入身份证号">
+                    <template #prefix>
+                      <el-icon><ScaleToOriginal /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="联系邮箱" prop="email">
+                  <el-input v-model="form.email" placeholder="请输入联系邮箱">
+                    <template #prefix>
+                      <el-icon><Message /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="密码" prop="password">
+                  <el-input v-model="form.password" type="password" show-password placeholder="请输入登录密码">
+                    <template #prefix>
+                      <el-icon><Unlock /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="确认密码" prop="refpassword">
+                  <el-input v-model="form.refpassword" type="password" show-password placeholder="请再次确认输入密码">
+                    <template #prefix>
+                      <el-icon><Unlock /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-col :span="24" class="remark">
+                  <span @click="toLogin">已有账号去登录</span>
+                  <span @click="toBack">返回首页</span>
+                </el-col>
+                <el-col :span="24" class="button">
+                  <el-button type="primary" @click="submitForm(ruleFormRef)">注册</el-button>
+                </el-col>
+                <el-col :span="24" class="agree">
+                  <el-checkbox v-model="isAgree"></el-checkbox>
+                  <span style="margin: 0 0 0 5px">我已阅读并同意</span><span @click="toRegister">《{{ siteInfo.zhTitle }}使用协议》</span>
+                </el-col>
+              </el-form>
+            </el-col>
+            <el-col :span="24" class="content" v-show="activeName == '1'">
+              <el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="80px" class="form" label-position="left">
+                <el-form-item label="账号" prop="account">
+                  <el-input v-model="form.account" placeholder="请输入账号">
+                    <template #prefix>
+                      <el-icon><User /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="用户名" prop="nick_name">
+                  <el-input v-model="form.nick_name" placeholder="请输入用户名">
+                    <template #prefix>
+                      <el-icon><Avatar /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="工作单位" prop="unit">
+                  <el-input v-model="form.tel" placeholder="请输入工作单位">
+                    <template #prefix>
+                      <el-icon><OfficeBuilding /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="联系电话" prop="tel">
+                  <el-input v-model="form.tel" placeholder="请输入联系电话">
+                    <template #prefix>
+                      <el-icon><Iphone /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="身份证号" prop="id_card">
+                  <el-input v-model="form.id_card" placeholder="请输入身份证号">
+                    <template #prefix>
+                      <el-icon><ScaleToOriginal /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="联系邮箱" prop="email">
+                  <el-input v-model="form.email" placeholder="请输入联系邮箱">
+                    <template #prefix>
+                      <el-icon><Message /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="密码" prop="password">
+                  <el-input v-model="form.password" type="password" show-password placeholder="请输入登录密码">
+                    <template #prefix>
+                      <el-icon><Unlock /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="确认密码" prop="refpassword">
+                  <el-input v-model="form.refpassword" type="password" show-password placeholder="请再次确认输入密码">
+                    <template #prefix>
+                      <el-icon><Unlock /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-col :span="24" class="remark">
+                  <span @click="toLogin">已有账号去登录</span>
+                  <span @click="toBack">返回首页</span>
+                </el-col>
+                <el-col :span="24" class="button">
+                  <el-button type="primary" @click="submitForm(ruleFormRef)">注册</el-button>
+                </el-col>
+                <el-col :span="24" class="agree">
+                  <el-checkbox v-model="isAgree"></el-checkbox>
+                  <span style="margin: 0 0 0 5px">我已阅读并同意</span><span @click="toRegister">《{{ siteInfo.zhTitle }}使用协议》</span>
+                </el-col>
+              </el-form>
+            </el-col>
+            <el-col :span="24" class="content" v-show="activeName == '2'">
+              <el-form ref="ruleFormRef" :model="form" :rules="rules" label-width="80px" class="form" label-position="left">
+                <el-form-item label="账号" prop="account">
+                  <el-input v-model="form.account" placeholder="请输入账号">
+                    <template #prefix>
+                      <el-icon><User /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="用户名" prop="nick_name">
+                  <el-input v-model="form.nick_name" placeholder="请输入用户名">
+                    <template #prefix>
+                      <el-icon><Avatar /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="工作单位" prop="unit">
+                  <el-input v-model="form.tel" placeholder="请输入工作单位">
+                    <template #prefix>
+                      <el-icon><OfficeBuilding /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="联系电话" prop="tel">
+                  <el-input v-model="form.tel" placeholder="请输入联系电话">
+                    <template #prefix>
+                      <el-icon><Iphone /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="身份证号" prop="id_card">
+                  <el-input v-model="form.id_card" placeholder="请输入身份证号">
+                    <template #prefix>
+                      <el-icon><ScaleToOriginal /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="联系邮箱" prop="email">
+                  <el-input v-model="form.email" placeholder="请输入联系邮箱">
+                    <template #prefix>
+                      <el-icon><Message /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="密码" prop="password">
+                  <el-input v-model="form.password" type="password" show-password placeholder="请输入登录密码">
+                    <template #prefix>
+                      <el-icon><Unlock /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-form-item label="确认密码" prop="refpassword">
+                  <el-input v-model="form.refpassword" type="password" show-password placeholder="请再次确认输入密码">
+                    <template #prefix>
+                      <el-icon><Unlock /></el-icon>
+                    </template>
+                  </el-input>
+                </el-form-item>
+                <el-col :span="24" class="remark">
+                  <span @click="toLogin">已有账号去登录</span>
+                  <span @click="toBack">返回首页</span>
+                </el-col>
+                <el-col :span="24" class="button">
+                  <el-button type="primary" @click="submitForm(ruleFormRef)">注册</el-button>
+                </el-col>
+                <el-col :span="24" class="agree">
+                  <el-checkbox v-model="isAgree"></el-checkbox>
+                  <span style="margin: 0 0 0 5px">我已阅读并同意</span><span @click="toRegister">《{{ siteInfo.zhTitle }}使用协议》</span>
+                </el-col>
+              </el-form>
+            </el-col>
+          </div>
+        </el-col>
+        <cFoot></cFoot>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref, reactive } from 'vue';
+import type { FormInstance, FormRules } from 'element-plus';
+import { useRouter } from 'vue-router';
+import { siteInfo } from '@/layout/site';
+// // 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+// 路由
+const router = useRouter();
+// 加载中
+const loading: Ref<any> = ref(false);
+const form: Ref<any> = ref({});
+interface RuleForm {
+  account: string;
+  password: string;
+}
+const ruleFormRef = ref<FormInstance>();
+const rules = reactive<FormRules<RuleForm>>({
+  account: [{ required: true, message: '请输入账号', trigger: 'blur' }],
+  password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
+});
+const activeName: Ref<any> = ref(0);
+const isAgree: Ref<any> = ref(false);
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  search();
+  loading.value = false;
+});
+const search = async () => {
+  // let res: IQueryResult = await toolsAxios.dataCount();
+  // if (res.errcode == '0') {
+  //     info.value = res.data;
+  // }
+};
+// 选择
+const toTab = async (active) => {
+  activeName.value = active;
+};
+// 注册
+const submitForm = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+      console.log('submit!');
+    } else {
+      console.log('error submit!', fields);
+    }
+  });
+};
+// 去登录
+const toLogin = () => {
+  router.push({ path: '/login', query: { status: '0' } });
+};
+// 返回
+const toBack = () => {
+  router.push({ path: '/home' });
+};
+</script>
+<style scoped lang="scss">
+.main {
+  .two {
+    background-image: url(/src/assets/loginbg.jpg);
+    background-position: center center;
+    background-repeat: no-repeat;
+    height: 500px;
+    width: 100%;
+    background-size: cover;
+    display: flex;
+    justify-content: space-evenly;
+    .logo {
+      margin: 50px 0px 0px 0;
+      height: 420px;
+      opacity: 0.8;
+      .image {
+        width: 100%;
+        height: 100%;
+      }
+    }
+    .loginform {
+      margin: 50px 0 0 0;
+      padding: 20px 0 0 0;
+      width: 380px;
+      height: 422px;
+      background-color: #ffffff;
+      border-radius: 3px;
+      .tab {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        .title {
+          text-align: center;
+          margin: 0 20px;
+          font-family: PingFangSC-Semibold !important;
+          font-size: 15px;
+          letter-spacing: -0.14px;
+          line-height: 30px;
+          font-weight: bold;
+        }
+        .tab0 {
+          color: #1492ff;
+          border-bottom: 2px solid;
+          border-bottom-color: #1492ff;
+          padding-bottom: 10px;
+        }
+        .tab1 {
+          color: #333333;
+          padding-bottom: 10px;
+        }
+      }
+
+      .content {
+        margin: 30px 30px 0 30px;
+        height: 310px;
+        overflow-y: auto;
+        .remark {
+          display: flex;
+          justify-content: space-between;
+          span {
+            cursor: pointer;
+            font-family: PingFangSC-Regular;
+            font-size: 14px;
+            color: #333333;
+            letter-spacing: -0.09px;
+            text-align: right;
+            line-height: 32px;
+          }
+          span:hover {
+            color: #2374ff;
+          }
+        }
+        .button {
+          padding: 10px 0;
+          :deep(.el-button) {
+            width: 318px !important;
+            height: 44px !important;
+            border: 0 !important;
+            color: #f8f8f8 !important;
+            font-size: 16px !important;
+            text-align: center !important;
+            line-height: 40px !important;
+            cursor: pointer !important;
+            font-family: PingFangSC-Regular !important;
+            background-color: #1492ff !important;
+          }
+        }
+        .agree {
+          padding: 0 0 40px 0;
+          color: #999;
+          font-size: 12px;
+          span:last-child {
+            color: #2374ff;
+          }
+        }
+      }
+      .content::-webkit-scrollbar {
+        display: none;
+      }
+    }
+  }
+}
+</style>

+ 246 - 0
src/views/service/detail.vue

@@ -0,0 +1,246 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <cHead>
+          <template v-slot:info>
+            <div class="w_1200">
+              <el-row style="margin: 20px 0 0 0;">
+                <el-col :span="8" class="image">
+                  <el-image class="images" :src="info.url" fit="fill" />
+                </el-col>
+                <el-col :span="16" style="padding: 10px;">
+                  <el-col :span="24" class="one">
+                    <el-row :span="24" class="one_1">
+                      <el-col :span="20" class="title">{{ info.title || '暂无标题' }}</el-col>
+                      <el-col :span="4" class="file">
+                        <el-icon>
+                          <Download />
+                        </el-icon>
+                        附件下载
+                      </el-col>
+                    </el-row>
+                    <el-row :span="24" class="one_2"> 科技保险,科技担保,知识产权质押 </el-row>
+                  </el-col>
+                  <el-col :span="24" class="two">
+                    <a-descriptions bordered title="简介">
+                      <a-descriptions-item label="服务领域">
+                        电子信息、先进制造、城市建设与社会发展、新材料及其应用、生物、医药和医疗器械、新能源与高效、现代交通、环境保护与资源综合利用</a-descriptions-item>
+                      <a-descriptions-item label="服务方式">服务方式</a-descriptions-item>
+                      <a-descriptions-item label="服务地区">服务地区</a-descriptions-item>
+                      <a-descriptions-item label="发布时间">发布时间</a-descriptions-item>
+                    </a-descriptions>
+                  </el-col>
+                </el-col>
+              </el-row>
+              <el-col :span="24" class="thr">
+                <el-col :span="24" class="thr_1">单位信息</el-col>
+                <el-row :span="24" class="thr_2">
+                  <el-col :span="17" class="left">
+                    <el-col :span="24" class="name">
+                      {{ info.unit || '暂无' }}
+                    </el-col>
+                    <el-col :span="24" class="other"> <span>联系人</span>{{ info.unit || '暂无' }} </el-col>
+                  </el-col>
+                  <el-col :span="7" class="right">
+                    <a-button type="primary">
+                      <template #icon>
+                        <MessageOutlined />
+                      </template>
+                      点击在线洽谈
+                    </a-button>
+                    <a-button>进入单位</a-button>
+                    <a-button>收藏单位</a-button>
+                  </el-col>
+                </el-row>
+              </el-col>
+              <a-divider />
+              <el-col :span="24" class="four">
+                <a-tabs>
+                  <a-tab-pane tab="详情描述">{{ info.brief || '暂无' }}</a-tab-pane>
+                </a-tabs>
+              </el-col>
+            </div>
+          </template>
+        </cHead>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+import { useRoute } from 'vue-router';
+import { MessageOutlined } from '@ant-design/icons-vue';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+
+// 路由
+const route = useRoute();
+
+// 加载中
+const loading: Ref<any> = ref(false);
+const info: Ref<any> = ref({
+  unit: '吉林大学',
+  title: '科技金融服务',
+  time: '2024-01-05 09:12:23',
+  end_time: '2024-01-05 09:12:23',
+  money: '3',
+  url: '/src/assets/login.jpeg',
+  brief: '面向科技型企业提供天使投资、创业投资等股权投资服务'
+});
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search();
+  loading.value = false;
+});
+const search = async () => {
+  //   let id = route.query.id;
+  //   if (id) {
+  //     let res: IQueryResult = await userCheckAxios.fetch(id);
+  //     if (res.errcode == '0') {
+  //       let info: any = res.data as {};
+  //       form.value = info;
+  //       dataChange({ value: info.work_status, model: 'work_status' });
+  //     }
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/src/assets/detail.png) right top no-repeat;
+  background-size: 100%;
+
+  .image {
+    width: 100%;
+    height: 450px;
+    background-color: #fff;
+    border: 1px solid #edeff2;
+    display: flex;
+    align-items: center;
+    padding: 5px;
+  }
+
+  .one {
+    margin: 10px 0;
+
+    .one_1 {
+      margin: 5px 0;
+
+      .title {
+        font-size: 18px;
+        font-weight: 700;
+        color: #383b40;
+      }
+
+      .file {
+        display: flex;
+        align-items: center;
+        justify-content: end;
+        font-family: PingFangSC-Regular;
+        font-size: 14px;
+        color: #2374ff;
+        text-align: right;
+      }
+    }
+
+    .one_2 {
+      display: inline-block;
+      font-size: 12px;
+      background: rgba(18, 172, 117, .05);
+      color: #12ac75;
+      padding: 0 15px;
+      height: 20px;
+      line-height: 20px;
+      border-radius: 10px;
+      margin-bottom: 2px;
+    }
+  }
+
+  .two {
+    background: #f9fafb;
+    border-radius: 2px;
+    padding: 30px;
+    margin: 34px 0 20px;
+    font-family: PingFangSC-Medium;
+    font-size: 14px;
+    color: #383b40;
+    line-height: 14px;
+  }
+
+  .thr {
+    margin: 0 0 10px 0;
+
+    .thr_1 {
+      margin-bottom: 20px;
+      font-size: 18px;
+      font-weight: 700;
+      color: #383b40;
+    }
+
+    .thr_2 {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      background: #fff;
+      border: 1px solid #edeff2;
+      box-shadow: 0 4px 10px 0 rgba(0, 0, 0, .03);
+      border-radius: 2px;
+      padding: 30px 20px;
+
+      .left {
+        .name {
+          height: 20px;
+          font-family: PingFangSC-Semibold;
+          font-size: 18px;
+          color: #383b40;
+          line-height: 20px;
+          font-weight: 700;
+          margin-bottom: 8px;
+        }
+
+        .other {
+          height: 14px;
+          font-family: PingFangSC-Medium;
+          font-size: 14px;
+          color: #383b40;
+          line-height: 14px;
+          font-weight: 700;
+
+          span {
+            height: 14px;
+            font-family: PingFangSC-Regular;
+            font-size: 14px;
+            color: #7e8288;
+            line-height: 14px;
+            font-weight: 400;
+            margin-right: 16px;
+          }
+        }
+      }
+
+      .right {
+        display: flex;
+        justify-content: space-between;
+      }
+    }
+  }
+
+  .four {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 235 - 0
src/views/service/index.vue

@@ -0,0 +1,235 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <cSearch :is_title="false" :is_search="true" :fields="fields" @search="toSearch"> </cSearch>
+          </el-col>
+          <el-col :span="24" class="two">
+            <a-list :loading="loading" :grid="{ gutter: 16, column: 4 }" :data-source="list">
+              <template #renderItem="{ item }">
+                <el-col :span="24" class="list" @click="toView(item)">
+                  <el-col :span="24" class="top">
+                    <el-image class="image" :src="item.url" fit="fill" />
+                  </el-col>
+                  <el-col :span="24" class="bottom">
+                    <el-col :span="24" class="name textOver">
+                      <el-tooltip effect="dark" :content="item.name" placement="top">
+                        {{ item.name || '暂无名称' }}
+                      </el-tooltip>
+                    </el-col>
+                    <el-col :span="24" class="two_1"> <span>机构名称: </span>{{ item.unit || '暂无机构名称' }} </el-col>
+                    <el-col :span="24" class="two_1"> <span>地区: </span>{{ item.city || '暂无地区' }} </el-col>
+                  </el-col>
+                </el-col>
+              </template>
+            </a-list>
+          </el-col>
+          <el-col :span="24" class="thr">
+            <a-pagination v-model:page-size="limit" show-size-changer :page-size-options="pageSizeOptions" :total="total" @showSizeChange="onShowSizeChange" />
+          </el-col>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, getCurrentInstance, ref } from 'vue';
+import { useRouter } from 'vue-router';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+const { proxy } = getCurrentInstance() as any;
+
+// 路由
+const router = useRouter();
+// 加载中
+const loading: Ref<any> = ref(false);
+let list: Ref<any> = ref([
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司',
+    url: '/src/assets/video_1.png'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    url: '/src/assets/video_1.png',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    url: '/src/assets/video_1.png',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    url: '/src/assets/video_1.png',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    url: '/src/assets/video_1.png',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    url: '/src/assets/video_1.png',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    url: '/src/assets/video_1.png',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    url: '/src/assets/video_1.png',
+    unit: '浙江易丰安全科技有限公司'
+  },
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    url: '/src/assets/video_1.png',
+    unit: '浙江易丰安全科技有限公司'
+  }
+]);
+let total: Ref<number> = ref(12);
+let skip = 0;
+let limit: number = proxy.$limit;
+const pageSizeOptions = ref<string[]>(['12', '24', '60', '120']);
+// 查询数据
+let searchForm: Ref<any> = ref({});
+let fields: Ref<any[]> = ref([
+  { label: '服务类型', model: 'type', isSearch: true },
+  { label: '服务方式', model: 'label', isSearch: true },
+  { label: '服务地区', model: 'value', isSearch: true }
+]);
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search({ skip, limit });
+  loading.value = false;
+});
+const search = async (e: { skip: number; limit: number }) => {
+  const info = { skip: e.skip, limit: e.limit };
+  //   const res: IQueryResult = await userCheckAxios.query(info);
+  //   if (res.errcode == '0') {
+  //     list.value = res.data;
+  //     total.value = res.total;
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+const toSearch = (query) => {
+  searchForm.value = query;
+  search({ skip, limit });
+};
+// 服务大厅查看详情
+const toView = (item) => {
+  router.push({ path: '/service/detail', query: { id: item.id || item._id } });
+};
+const onShowSizeChange = (current: number, pageSize: number) => {
+  console.log(current, pageSize);
+  limit = pageSize;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/src/assets/detail.png) right top no-repeat;
+  background-size: 100%;
+  .one {}
+
+  .two {
+    .list {
+      background: #fff;
+      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.03);
+      border-radius: 2px;
+      width: 282px;
+      height: 300px;
+      margin-bottom: 30px;
+      cursor: pointer;
+      transition: all 0.3s;
+
+      .top {
+        width: 100%;
+        height: 158px;
+
+        .image {
+          width: 100%;
+          height: 158px;
+        }
+      }
+
+      .bottom {
+        padding: 12px 20px 20px;
+
+        .name {
+          font-size: 16px;
+          color: #121834;
+          height: 16px;
+          line-height: 13px;
+          font-weight: 500;
+          margin: 10px 0;
+        }
+
+        .name:hover {
+          color: #2374ff;
+        }
+
+        .two_1 {
+          font-size: 12px;
+          text-align: justify;
+          line-height: 12px;
+          font-weight: 400;
+          letter-spacing: 0;
+          color: #8f97a3;
+          margin-top: 15px;
+
+          span:last-child {
+            color: #525a68;
+          }
+        }
+      }
+    }
+
+    .list:hover {
+      background: #f0f7ff;
+      box-shadow: 0 0 16px rgba(205, 205, 205, 0.6);
+    }
+  }
+
+  .thr {
+    display: flex;
+    flex-direction: row-reverse;
+    padding: 0 0 10px 0;
+  }
+}
+</style>

Diff do ficheiro suprimidas por serem muito extensas
+ 266 - 0
src/views/trade/detail.vue


+ 280 - 0
src/views/trade/one.vue

@@ -0,0 +1,280 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <cSearch :is_title="false" :is_search="true" :fields="fields" @search="toSearch"> </cSearch>
+          </el-col>
+          <el-col :span="24" class="two">
+            <a-list :loading="loading" :grid="{ gutter: 16, column: 4 }" :data-source="list">
+              <template #renderItem="{ item }">
+                <el-col :span="24" class="list">
+                  <el-col :span="24" class="name textOver">
+                    <el-tooltip effect="dark" :content="item.name" placement="top">
+                      {{ item.name || '暂无名称' }}
+                    </el-tooltip>
+                  </el-col>
+                  <el-col :span="24" class="two_1"> <span>服务机构: </span>{{ item.unit || '暂无服务机构' }} </el-col>
+                  <el-col :span="24" class="two_1"> <span>项目编号: </span>{{ item.no || '暂无项目编号' }} </el-col>
+                  <el-col :span="24" class="two_1"> <span>发布日期: </span>{{ item.notice_time || '暂无发布日期' }} </el-col>
+                  <el-col :span="24" class="bottom">
+                    <div class="status">挂牌公告</div>
+                    <div class="button" @click="toView">查看详情</div>
+                  </el-col>
+                </el-col>
+              </template>
+            </a-list>
+          </el-col>
+          <el-col :span="24" class="thr">
+            <a-pagination v-model:page-size="limit" show-size-changer :page-size-options="pageSizeOptions" :total="total" @showSizeChange="onShowSizeChange" />
+          </el-col>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, getCurrentInstance, ref } from 'vue';
+import { useRouter } from 'vue-router';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+const { proxy } = getCurrentInstance() as any;
+
+// 路由
+const router = useRouter();
+// 加载中
+const loading: Ref<any> = ref(false);
+let list: Ref<any> = ref([
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  }
+]);
+let total: Ref<number> = ref(12);
+let skip = 0;
+let limit: number = proxy.$limit;
+const pageSizeOptions = ref<string[]>(['12', '24', '60', '120']);
+// 查询数据
+let searchForm: Ref<any> = ref({});
+let fields: Ref<any[]> = ref([{ label: '公示/公告类型', model: 'type', isSearch: true }]);
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search({ skip, limit });
+  loading.value = false;
+});
+const search = async (e: { skip: number; limit: number }) => {
+  // const info = { skip: e.skip, limit: e.limit };
+  //   const res: IQueryResult = await userCheckAxios.query(info);
+  //   if (res.errcode == '0') {
+  //     list.value = res.data;
+  //     total.value = res.total;
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+const toSearch = (query) => {
+  searchForm.value = query;
+  search({ skip, limit });
+};
+// 交易大厅查看详情
+const toView = (item) => {
+  router.push({ path: '/trade/detail', query: { id: item.id || item._id } });
+};
+const onShowSizeChange = (current: number, pageSize: number) => {
+  console.log(current, pageSize);
+  limit = pageSize;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/src/assets/detail.png) right top no-repeat;
+  background-size: 100%;
+  .one {}
+
+  .two {
+    .list {
+      background: #fff;
+      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.03);
+      border-radius: 2px;
+      width: 282px;
+      height: 194px;
+      margin-bottom: 30px;
+      cursor: pointer;
+      transition: all 0.3s;
+      padding: 20px;
+
+      .name {
+        font-size: 16px;
+        color: #121834;
+        height: 16px;
+        line-height: 13px;
+        font-weight: 500;
+        margin: 10px 0;
+      }
+
+      .name:hover {
+        color: #2374ff;
+      }
+
+      .two_1 {
+        font-size: 12px;
+        text-align: justify;
+        line-height: 12px;
+        font-weight: 400;
+        letter-spacing: 0;
+        color: #8f97a3;
+        margin-top: 15px;
+
+        span:last-child {
+          color: #525a68;
+        }
+      }
+
+      .bottom {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        margin-top: 20px;
+
+        .status {
+          padding: 5px 12px;
+          font-size: 12px;
+          color: #2374ff;
+          line-height: 12px;
+          font-weight: 400;
+          background: rgba(35, 116, 255, 0.05);
+          border-radius: 16px;
+        }
+
+        .button {
+          font-size: 12px;
+          color: #fff;
+          text-align: center;
+          line-height: 12px;
+          font-weight: 500;
+          padding: 5px 12px;
+          background: #2374ff;
+          box-shadow: 0 3px 6px 0 rgba(35, 116, 255, 0.1);
+          border-radius: 2px;
+        }
+      }
+    }
+
+    .list:hover {
+      background: #f0f7ff;
+      box-shadow: 0 0 16px rgba(205, 205, 205, 0.6);
+    }
+  }
+
+  .thr {
+    display: flex;
+    flex-direction: row-reverse;
+    padding: 0 0 10px 0;
+  }
+}
+</style>

+ 238 - 0
src/views/trade/two.vue

@@ -0,0 +1,238 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <cSearch :is_title="false" :is_search="true" :fields="fields" @search="toSearch"> </cSearch>
+          </el-col>
+          <el-col :span="24" class="two">
+            <a-list item-layout="vertical" :loading="loading" :data-source="list">
+              <template #renderItem="{ item }">
+                <a-list-item key="item.name" @click="toView(item)">
+                  <template #extra>
+                    <img width="272" alt="logo" src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png" />
+                  </template>
+                  <el-col :span="24" class="name textOver">
+                    <el-tooltip effect="dark" :content="item.name" placement="top">
+                      {{ item.name || '暂无名称' }}
+                    </el-tooltip>
+                  </el-col>
+                  <el-col :span="24" class="two_1"> <span>服务机构: </span>{{ item.unit || '暂无服务机构' }} </el-col>
+                  <el-col :span="24" class="two_1"> <span>项目编号: </span>{{ item.no || '暂无项目编号' }} </el-col>
+                  <el-col :span="24" class="two_1"> <span>发布日期: </span>{{ item.notice_time || '暂无发布日期' }} </el-col>
+                </a-list-item>
+              </template>
+            </a-list>
+          </el-col>
+          <el-col :span="24" class="thr">
+            <a-pagination v-model:page-size="limit" show-size-changer :page-size-options="pageSizeOptions" :total="total"
+              @showSizeChange="onShowSizeChange" />
+          </el-col>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, getCurrentInstance, ref } from 'vue';
+import { useRouter } from 'vue-router';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+const { proxy } = getCurrentInstance() as any;
+
+// 路由
+const router = useRouter();
+// 加载中
+const loading: Ref<any> = ref(false);
+let list: Ref<any> = ref([
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种利用动物软骨制备硫酸软骨素和胶原蛋白多肽的方法成果的转让',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '数字矫形肢体骨骼康复机器辅助系统',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '一种老黄酶NemR-PS突变体及其在制备(S)-香茅醇中的应用等2种成果',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  },
+  {
+    name: '常规早稻新品种“浙早33”的相关培育技术',
+    no: 'XY20231215012',
+    unit: '浙江工业大学',
+    notice_time: '2023-12-15 17:47:19',
+    end_time: '2023-12-25 17:47:19',
+    status: '0'
+  }
+]);
+let total: Ref<number> = ref(12);
+let skip = 0;
+let limit: number = proxy.$limit;
+const pageSizeOptions = ref<string[]>(['12', '24', '60', '120']);
+// 查询数据
+let searchForm: Ref<any> = ref({});
+let fields: Ref<any[]> = ref([
+  { label: '展示形式', model: 'type', isSearch: true },
+  { label: '公告(报名)开始时间', model: 'label', isSearch: true },
+  { label: '竞价(拍卖)开始时间', model: 'value', isSearch: true },
+  { label: '竞价主体', model: 'sort', isSearch: true },
+  { label: '交易类型', model: 'sort', isSearch: true }
+]);
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  await searchOther();
+  await search({ skip, limit });
+  loading.value = false;
+});
+const search = async (e: { skip: number; limit: number }) => {
+  const info = { skip: e.skip, limit: e.limit };
+  //   const res: IQueryResult = await userCheckAxios.query(info);
+  //   if (res.errcode == '0') {
+  //     list.value = res.data;
+  //     total.value = res.total;
+  //   }
+};
+// 查询其他信息
+const searchOther = async () => {
+  //   let res: IQueryResult;
+  //   // 性别
+  //   res = await dictAxios.query({ type: 'common_gender' });
+  //   if (res.errcode == '0') genderList.value = res.data;
+};
+const toSearch = (query) => {
+  searchForm.value = query;
+  search({ skip, limit });
+};
+// 交易大厅查看详情
+const toView = (item) => {
+  router.push({ path: '/trade/detail', query: { id: item.id || item._id } });
+};
+const onShowSizeChange = (current: number, pageSize: number) => {
+  console.log(current, pageSize);
+  limit = pageSize;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  .one {}
+
+  .two {
+    .name {
+      height: 28px;
+      font-size: 20px;
+      color: #383b40;
+      line-height: 28px;
+      font-weight: 600;
+      margin-bottom: 12px;
+    }
+
+    .name:hover {
+      color: #2374ff;
+    }
+
+    .two_1 {
+      font-size: 14px;
+      text-align: justify;
+      line-height: 14px;
+      font-weight: 400;
+      letter-spacing: 0;
+      color: #8f97a3;
+      margin-top: 20px;
+
+      span:last-child {
+        color: #525a68;
+      }
+    }
+  }
+
+  .thr {
+    display: flex;
+    flex-direction: row-reverse;
+    padding: 0 0 10px 0;
+  }
+}
+</style>

+ 14 - 0
tsconfig.app.json

@@ -0,0 +1,14 @@
+{
+  "extends": "@vue/tsconfig/tsconfig.dom.json",
+  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
+  "exclude": ["src/**/__tests__/*"],
+  "compilerOptions": {
+    "composite": true,
+    "baseUrl": ".",
+    "module" : "ESNext",
+    "moduleResolution": "Node",
+    "paths": {
+      "@/*": ["./src/*"]
+    }
+  }
+}

+ 37 - 0
tsconfig.json

@@ -0,0 +1,37 @@
+{
+  // "extends": "@vue/tsconfig/tsconfig.web.json",
+  // "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "../common/src/stores/user", "../common/src/stores/user"],
+  "include": [
+    "src/**/*.ts",
+    "src/**/*.d.ts",
+    "src/**/*.tsx",
+    "src/**/*.vue",
+    "src/untils/baiduMap.js",
+    "src/untils/debuonce.js",
+    "**/*.ts",
+    "**/*.tsx"
+  ],
+  "compilerOptions": {
+    "ignoreDeprecations": "5.0",
+    "target": "esnext",
+    "module": "ESNext",
+    "strict": false,
+    "jsx": "preserve",
+    "moduleResolution": "Node",
+    "baseUrl": "./",
+    "paths": {
+      "@/*": ["./src/*"]
+    },
+    "isolatedModules": false,
+    "sourceMap": true,
+    "resolveJsonModule": true,
+    "esModuleInterop": true,
+    "lib": ["es5", "es6", "dom", "dom.iterable"],
+    "allowSyntheticDefaultImports": true
+  },
+  "references": [
+    {
+      "path": "./tsconfig.node.json"
+    }
+  ]
+}

+ 18 - 0
tsconfig.node.json

@@ -0,0 +1,18 @@
+{
+  // "extends": "@vue/tsconfig/tsconfig.node.json",
+  "include": [
+    "vite.config.*",
+    "vitest.config.*",
+    "cypress.config.*",
+    "playwright.config.*"
+  ],
+  "compilerOptions": {
+    "ignoreDeprecations": "5.0",
+    "module" : "ESNext",
+    "moduleResolution": "Node",
+    "composite": true,
+    "types": [
+      "node"
+    ]
+  }
+}

+ 35 - 0
vite.config.ts

@@ -0,0 +1,35 @@
+import { fileURLToPath, URL } from 'node:url';
+import { defineConfig, loadEnv } from 'vite';
+import vue from '@vitejs/plugin-vue';
+export default defineConfig(({ mode }) => {
+  const env = loadEnv(mode, __dirname);
+  return {
+    // 静态路径
+    base: env.VITE_BASE_URL,
+    // 打包名称
+    build: {
+      outDir: env.VITE_OUT_DIR
+    },
+    plugins: [vue()],
+    server: {
+      port: 9002,
+      proxy: {
+        '/file': {
+          target: 'https://broadcast.waityou24.cn',
+          changeOrigin: true
+        },
+        '/field/v1/api': {
+          target: 'https://broadcast.waityou24.cn',
+          changeOrigin: true,
+          ws: false
+        }
+      },
+      fs: { strict: false }
+    },
+    resolve: {
+      alias: {
+        '@': fileURLToPath(new URL('./src', import.meta.url))
+      }
+    }
+  };
+});