zs 1 anno fa
commit
f9fdcc3fb5
76 ha cambiato i file con 14660 aggiunte e 0 eliminazioni
  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. 6 0
      env.d.ts
  9. 16 0
      index.html
  10. 9843 0
      package-lock.json
  11. 51 0
      package.json
  12. BIN
      public/favicon.ico
  13. 34 0
      src/App.vue
  14. BIN
      src/assets/achievement.png
  15. 0 0
      src/assets/base.css
  16. BIN
      src/assets/brain.png
  17. BIN
      src/assets/code.png
  18. BIN
      src/assets/demand.png
  19. BIN
      src/assets/home.jpg
  20. BIN
      src/assets/home.mp4
  21. BIN
      src/assets/home_1.png
  22. BIN
      src/assets/home_2.png
  23. BIN
      src/assets/home_3.png
  24. BIN
      src/assets/home_4.png
  25. BIN
      src/assets/homebg.png
  26. 95 0
      src/assets/icon/iconfont.css
  27. 1 0
      src/assets/icon/iconfont.js
  28. 149 0
      src/assets/icon/iconfont.json
  29. BIN
      src/assets/icon/iconfont.ttf
  30. BIN
      src/assets/icon/iconfont.woff
  31. BIN
      src/assets/icon/iconfont.woff2
  32. BIN
      src/assets/innovation.png
  33. BIN
      src/assets/loginbg.jpeg
  34. BIN
      src/assets/logo.png
  35. 1 0
      src/assets/logo.svg
  36. 19 0
      src/assets/main.css
  37. BIN
      src/assets/map.jpg
  38. BIN
      src/assets/new_1.png
  39. BIN
      src/assets/new_2.png
  40. BIN
      src/assets/new_3.png
  41. BIN
      src/assets/new_4.png
  42. BIN
      src/assets/new_5.png
  43. BIN
      src/assets/news.png
  44. BIN
      src/assets/unit.png
  45. BIN
      src/assets/video.mp4
  46. BIN
      src/assets/video_1.png
  47. BIN
      src/assets/video_2.jpg
  48. BIN
      src/assets/videobg.png
  49. 194 0
      src/components/head.vue
  50. 8 0
      src/components/index.ts
  51. 187 0
      src/components/video.vue
  52. 24 0
      src/layout/site.ts
  53. 50 0
      src/main.ts
  54. 66 0
      src/router/index.ts
  55. 12 0
      src/stores/counter.ts
  56. 150 0
      src/util/axios-wrapper.ts
  57. 29 0
      src/util/types.util.ts
  58. 264 0
      src/views/achievement/detail.vue
  59. 259 0
      src/views/demand/detail.vue
  60. 155 0
      src/views/help/index.vue
  61. 418 0
      src/views/home/components/achievement.vue
  62. 195 0
      src/views/home/components/brain.vue
  63. 349 0
      src/views/home/components/demand.vue
  64. 223 0
      src/views/home/components/home.vue
  65. 50 0
      src/views/home/components/innovation.vue
  66. 317 0
      src/views/home/components/news.vue
  67. 169 0
      src/views/home/index.vue
  68. 217 0
      src/views/index/index.vue
  69. 262 0
      src/views/login/index.vue
  70. 102 0
      src/views/news/detail.vue
  71. 48 0
      src/views/news/index.vue
  72. 460 0
      src/views/register/index.vue
  73. 14 0
      tsconfig.app.json
  74. 37 0
      tsconfig.json
  75. 18 0
      tsconfig.node.json
  76. 36 0
      vite.config.ts

+ 7 - 0
.env.development

@@ -0,0 +1,7 @@
+VITE_BASE_URL = "/"
+VITE_OUT_DIR = "technique"
+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 = "/technique"
+VITE_OUT_DIR = "technique"
+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*
+zdlyjszyWeb2/
+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
+```

+ 6 - 0
env.d.ts

@@ -0,0 +1,6 @@
+/// <reference types="vite/client" />
+interface ImportMetaEnv {
+  VITE_BASE_URL: string;
+  VITE_OUT_DIR: string;
+}
+declare module '@dataview/datav-vue3';

+ 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>

File diff suppressed because it is too large
+ 9843 - 0
package-lock.json


+ 51 - 0
package.json

@@ -0,0 +1,51 @@
+{
+  "name": "technique_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": {
+    "@dataview/datav-vue3": "^0.0.0-test.1672506674342",
+    "@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",
+    "swiper": "^11.0.5",
+    "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


+ 34 - 0
src/App.vue

@@ -0,0 +1,34 @@
+<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;
+  font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
+}
+.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/achievement.png


+ 0 - 0
src/assets/base.css


BIN
src/assets/brain.png


BIN
src/assets/code.png


BIN
src/assets/demand.png


BIN
src/assets/home.jpg


BIN
src/assets/home.mp4


BIN
src/assets/home_1.png


BIN
src/assets/home_2.png


BIN
src/assets/home_3.png


BIN
src/assets/home_4.png


BIN
src/assets/homebg.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";
+}
+

File diff suppressed because it is too large
+ 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/innovation.png


BIN
src/assets/loginbg.jpeg


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/map.jpg


BIN
src/assets/new_1.png


BIN
src/assets/new_2.png


BIN
src/assets/new_3.png


BIN
src/assets/new_4.png


BIN
src/assets/new_5.png


BIN
src/assets/news.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


+ 194 - 0
src/components/head.vue

@@ -0,0 +1,194 @@
+<template>
+  <div class="header">
+    <div class="top">
+      <el-row :gutter="20" align="middle">
+        <el-col :span="9" class="top_1">
+          <el-image class="image" :src="siteInfo.logoUrl" fit="fill" />
+          <div class="content">
+            <text class="title">{{ siteInfo.zhTitle }}</text>
+            <text class="english">{{ siteInfo.zhBrief }}</text>
+          </div>
+        </el-col>
+        <el-col :span="11">
+          <a-tabs v-model:activeKey="current" size="large" @tabClick="selectMenu">
+            <a-tab-pane key="home" tab="首页"> </a-tab-pane>
+            <a-tab-pane key="news" tab="政策新闻"> </a-tab-pane>
+            <a-tab-pane key="brain" tab="新闻咨询"> </a-tab-pane>
+            <a-tab-pane key="demand" tab="供需商城"> </a-tab-pane>
+            <a-tab-pane key="innovation" tab="创新大赛"> </a-tab-pane>
+            <a-tab-pane key="achievement" tab="成果展示"> </a-tab-pane>
+          </a-tabs>
+        </el-col>
+        <el-col :span="4">
+          <el-row :gutter="20">
+            <el-col :span="5">
+              <SearchOutlined />
+            </el-col>
+            <el-col :span="12" class="top_3">
+              <text @click="toLogin(1)">登录</text>
+              <text>|</text>
+              <text @click="toLogin(2)">注册</text>
+            </el-col>
+          </el-row>
+        </el-col>
+      </el-row>
+    </div>
+    <div class="center">
+      <slot name="info"></slot>
+    </div>
+    <div class="bottom">
+      <div class="w_1200 footflex">
+        <el-image class="image" :src="unit" 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" @click="toHelp('1')">关于我们</span> <span class="footSpan" @click="toHelp('2')">意见反馈</span>
+          </div>
+          <div class="footTitle footflex1">
+            <span class="footSpan" @click="toHelp('3')">联系我们</span> <span class="footSpan" @click="toHelp('4')">法律条款</span>
+          </div>
+        </el-col>
+        <el-col :span="4" class="foot_3 footflex">
+          <el-image class="image" :src="code" fit="fill" />
+          <el-image class="image" :src="code" fit="fill" />
+        </el-col>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import { ref, toRefs } from 'vue';
+import { siteInfo } from '@/layout/site';
+import { useRouter } from 'vue-router';
+import { SearchOutlined } from '@ant-design/icons-vue';
+// 图片引入
+import code from '@/assets/code.png';
+import unit from '@/assets/unit.png';
+const router = useRouter();
+const props = defineProps({
+  activeKey: { type: String, default: 'home' }
+});
+const { activeKey } = toRefs(props);
+const current = ref<any>(localStorage.getItem('href') || activeKey.value);
+// 选择菜单
+const emit = defineEmits(['selectMenu']);
+const selectMenu = (item) => {
+  current.value = item;
+  emit('selectMenu', item);
+};
+// 登录|注册
+const toLogin = (status) => {
+  router.push({ path: '/login', query: { status } });
+};
+// 帮助中心
+const toHelp = (type) => {
+  router.push({ path: '/help', query: { type } });
+};
+</script>
+<style scoped lang="scss">
+.header {
+  min-height: 100vh;
+  min-width: 1200px;
+
+  .top {
+    position: sticky;
+    top: 0;
+    z-index: 99999;
+    padding: 0 80px;
+    background: #ffffff;
+
+    .top_1 {
+      display: flex;
+      align-items: center;
+
+      .image {
+        height: 45px;
+        width: 45px;
+      }
+
+      .content {
+        margin: 0 0 0 5px;
+
+        .title {
+          margin: 0 0 5px 0;
+          font-size: 23px;
+          font-weight: bold;
+        }
+
+        .english {
+          margin: 0 0 0 5px;
+          font-size: 12px;
+          opacity: 0.8;
+          color: #1c66e7;
+        }
+      }
+    }
+    :deep(.ant-tabs-nav) {
+      margin: 0 !important;
+    }
+
+    :deep(.ant-tabs-nav::before) {
+      border: 0 !important;
+    }
+    .top_3 {
+      display: flex;
+      justify-content: space-between;
+    }
+  }
+
+  .center {
+    margin: 0 0 20vh 0;
+  }
+
+  .bottom {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    padding: 7px 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>

+ 8 - 0
src/components/index.ts

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

+ 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>

+ 24 - 0
src/layout/site.ts

@@ -0,0 +1,24 @@
+// 图片引入
+import logo from '@/assets/logo.png';
+import home from '@/assets/home.jpg';
+// 网站基本设置
+export const siteInfo = {
+  display: false,
+  zhTitle: '新一代信息技术孵化平台',
+  zhEnglish: 'Information Technology Incubation Platform',
+  zhBrief: '方寸心间 创新无限',
+  zhAddress: '吉林省长春市前进大街力旺广场',
+  zhPhone: '400-469-1899',
+  zhMailbox: '123456789@.com',
+  logoUrl: logo,
+  videoUrl: home
+};
+// 菜单设置
+export const menuList = [
+  { title: '首页', href: 'home', English: 'Home' },
+  { title: '政策新闻', href: 'news', English: 'Policy News' },
+  { title: '新闻资讯', href: 'brain', English: 'News Information' },
+  { title: '供需商城', href: 'demand', English: 'Demand Mall' },
+  { title: '创新大赛', href: 'innovation', English: 'Innovation Competition' },
+  { title: '成果展示', href: 'achievement', English: 'Achievement Display' }
+];

+ 50 - 0
src/main.ts

@@ -0,0 +1,50 @@
+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';
+
+// Antd
+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, { name: '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');

+ 66 - 0
src/router/index.ts

@@ -0,0 +1,66 @@
+import { createRouter, createWebHistory } from 'vue-router';
+const router = createRouter({
+  history: createWebHistory(import.meta.env.BASE_URL),
+  routes: [
+    {
+      path: '/',
+      redirect: '/index'
+    },
+    {
+      path: '/index',
+      name: 'index',
+      meta: { title: '吉林省信息技术孵化平台' },
+      component: () => import('@/views/index/index.vue')
+    },
+    {
+      path: '/home',
+      name: 'home',
+      meta: { title: '吉林省信息技术孵化平台' },
+      component: () => import('@/views/home/index.vue')
+    },
+    {
+      path: '/achievement/detail',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/achievement/detail.vue')
+    },
+    {
+      path: '/demand/detail',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/demand/detail.vue')
+    },
+    {
+      path: '/news',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/news/index.vue')
+    },
+    {
+      path: '/news/detail',
+      meta: { title: '吉林省重点领域技术转移平台' },
+      component: () => import('@/views/news/detail.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: '/help',
+      meta: { title: '吉林省信息技术孵化平台-帮助中心' },
+      component: () => import('@/views/help/index.vue')
+    }
+  ]
+});
+router.beforeEach(async (to) => {
+  document.title = `${to.meta.title} `;
+});
+router.afterEach(() => {
+  window.scrollTo(0, 0);
+});
+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;
+}

+ 264 - 0
src/views/achievement/detail.vue

@@ -0,0 +1,264 @@
+<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>
+                  <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">
+                  <p>单位信息</p>
+                </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">
+                <el-col :span="24" class="four_1">
+                  <p>成果描述</p>
+                </el-col>
+                <el-col :span="24" class="four_2">{{ info.brief || '暂无' }}</el-col>
+              </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 {
+  .one {
+    margin: 10px 0 0 0;
+    background: #f7f7f7;
+    padding: 24px;
+    border-top: 6px solid #2374ff;
+    overflow: hidden;
+    border-radius: 0 0 5px 5px;
+
+    .one_1 {
+      margin: 0 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 {
+      width: 100%;
+      height: 40px;
+      line-height: 40px;
+      border-bottom: 2px solid #2374ff;
+      margin: 20px 0;
+      background: #f7f7f7;
+
+      p {
+        float: left;
+        padding: 0 20px;
+        height: 40px;
+        border-bottom: 2px solid #2374ff;
+        color: #fff;
+        font-size: 18px;
+        background: #2374ff;
+      }
+    }
+
+    .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;
+
+    .four_1 {
+      width: 100%;
+      height: 40px;
+      line-height: 40px;
+      border-bottom: 2px solid #2374ff;
+      margin: 20px 0;
+      background: #f7f7f7;
+
+      p {
+        float: left;
+        padding: 0 20px;
+        height: 40px;
+        border-bottom: 2px solid #2374ff;
+        color: #fff;
+        font-size: 18px;
+        background: #2374ff;
+      }
+    }
+  }
+}
+</style>

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

@@ -0,0 +1,259 @@
+<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>
+                  <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">
+                  <p>单位信息</p>
+                </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">
+                <el-col :span="24" class="four_1">
+                  <p>需求详情</p>
+                </el-col>
+                <el-col :span="24" class="four_2">{{ info.brief || '暂无' }}</el-col>
+              </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 {
+  .one {
+    margin: 10px 0 0 0;
+    background: #f7f7f7;
+    padding: 24px;
+    border-top: 6px solid #2374ff;
+    overflow: hidden;
+    border-radius: 0 0 5px 5px;
+
+    .one_1 {
+      margin: 0 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 {
+      width: 100%;
+      height: 40px;
+      line-height: 40px;
+      border-bottom: 2px solid #2374ff;
+      margin: 20px 0;
+      background: #f7f7f7;
+
+      p {
+        float: left;
+        padding: 0 20px;
+        height: 40px;
+        border-bottom: 2px solid #2374ff;
+        color: #fff;
+        font-size: 18px;
+        background: #2374ff;
+      }
+    }
+
+    .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;
+
+    .four_1 {
+      width: 100%;
+      height: 40px;
+      line-height: 40px;
+      border-bottom: 2px solid #2374ff;
+      margin: 20px 0;
+      background: #f7f7f7;
+
+      p {
+        float: left;
+        padding: 0 20px;
+        height: 40px;
+        border-bottom: 2px solid #2374ff;
+        color: #fff;
+        font-size: 18px;
+        background: #2374ff;
+      }
+    }
+  }
+}
+</style>

+ 155 - 0
src/views/help/index.vue

@@ -0,0 +1,155 @@
+<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 class="help">
+                <el-col :span="6" class="left">
+                  <a-menu v-model:selectedKeys="selectedKeys" style="width: 256px" mode="inline" :items="menuList" @select="onOpenChange"></a-menu>
+                </el-col>
+                <el-col v-if="select === '1'" :span="18" class="right">
+                  <h2>关于我们</h2>
+                  <el-col :span="24" class="other">
+                    吉林省重点领域技术转移平台是全国最早开设的大型常设网上技术交易市场,为我国探索网上技术交易提供了大量的“浙江经验”。
+                    吉林省重点领域技术转移平台3.0版按照全要素聚集、全链条服务、全球化生态的规划思路升级建设,将打造统一的科技成果交易体系、服务体系、统计监测分析体系,构建线上线下、有形无形、国际国内一体化的技术市场体系,形成“招拍挂、股改投”联动的技术交易模式和辐射全国、链接全球的技术交易生态。
+                  </el-col>
+                </el-col>
+                <el-col v-else-if="select === '2'" :span="18" class="right">意见反馈</el-col>
+                <el-col v-else-if="select === '3'" :span="18" class="right">
+                  <el-row :gutter="20">
+                    <el-col :span="12" class="left">
+                      <el-image class="image" :src="map" fit="fill" />
+                    </el-col>
+                    <el-col :span="12" class="right">
+                      <el-col :span="24" class="other">
+                        <el-icon color="#2374ff">
+                          <Message />
+                        </el-icon>
+                        <span>联系我们</span> 吉林省科技开发交流中心
+                      </el-col>
+                      <el-col :span="24" class="other">
+                        <el-icon color="#2374ff">
+                          <Location />
+                        </el-icon>
+                        <span>联系地址</span>长春朝阳区前进大街1244号(吉林省科技厅科研园)
+                      </el-col>
+                      <el-col :span="24" class="other">
+                        <el-icon color="#2374ff">
+                          <Iphone />
+                        </el-icon>
+                        <span>联系电话</span> 0431-81165166
+                      </el-col>
+                    </el-col>
+                  </el-row>
+                </el-col>
+                <el-col v-else-if="select === '4'" :span="18" class="right">法律条款</el-col>
+              </el-row>
+            </div>
+          </template>
+        </cHead>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref, reactive } from 'vue';
+import { useRoute } from 'vue-router';
+import { ItemType } from 'ant-design-vue';
+// 图片引入
+import map from '@/assets/map.jpg';
+// 接口
+// 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({});
+const selectedKeys: Ref<any> = ref(['1']);
+const select: Ref<any> = ref('1');
+const menuList: ItemType[] = reactive([
+  {
+    key: '1',
+    label: '关于我们',
+    title: '关于我们'
+  },
+  {
+    key: '2',
+    label: '意见反馈',
+    title: '意见反馈'
+  },
+  {
+    key: '3',
+    label: '联系我们',
+    title: '联系我们'
+  },
+  {
+    key: '4',
+    label: '法律条款',
+    title: '法律条款'
+  }
+]);
+// 请求
+onMounted(async () => {
+  loading.value = true;
+  search();
+  loading.value = false;
+});
+const search = async () => {
+  if (route.query.type) {
+    select.value = route.query.type;
+    selectedKeys.value = [route.query.type];
+  }
+  //   let res: IQueryResult = await toolsAxios.dataCount();
+  //   if (res.errcode == '0') {
+  //     info.value = res.data;
+  //   }
+};
+const onOpenChange = (item) => {
+  select.value = item.key;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  .help {
+    padding: 10px 0;
+    min-height: 490px;
+
+    .left {
+      display: flex;
+      align-items: normal;
+    }
+
+    .right {
+      background: rgba(40, 77, 191, 0.03);
+      padding: 20px;
+
+      h2 {
+        font-size: 32px;
+        color: #284dbf;
+      }
+
+      .other {
+        margin-bottom: 10px;
+        font-family: PingFangSC-Regular;
+        font-size: 14px;
+        color: #7e8288;
+        line-height: 25px;
+
+        span {
+          font-family: PingFangSC-Regular;
+          font-size: 14px;
+          color: #383b40;
+          line-height: 25px;
+          margin: 0 5px;
+        }
+      }
+    }
+  }
+}
+</style>

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

@@ -0,0 +1,418 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="iachievement">
+          <el-image class="image" :src="achievement" fit="fill" />
+          <div class="input">
+            <a-input v-model:value="searchValue" placeholder="请输入想要搜索的内容">
+              <template #suffix>
+                <SearchOutlined :style="{ fontSize: '30px', color: '#ffffff' }" />
+              </template>
+            </a-input>
+          </div>
+        </el-col>
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <el-row class="one_1" v-for="(val, indexs) in searchList" :key="indexs">
+              <el-col :span="3" class="left">{{ val.title }}</el-col>
+              <el-col :span="21" class="right">
+                <a-button class="title" v-for="(item, index) in val.list" :key="index" type="link" size="samll">{{ item.label }}</a-button>
+              </el-col>
+            </el-row>
+          </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="24" class="name">
+                <el-tooltip effect="dark" :content="item.name" placement="top">
+                  {{ item.name || '暂无成果名称' }}
+                </el-tooltip>
+              </el-col>
+              <el-row class="other">
+                <el-col :span="8" class="other_1"><span>技术领域:</span>{{ item.area || '暂无技术领域' }}</el-col>
+                <el-col :span="8" class="other_1"><span>成果地区:</span>{{ item.city || '暂无成果地区' }}</el-col>
+                <el-col :span="8" class="other_1"><span>单位:</span>{{ item.unit || '暂无单位' }}</el-col>
+              </el-row>
+              <el-col :span="24" class="brief textOver">{{ item.brief || '没有更多成果简介' }}</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 { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { useRouter } from 'vue-router';
+import { SearchOutlined } from '@ant-design/icons-vue';
+// 路由
+const router = useRouter();
+const { proxy } = getCurrentInstance() as any;
+// 图片引入
+import achievement from '@/assets/achievement.png';
+// 加载中
+const loading: Ref<any> = ref(false);
+const searchValue = ref<string>('');
+// 列表
+const list: Ref<any> = ref([
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司',
+    brief:
+      '技术特点:专为电子商务行业设计,以自动化和流程化地管理订单、财务、仓库、物流和发货等业务为主。它的目标是提高商家的订单速度和出货速度,有效管理企业内部员工的工作能力和监管财务系统,以及改善企业业务流程、提高企业核心竞争力'
+  },
+  {
+    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 pageSizeOptions = ref<string[]>(['12', '24', '60', '120']);
+const searchList: Ref<any> = ref([
+  {
+    title: '行业分市场',
+    list: [
+      { value: '0', label: '全部' },
+      { value: '1', label: '碳中和' },
+      { value: '2', label: '水利科技' },
+      { value: '3', label: '物联网' },
+      { value: '4', label: '产业计量' },
+      { value: '5', label: '卫生健康' },
+      { value: '6', label: '时尚轻纺' },
+      { value: '7', label: '农业科技' },
+      { value: '8', label: '智能化' },
+      { value: '9', label: '海洋科技' }
+    ]
+  },
+  {
+    title: '技术领域',
+    list: [
+      { value: '0', label: '全部' },
+      { value: '1', label: '先进制造' },
+      { value: '2', label: '地球、空间与海洋' },
+      { value: '3', label: '新材料' },
+      { value: '4', label: '新能源与节能' },
+      { value: '5', label: '核应用技术' },
+      { value: '6', label: '环境保护' },
+      { value: '7', label: '现代交通' },
+      { value: '8', label: '现代农业' },
+      { value: '9', label: '生物医药与医疗器械' },
+      { value: '10', label: '电子信息' },
+      { value: '11', label: '航空航天' }
+    ]
+  },
+  {
+    title: '成熟度',
+    list: [
+      { value: '0', label: '全部' },
+      { value: '1', label: '正在研发' },
+      { value: '2', label: '已有样品' },
+      { value: '3', label: '通过小试' },
+      { value: '4', label: '通过中试' }
+    ]
+  },
+  {
+    title: '出让方式',
+    list: [
+      { value: '0', label: '全部' },
+      { value: '1', label: '转让' },
+      { value: '2', label: '许可' },
+      { value: '3', label: '作价入股' },
+      { value: '4', label: '其他' },
+      { value: '4', label: '免费许可/先用后转' }
+    ]
+  },
+  {
+    title: '交易价格',
+    list: [
+      { value: '0', label: '全部' },
+      { value: '1', label: '面议' },
+      { value: '2', label: '1-10万元' },
+      { value: '3', label: '10-20万元' },
+      { value: '4', label: '20-100万元' },
+      { value: '5', label: '100-500万元' },
+      { value: '6', label: '500-1000万元' },
+      { value: '7', label: '1000万元以上' }
+    ]
+  },
+  {
+    title: '成果地区',
+    list: [
+      { value: '0', label: '北京市' },
+      { value: '1', label: '天津市' },
+      { value: '2', label: '河北省' },
+      { value: '3', label: '山西省' },
+      { value: '4', label: '内蒙古自治区' },
+      { value: '5', label: '辽宁省' },
+      { value: '6', label: '吉林省' },
+      { value: '7', label: '上海市' },
+      { value: '8', label: '江苏省' },
+      { value: '9', label: '浙江省' },
+      { value: '10', label: '安徽省' },
+      { value: '11', label: '福建省' },
+      { value: '0', label: '江西省' },
+      { value: '1', label: '山东省' },
+      { value: '2', label: '河南省' },
+      { value: '3', label: '湖北省' },
+      { value: '4', label: '湖南省' },
+      { value: '5', label: '广东省' },
+      { value: '6', label: '广西壮族自治区' },
+      { value: '7', label: '海南省' },
+      { value: '8', label: '重庆市' },
+      { value: '9', label: '四川省' },
+      { value: '10', label: '贵州省' },
+      { value: '11', label: '云南省' }
+    ]
+  }
+]);
+// 查看
+const toView = (item) => {
+  router.push({ path: '/achievement/detail', query: { id: item.id || item._id } });
+};
+const onShowSizeChange = (current: number, pageSize: number) => {
+  console.log(current, pageSize);
+  limit = pageSize;
+};
+// 请求
+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>
+.main {
+  background: rgb(248, 248, 248);
+
+  .iachievement {
+    position: relative;
+
+    .image {
+      width: 100%;
+      height: 250px;
+    }
+
+    .input {
+      width: 800px;
+      position: absolute;
+      left: 25%;
+      bottom: 40%;
+
+      :deep(.ant-input-affix-wrapper) {
+        background-color: transparent;
+        border: 3px solid #fff !important;
+      }
+
+      :deep(.ant-input) {
+        height: 45px;
+        line-height: 45px;
+        font-family: PingFangSC-Regular;
+        font-size: 16px;
+        padding-right: 24px;
+
+        border: none !important;
+        outline: none !important;
+        box-shadow: 0 0 0 0 !important;
+        text-shadow: 0 0 0 0 !important;
+        background-color: transparent !important;
+
+        &::placeholder {
+          color: #ffffff !important;
+        }
+      }
+    }
+  }
+
+  .one {
+    background: #ffffff;
+    border-radius: 10px;
+    padding: 15px;
+    margin: 10px 0 0 0;
+
+    .one_1 {
+      display: flex;
+      align-items: center;
+      padding: 10px 0;
+      border-bottom: #9d9898 1px dashed;
+
+      .left {
+        background: #778cb3;
+        border-radius: 15px;
+        line-height: 26px;
+        color: #fff;
+        text-align: center;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        font-family: PingFangSC-Medium;
+      }
+
+      .right {
+        .title {
+          color: #666;
+          font-size: 14px;
+          line-height: 15px;
+          margin: 0 10px;
+          display: inline-block;
+          overflow: hidden;
+          text-decoration: none;
+        }
+
+        .title:hover {
+          color: #2374ff;
+        }
+      }
+    }
+  }
+
+  .two {
+    margin-top: 20px;
+    background: #ffffff;
+    border-radius: 10px;
+    padding: 15px;
+
+    .list {
+      margin-bottom: 30px;
+      border-bottom: 1px solid #ebebeb;
+      padding-bottom: 10px;
+
+      .name {
+        color: #337ab7;
+        font-size: 18px;
+        font-weight: bold;
+        display: inline-block;
+        margin: 10px 0;
+      }
+
+      .name:hover {
+        color: #2374ff;
+      }
+
+      .other {
+        padding: 5px 0;
+
+        .other_1 {
+          font-family: 'PingFangSC-Light', 'Microsoft YaHei', 'WenQuanYi Micro Hei', arial, sans-serif;
+          font-size: 12px;
+          font-weight: normal;
+        }
+
+        .other_1:hover {
+          color: #2374ff;
+        }
+      }
+
+      .brief {
+        line-height: 30px;
+        color: #666;
+        font-size: 14px;
+      }
+    }
+  }
+
+  .thr {
+    display: flex;
+    flex-direction: row-reverse;
+    padding: 20px;
+  }
+}
+</style>

File diff suppressed because it is too large
+ 195 - 0
src/views/home/components/brain.vue


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

@@ -0,0 +1,349 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="idemand">
+          <el-image class="image" :src="demand" fit="fill" />
+        </el-col>
+        <div class="w_1200">
+          <el-col :span="24" class="one">
+            <el-row class="one_1" v-for="(val, indexs) in searchList" :key="indexs">
+              <el-col :span="3" class="left">{{ val.title }}</el-col>
+              <el-col :span="21" class="right">
+                <a-button class="title" v-for="(item, index) in val.list" :key="index" type="link" size="samll">{{ item.label }}</a-button>
+              </el-col>
+            </el-row>
+          </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="24" class="name">
+                <el-tooltip effect="dark" :content="item.name" placement="top">
+                  {{ item.name || '暂无需求名称' }}
+                </el-tooltip>
+              </el-col>
+              <el-row class="other">
+                <el-col :span="8" class="other_1"><span>技术领域:</span>{{ item.area || '暂无技术领域' }}</el-col>
+                <el-col :span="8" class="other_1"><span>需求地区:</span>{{ item.city || '暂无需求地区' }}</el-col>
+                <el-col :span="8" class="other_1"><span>单位:</span>{{ item.unit || '暂无单位' }}</el-col>
+              </el-row>
+              <el-col :span="24" class="brief textOver">{{ item.brief || '没有更多需求简介' }}</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 { Ref } from 'vue';
+import { ref, onMounted, getCurrentInstance } from 'vue';
+import { useRouter } from 'vue-router';
+// 图片引入
+import demand from '@/assets/demand.png';
+// 路由
+const router = useRouter();
+const { proxy } = getCurrentInstance() as any;
+// 加载中
+const loading: Ref<any> = ref(false);
+// 列表
+const list: Ref<any> = ref([
+  {
+    name: '拉力均衡强稳定性无焊口锚链',
+    area: '先进制造',
+    city: '舟山市',
+    unit: '浙江易丰安全科技有限公司',
+    brief:
+      '技术特点:专为电子商务行业设计,以自动化和流程化地管理订单、财务、仓库、物流和发货等业务为主。它的目标是提高商家的订单速度和出货速度,有效管理企业内部员工的工作能力和监管财务系统,以及改善企业业务流程、提高企业核心竞争力'
+  },
+  {
+    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 pageSizeOptions = ref<string[]>(['12', '24', '60', '120']);
+const searchList: Ref<any> = ref([
+  {
+    title: '技术领域',
+    list: [
+      { value: '0', label: '全部' },
+      { value: '1', label: '先进制造' },
+      { value: '2', label: '地球、空间与海洋' },
+      { value: '3', label: '新材料' },
+      { value: '4', label: '新能源与节能' },
+      { value: '5', label: '核应用技术' },
+      { value: '6', label: '环境保护' },
+      { value: '7', label: '现代交通' },
+      { value: '8', label: '现代农业' },
+      { value: '9', label: '生物医药与医疗器械' },
+      { value: '10', label: '电子信息' },
+      { value: '11', label: '航空航天' }
+    ]
+  },
+  {
+    title: '合作方式',
+    list: [
+      { value: '0', label: '全部' },
+      { value: '1', label: '技术开发' },
+      { value: '2', label: '技术咨询' },
+      { value: '3', label: '技术服务' },
+      { value: '4', label: '许可转让' },
+      { value: '4', label: '完全转让' },
+      { value: '4', label: '技术入股' },
+      { value: '4', label: '合作开发' },
+      { value: '4', label: '其他' }
+    ]
+  },
+  {
+    title: '需求地区',
+    list: [
+      { value: '0', label: '北京市' },
+      { value: '1', label: '天津市' },
+      { value: '2', label: '河北省' },
+      { value: '3', label: '山西省' },
+      { value: '4', label: '内蒙古自治区' },
+      { value: '5', label: '辽宁省' },
+      { value: '6', label: '吉林省' },
+      { value: '7', label: '上海市' },
+      { value: '8', label: '江苏省' },
+      { value: '9', label: '浙江省' },
+      { value: '10', label: '安徽省' },
+      { value: '11', label: '福建省' },
+      { value: '0', label: '江西省' },
+      { value: '1', label: '山东省' },
+      { value: '2', label: '河南省' },
+      { value: '3', label: '湖北省' },
+      { value: '4', label: '湖南省' },
+      { value: '5', label: '广东省' },
+      { value: '6', label: '广西壮族自治区' },
+      { value: '7', label: '海南省' },
+      { value: '8', label: '重庆市' },
+      { value: '9', label: '四川省' },
+      { value: '10', label: '贵州省' },
+      { value: '11', label: '云南省' }
+    ]
+  },
+  {
+    title: '需求状态',
+    list: [
+      { value: '0', label: '全部' },
+      { value: '1', label: '洽谈中' },
+      { value: '2', label: '已结束' }
+    ]
+  }
+]);
+// 查看
+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;
+};
+// 请求
+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>
+.main {
+  background: rgb(248, 248, 248);
+
+  .idemand {
+    .image {
+      width: 100%;
+      height: 250px;
+    }
+  }
+
+  .one {
+    background: #ffffff;
+    border-radius: 10px;
+    padding: 15px;
+    margin: 10px 0 0 0;
+
+    .one_1 {
+      display: flex;
+      align-items: center;
+      padding: 10px 0;
+      border-bottom: #9d9898 1px dashed;
+
+      .left {
+        background: #778cb3;
+        border-radius: 15px;
+        line-height: 26px;
+        color: #fff;
+        text-align: center;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        font-family: PingFangSC-Medium;
+      }
+
+      .right {
+        .title {
+          color: #666;
+          font-size: 14px;
+          line-height: 15px;
+          margin: 0 10px;
+          display: inline-block;
+          overflow: hidden;
+          text-decoration: none;
+        }
+
+        .title:hover {
+          color: #2374ff;
+        }
+      }
+    }
+  }
+
+  .two {
+    margin-top: 20px;
+    background: #ffffff;
+    border-radius: 10px;
+    padding: 15px;
+
+    .list {
+      margin-bottom: 30px;
+      border-bottom: 1px solid #ebebeb;
+      padding-bottom: 10px;
+
+      .name {
+        color: #337ab7;
+        font-size: 18px;
+        font-weight: bold;
+        display: inline-block;
+        margin: 10px 0;
+      }
+
+      .name:hover {
+        color: #2374ff;
+      }
+
+      .other {
+        padding: 5px 0;
+
+        .other_1 {
+          font-family: 'PingFangSC-Light', 'Microsoft YaHei', 'WenQuanYi Micro Hei', arial, sans-serif;
+          font-size: 12px;
+          font-weight: normal;
+        }
+
+        .other_1:hover {
+          color: #2374ff;
+        }
+      }
+
+      .brief {
+        line-height: 30px;
+        color: #666;
+        font-size: 14px;
+      }
+    }
+  }
+
+  .thr {
+    display: flex;
+    flex-direction: row-reverse;
+    padding: 20px;
+  }
+}</style>

+ 223 - 0
src/views/home/components/home.vue

@@ -0,0 +1,223 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">
+          <el-carousel height="250px">
+            <el-carousel-item v-for="(item, index) in carouselList" :key="index">
+              <el-image class="image" :src="item.url" fit="fill" />
+            </el-carousel-item>
+          </el-carousel>
+        </el-col>
+        <el-col :span="24" class="two"> 创高创新 · 共赢未来 </el-col>
+        <el-col :span="24" class="thr">
+          <div class="w_1200" v-for="(item, index) in list" :key="index">
+            <el-col :span="24" class="thr_1" v-if="(index + 1) % 2 == 0">
+              <el-col :span="12" class="left"> <el-image class="image" :src="item.url" fit="fill" /> </el-col>
+              <el-col :span="12" class="right">
+                <el-col :span="24" class="title">{{ item.title }}</el-col>
+                <el-col :span="12" class="brief">{{ item.brief }} </el-col>
+                <el-col :span="24" class="right"> <a-button type="primary" ghost>了解更多</a-button> </el-col>
+              </el-col>
+            </el-col>
+            <el-col :span="24" class="thr_2" v-else>
+              <el-col :span="12" class="left">
+                <el-col :span="24" class="title">{{ item.title }}</el-col>
+                <el-col :span="12" class="brief">{{ item.brief }} </el-col>
+                <el-col :span="24" class="right"> <a-button type="primary" ghost>了解更多</a-button> </el-col>
+              </el-col>
+              <el-col :span="12" class="right"> <el-image class="image" :src="item.url" fit="fill" /> </el-col>
+            </el-col>
+          </div>
+        </el-col>
+        <el-col :span="24" class="four">
+          <el-col :span="24" class="four_1">创新平台</el-col>
+          <el-col :span="24" class="four_2">灵感一触即发,成果就在眼前。创新创业,点亮未来。</el-col>
+          <el-col :span="24" class="four_3 w_1200">
+            <div v-for="(item, index) in otherList" :key="index">
+              <div class="list">
+                <el-col :span="24" class="list_1"> <el-image class="image" :src="item.url" fit="fill" /></el-col>
+                <el-col :span="24" class="list_2">{{ item.title }}</el-col>
+              </div>
+            </div>
+          </el-col>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+
+// 图片引入
+import video_1 from '@/assets/video_1.png';
+import video_2 from '@/assets/video_2.jpg';
+import home_1 from '@/assets/home_1.png';
+import home_2 from '@/assets/home_2.png';
+import home_3 from '@/assets/home_3.png';
+import home_4 from '@/assets/home_4.png';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+
+// 加载中
+const loading: Ref<any> = ref(false);
+const carouselList: Ref<any> = ref([{ url: video_1 }, { url: video_2 }, { url: video_1 }]);
+const list: Ref<any> = ref([
+  { title: '政策新闻', brief: '推动政策落地,让每一分投入都发挥最大效益,让每一步行动都引领未来发展。', url: home_1 },
+  { title: '供需商城', brief: '我们向您献上最诚挚的敬意,希望我们能一起开拓更广阔的合作领域。', url: home_2 },
+  { title: '创新大赛', brief: '科技点亮希望,创新改变世界。', url: home_3 },
+  { title: '成果展示', brief: '通过不懈的努力,我们成功地完成了项目目标,取得了显著的成果。', url: home_4 },
+  { title: '新闻资讯', brief: '新闻资讯也指一个集中的空间,能够在企业创办初期举步维艰时,提供资金、管理等多种便利。', url: home_1 }
+]);
+const otherList: Ref<any> = ref([
+  { title: '汽车电子', url: home_1 },
+  { title: '碳纤维', url: home_2 },
+  { title: '光电', url: home_3 },
+  { title: '农产品', url: home_4 },
+  { title: '车芯片', url: home_1 },
+  { title: '人工智能', url: home_1 },
+  { title: '生物基', url: home_2 },
+  { title: '新能源', url: home_3 },
+  { title: '遥感卫星', url: home_4 },
+  { title: '天然气', url: home_1 },
+  { title: '精密仪器', url: home_4 },
+  { title: '生物医药', url: home_1 }
+]);
+// 请求
+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;
+  //   }
+};
+</script>
+<style scoped lang="scss">
+.main {
+  .two {
+    text-align: center;
+    font-size: 28px;
+    margin: 40px 0;
+  }
+
+  .thr {
+    margin: 10px 0;
+
+    .thr_1 {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      .left {
+        .image {
+          width: 90%;
+          height: 350px;
+        }
+      }
+
+      .right {
+        .title {
+          font-size: 20px;
+          font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
+          font-weight: bold;
+        }
+
+        .title:hover {
+          color: #3894FF;
+          transform: translateY(-10px);
+          /* 当鼠标悬停时,向上平移20像素 */
+        }
+
+        .brief {
+          margin: 20px 0;
+          font-size: 16px;
+          font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
+        }
+      }
+    }
+
+    .thr_2 {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      .left {
+        .title {
+          font-size: 20px;
+          font-weight: bold;
+        }
+
+        .title:hover {
+          color: #3894FF;
+          transform: translateY(-10px);
+          /* 当鼠标悬停时,向上平移20像素 */
+        }
+
+        .brief {
+          margin: 20px 0;
+          font-size: 16px;
+        }
+      }
+
+      .right {
+        .image {
+          width: 90%;
+          height: 350px;
+        }
+      }
+    }
+  }
+
+  .four {
+    background: #efefef;
+    padding: 20px;
+
+    .four_1 {
+      text-align: center;
+      font-size: 28px;
+      margin: 40px 0 20px 0;
+    }
+
+    .four_2 {
+      text-align: center;
+      font-size: 16px;
+      margin: 0 0 20px 0;
+      color: #333333;
+    }
+
+    .four_3 {
+      display: flex;
+      flex-wrap: wrap;
+
+      .list {
+        width: 260px;
+        margin: 20px;
+        background: #ffffff;
+        padding: 20px;
+
+        .list_2 {
+          text-align: center;
+          margin: 10px 0 0 0;
+        }
+        .list_2:hover {
+          color: #3894FF;
+        }
+      }
+
+      .list:hover {
+        transform: translateY(-20px);
+        /* 当鼠标悬停时,向上平移20像素 */
+      }
+    }
+  }
+}
+</style>

+ 50 - 0
src/views/home/components/innovation.vue

@@ -0,0 +1,50 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">
+          <el-image class="image" :src="innovation" fit="fill" />
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+// 图片引入
+import innovation from '@/assets/innovation.png';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util';
+// const toolsAxios = ToolsStore();
+
+// 加载中
+const loading: Ref<any> = ref(false);
+const info: Ref<any> = ref({});
+
+// 请求
+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;
+  //   }
+};
+</script>
+<style scoped lang="scss">
+.main {
+  .one {
+    .image {
+      width: 100%;
+      height: 250px;
+    }
+  }
+}
+</style>

File diff suppressed because it is too large
+ 317 - 0
src/views/home/components/news.vue


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

@@ -0,0 +1,169 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <cHead @selectMenu="selectMenu" :activeKey="current">
+          <template v-slot:info>
+            <component v-show="current == 'home'" :is="home"> </component>
+            <component v-show="current == 'brain'" :is="brain"> </component>
+            <component v-show="current == 'news'" :is="news"> </component>
+            <component v-show="current == 'demand'" :is="demand"> </component>
+            <component v-show="current == 'achievement'" :is="achievement"> </component>
+            <component v-show="current == 'innovation'" :is="innovation"> </component>
+          </template>
+        </cHead>
+      </el-col>
+    </el-row>
+    <el-dialog v-model="dialog" title="智能客服">
+      <el-col :span="24" class="dialog">
+        <div class="content">
+          <div class="title">智能客服为您服务</div>
+          <div class="list">
+            <el-image class="image" :src="kf" fit="fill" />
+            <div class="message">Hi,遇到问题随时找智能客服哟~ 有什么需要我帮忙的吗?</div>
+          </div>
+        </div>
+        <div class="foot">
+          <textarea class="input" placeholder="输入消息"></textarea>
+          <div class="button">
+            <div class="send">发 送</div>
+          </div>
+        </div>
+      </el-col>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+import { useRoute } from 'vue-router';
+// 图片引入
+import kf from '@/assets/kf.png';
+// 接口
+// import { ToolsStore } from '@/stores/tool';
+// import type { IQueryResult } from '@/util/types.util'
+// const toolsAxios = ToolsStore();
+// 组件
+import home from './components/home.vue';
+import brain from './components/brain.vue';
+import news from './components/news.vue';
+import demand from './components/demand.vue';
+import achievement from './components/achievement.vue';
+import innovation from './components/innovation.vue';
+
+// 路由
+const route = useRoute();
+// 加载中
+const loading: Ref<any> = ref(false);
+const current = ref(localStorage.getItem('href') || 'home'); // 创建一个响应式数据;
+// 是否弹框客服
+const dialog: 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 selectMenu = async (item) => {
+  current.value = item;
+  localStorage.setItem('href', item);
+};
+</script>
+<style scoped lang="scss">
+:deep(.el-dialog__body) {
+  padding: 0 !important;
+}
+
+.dialog {
+  .content {
+    padding: 20px;
+
+    .title {
+      padding-top: 23px;
+      padding-bottom: 26px;
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      justify-content: center;
+      font-size: 14px;
+      color: rgba(0, 0, 0, 0.45);
+    }
+
+    .list {
+      display: flex;
+      align-items: center;
+
+      .image {
+        width: 60px;
+        height: 60px;
+        border-radius: 60px;
+        margin: 0 10px 0 0;
+      }
+
+      .message {
+        position: relative;
+        max-width: 330px;
+        border-radius: 4px;
+        font-size: 14px;
+        line-height: 22px;
+        box-sizing: border-box;
+        color: rgba(0, 0, 0, 0.65);
+        padding: 16px 11px 16px 16px;
+        background: #ffffff;
+        box-shadow: 0px 2px 10px 1px rgba(0, 0, 0, 0.12);
+      }
+    }
+  }
+
+  .foot {
+    height: 140px;
+    background: rgba(0, 0, 0, 0.04);
+    border: 1px solid rgba(0, 0, 0, 0.15);
+    padding: 13px 20px;
+    display: flex;
+    flex-direction: column;
+    align-items: stretch;
+
+    .input {
+      flex: 1;
+      height: 0;
+      resize: none;
+      border: none;
+      outline: none;
+      background: transparent;
+      font-size: 14px;
+      line-height: 22px;
+    }
+
+    .button {
+      margin-top: 8px;
+      flex-shrink: 0;
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-end;
+
+      .send {
+        cursor: pointer;
+        color: #fff;
+        background: #2f54eb;
+        border-radius: 4px;
+        width: 64px;
+        height: 32px;
+        font-size: 14px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+  }
+}
+</style>

+ 217 - 0
src/views/index/index.vue

@@ -0,0 +1,217 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-image class="video" :src="siteInfo.videoUrl" fit="fill" />
+        <div class="content">
+          <div class="one">
+            <el-row>
+              <el-col :span="14" class="left">
+                <el-image class="image" :src="siteInfo.logoUrl" fit="fill" />
+                <div class="left_1">
+                  <div class="title">{{ siteInfo.zhTitle }}</div>
+                  <div class="english">{{ siteInfo.zhEnglish }}</div>
+                </div>
+              </el-col>
+              <el-col :span="10" class="right">
+                <el-row align="middle">
+                  <el-col :span="6" class="right_1" @click="toCommon(0)">帮助中心</el-col>
+                  <el-col :span="14" class="right_2">
+                    <a-input-search v-model:value="searchValue" placeholder="请输入您想要搜索的内容" style="width: 240px" enter-button @search="onSearch" />
+                  </el-col>
+                  <el-col :span="4" class="right_3">
+                    <text @click="toCommon(1)">登录</text>
+                    <text>|</text>
+                    <text @click="toCommon(2)">注册</text>
+                  </el-col>
+                </el-row>
+              </el-col>
+            </el-row>
+          </div>
+          <div class="two">
+            <el-row justify="center" align="middle">
+              <el-col class="list" :span="8" v-for="(item, index) in menuList" :key="index" @click="switchMenu(item)">
+                <div class="bg"></div>
+                <div class="two_1">
+                  <text>{{ item.title }}</text>
+                  <text>{{ item.English }}</text>
+                </div>
+              </el-col>
+            </el-row>
+          </div>
+          <div class="thr">版权所有(C)2002-2024新一代信息技术孵化平台.All Rights Reserved.吉ICP备12029479号-2</div>
+        </div>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+import { siteInfo, menuList } from '@/layout/site';
+import { useRouter } from 'vue-router';
+// 加载中
+const loading: Ref<any> = ref(false);
+// 路由
+const router = useRouter();
+// 搜索
+const searchValue = ref<string>('');
+// 请求
+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 onSearch = (data: string) => {
+  console.log('use value', data);
+  console.log('or use this.value', searchValue.value);
+};
+const toCommon = (type: number) => {
+  if (type == 0) {
+    console.log('帮助中心');
+  } else {
+    console.log('登录或注册');
+  }
+};
+// 点击指定模块
+const switchMenu = async (item: any) => {
+  localStorage.setItem('href', item.href);
+  router.push({ path: '/home' });
+};
+</script>
+<style scoped lang="scss">
+.main {
+  height: 100vh;
+  min-width: 1200px;
+
+  .video {
+    position: absolute;
+    top: 0px;
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+    z-index: 0;
+  }
+
+  .content {
+    position: absolute;
+    top: 0px;
+    width: 100%;
+    height: 100%;
+    z-index: 0;
+    color: #ffffff;
+
+    .one {
+      width: 1200px;
+      min-width: 1200px;
+      margin: 0 auto;
+      padding-top: 32px;
+      padding-bottom: 12px;
+
+      .left {
+        display: flex;
+        align-items: center;
+
+        .image {
+          height: 45px;
+          width: 45px;
+        }
+
+        .left_1 {
+          margin: 0 0 0 5px;
+
+          .title {
+            margin: 0 0 5px 0;
+            font-size: 23px;
+            font-weight: bold;
+          }
+
+          .english {
+            font-size: 12px;
+            color: #fff;
+          }
+        }
+      }
+
+      .right {
+        font-size: 14px;
+        letter-spacing: 0;
+        color: #fff;
+        font-weight: 500;
+
+        .right_3 {
+          display: flex;
+          justify-content: space-between;
+        }
+      }
+    }
+
+    .two {
+      width: 1200px;
+      min-width: 1200px;
+      margin: 0 auto;
+
+      .list {
+        position: relative;
+        display: flex;
+        justify-content: center;
+
+        .bg {
+          margin: 10px;
+          width: 250px;
+          height: 250px;
+          z-index: 1;
+          background-image: url(@/assets/homebg.png);
+          background-position: center center;
+          background-repeat: no-repeat;
+          background-size: contain;
+          animation: animationName 5s linear infinite;
+        }
+
+        .two_1 {
+          position: absolute;
+          top: 43%;
+          left: 25%;
+          display: flex;
+          flex-direction: column;
+          align-items: center;
+          z-index: 999;
+          width: 200px;
+
+          text {
+            font-size: 20px;
+            color: #ffffff;
+          }
+
+          text:last-child {
+            margin: 5px 0 0 0;
+            font-size: 12px;
+          }
+        }
+
+        @keyframes animationName {
+          100% {
+            transform: rotate(1turn);
+          }
+        }
+      }
+    }
+
+    .thr {
+      margin: 30px 0 0 0;
+      text-align: center;
+      font-size: 12px;
+      color: #fff;
+    }
+  }
+}
+</style>

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

@@ -0,0 +1,262 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <cHead :is_menu="false">
+          <template v-slot:info>
+            <el-col :span="24" class="two">
+              <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="dialog = true">《{{ 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="dialog = true">《{{ 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>
+          </template>
+        </cHead>
+      </el-col>
+    </el-row>
+    <el-dialog v-model="dialog" title="使用协议">使用协议</el-dialog>
+  </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 dialog = 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 () => {
+  // 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(@/assets/loginbg.jpeg);
+    background-position: center center;
+    background-repeat: no-repeat;
+    height: 590px;
+    width: 100%;
+    background-size: cover;
+    display: flex;
+    justify-content: space-evenly;
+
+    .loginform {
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      height: 380px;
+      padding: 20px 85px;
+      background: hsla(0, 0%, 100%, 0.6);
+      box-shadow: 0 0 30px 0 rgba(51, 51, 51, 0.2);
+      -webkit-transform: translate(-50%, -50%);
+      transform: translate(-50%, -50%);
+      border-top: 10px solid #1492ff;
+
+      .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: 100% !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 30px 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>

File diff suppressed because it is too large
+ 102 - 0
src/views/news/detail.vue


+ 48 - 0
src/views/news/index.vue

@@ -0,0 +1,48 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">
+          <cHead>
+            <template v-slot:info>
+              <div class="w_1200">
+                <el-col :span="24" class="one"> 新闻资讯查看更多 </el-col>
+              </div>
+            </template>
+          </cHead>
+        </el-col>
+      </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();
+
+// 加载中
+const loading: 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;
+  //   }
+};
+</script>
+<style scoped lang="scss">
+.main {
+  .one {}
+}
+</style>

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

@@ -0,0 +1,460 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <cHead :is_menu="false">
+          <template v-slot:info>
+            <el-col :span="24" class="two">
+              <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="dialog = true">《{{ 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="dialog = true">《{{ 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="dialog = true">《{{ siteInfo.zhTitle }}使用协议》</span>
+                    </el-col>
+                  </el-form>
+                </el-col>
+              </div>
+            </el-col>
+          </template>
+        </cHead>
+      </el-col>
+    </el-row>
+    <el-dialog v-model="dialog" title="使用协议">使用协议</el-dialog>
+  </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({});
+const dialog = ref(false);
+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(@/assets/loginbg.jpeg);
+    background-position: center center;
+    background-repeat: no-repeat;
+    height: 590px;
+    width: 100%;
+    background-size: cover;
+    display: flex;
+    justify-content: space-evenly;
+
+    .loginform {
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      height: 460px;
+      padding: 20px 85px;
+      background: hsla(0, 0%, 100%, 0.6);
+      box-shadow: 0 0 30px 0 rgba(51, 51, 51, 0.2);
+      -webkit-transform: translate(-50%, -50%);
+      transform: translate(-50%, -50%);
+      border-top: 10px solid #1492ff;
+
+      .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: 340px;
+        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: 100% !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 {
+          display: flex;
+          align-items: center;
+          padding: 0 0 40px 0;
+          color: #999;
+          font-size: 12px;
+
+          span:last-child {
+            color: #2374ff;
+          }
+        }
+      }
+
+      .content::-webkit-scrollbar {
+        display: none;
+      }
+    }
+  }
+}
+</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"
+    ]
+  }
+}

+ 36 - 0
vite.config.ts

@@ -0,0 +1,36 @@
+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: 9009,
+      host: '0.0.0.0',
+      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))
+      }
+    }
+  };
+});