bfc061eba4c4791fe6dec1c7b7645aee28b5148b..d765d3a8c24d9d22115ab2fe33942bcb08676273
2025-08-07 zhongshujie
Merge branch 'master' of http://182.92.203.7:2001/r/molecularDatabase
d765d3 对比 | 目录
2025-08-07 zhongshujie
删除nodemoldus
098bfe 对比 | 目录
2025-08-07 YM
删除node_modules
e5c645 对比 | 目录
2025-08-07 zhongshujie
初始化更改
337ba7 对比 | 目录
77个文件已添加
12790 ■■■■■ 已修改文件
.gitattributes 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.prettierrc.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vscode/extensions.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.vscode/settings.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
env.d.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json 6282 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
src/App.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/ai/current.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/ai/noCurrent.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/details/download.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/details/getImage.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/home/AI_logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/home/home_bg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/home/rightArrow.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/home/search-left.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/home/sylogo.svg 297 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/home/tryNow.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/home/zylogo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/layout/footImg-left.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/layout/footImg-right.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/serachList/2D.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/serachList/3D.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/serachList/list_bg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/config.ts 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/iframe.js 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/WebMiddleGroundApi.js 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/api/app.js 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/api/edu.js 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/api/file.js 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/api/identity.js 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/api/job.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/api/resource.js 221 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/api/store.js 879 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/api/ugc.js 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/middleGround/tool.js 418 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/toolClass.js 465 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/userAction.js 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/logo.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/style/base.css 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/style/main.css 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/style/variable.less 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/HelloWorld.vue 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/TheWelcome.vue 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/WelcomeItem.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/icons/IconCommunity.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/icons/IconDocumentation.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/icons/IconEcosystem.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/icons/IconSupport.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/icons/IconTooling.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/crumbPage.vue 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/footerPage.vue 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/headerPage.vue 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/navPage.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/pageLayout.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/en.json 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/locales/zh.json 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.ts 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/plugin/axios/index.ts 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.ts 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/stores/counter.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/ai.d.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/aiDetails.d.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/details.d.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/home.d.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/searchlist.d.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/aiDetails.vue 454 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/ai/index.vue 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/detailsPage/index.vue 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/index.vue 375 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/searchList/index.vue 319 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tsconfig.app.json 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tsconfig.json 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tsconfig.node.json 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitattributes
New file
@@ -0,0 +1 @@
* text=auto eol=lf
.prettierrc.json
New file
@@ -0,0 +1,6 @@
{
  "$schema": "https://json.schemastore.org/prettierrc",
  "semi": false,
  "singleQuote": true,
  "printWidth": 100
}
.vscode/extensions.json
New file
@@ -0,0 +1,6 @@
{
  "recommendations": [
    "Vue.volar",
    "esbenp.prettier-vscode"
  ]
}
.vscode/settings.json
New file
@@ -0,0 +1,10 @@
{
  "explorer.fileNesting.enabled": true,
  "explorer.fileNesting.patterns": {
    "tsconfig.json": "tsconfig.*.json, env.d.ts",
    "vite.config.*": "jsconfig*, vitest.config.*, cypress.config.*, playwright.config.*",
    "package.json": "package-lock.json, pnpm*, .yarnrc*, yarn*, .eslint*, eslint*, .oxlint*, oxlint*, .prettier*, prettier*, .editorconfig"
  },
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}
env.d.ts
New file
@@ -0,0 +1 @@
/// <reference types="vite/client" />
index.html
New file
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="">
<head>
  <meta charset="UTF-8">
  <link rel="icon" href="/favicon.ico">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>小分子数据库</title>
</head>
<body>
  <div id="app"></div>
  <script type="module" src="/src/main.ts"></script>
</body>
</html>
package-lock.json
New file
Diff too large
package.json
New file
@@ -0,0 +1,49 @@
{
  "name": "smallmolecules",
  "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": {
    "@tinymce/tinymce-vue": "^5.1.1",
    "axios": "^1.6.2",
    "element-plus": "^2.4.2",
    "less": "^4.2.0",
    "less-loader": "^11.1.3",
    "moment": "^2.29.4",
    "pinia": "^2.1.7",
    "spark-md5": "^3.0.2",
    "speak-tts": "^2.0.8",
    "swiper": "^11.0.5",
    "vue": "^3.3.4",
    "vue-i18n": "^12.0.0-alpha.3",
    "vue-router": "^4.2.5"
  },
  "devDependencies": {
    "@rushstack/eslint-patch": "^1.3.3",
    "@tsconfig/node18": "^18.2.2",
    "@types/node": "^18.18.5",
    "@types/spark-md5": "^3.0.4",
    "@vitejs/plugin-vue": "^4.4.0",
    "@vitejs/plugin-vue-jsx": "^3.1.0",
    "@vue/eslint-config-prettier": "^8.0.0",
    "@vue/eslint-config-typescript": "^12.0.0",
    "@vue/tsconfig": "^0.4.0",
    "eslint": "^8.49.0",
    "eslint-plugin-vue": "^9.17.0",
    "npm-run-all2": "^6.1.1",
    "prettier": "^3.0.3",
    "sass": "^1.69.5",
    "typescript": "~5.2.0",
    "unplugin-element-plus": "^0.8.0",
    "vite": "^4.4.11",
    "vue-tsc": "^1.8.19"
  }
}
public/favicon.ico
src/App.vue
New file
@@ -0,0 +1,13 @@
<script setup lang="ts">
import { RouterView } from 'vue-router'
import { useRouter } from 'vue-router';
const route = useRouter();
</script>
<template>
  <RouterView />
</template>
<style></style>
src/assets/images/ai/current.png
src/assets/images/ai/noCurrent.png
src/assets/images/details/download.png
src/assets/images/details/getImage.png
src/assets/images/home/AI_logo.png
src/assets/images/home/home_bg.png
src/assets/images/home/rightArrow.png
src/assets/images/home/search-left.png
src/assets/images/home/sylogo.svg
New file
@@ -0,0 +1,297 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="239.521px" height="51.546px" viewBox="0 0 239.521 51.546" enable-background="new 0 0 239.521 51.546"
     xml:space="preserve">
<path fill="#16569C" d="M76.579,5.779h1.925V8.02h4.725v7.106h-1.874v-0.874h-2.851v4.078h-1.925v-4.078h-2.85v0.912h-1.874V8.02
    h4.724V5.779z M73.729,12.504h2.85V9.768h-2.85V12.504z M81.354,9.768h-2.85v2.736h2.85V9.768z"/>
<path fill="#16569C" d="M84.761,18.217V6.311h11.526v11.893h-1.812V17.76h-7.903v0.457H84.761z M94.476,7.869h-7.903v8.334h7.903
    V7.869z M93.766,12.453h-0.942c0.35,0.304,0.702,0.629,1.057,0.976l-0.671,0.608h0.861v1.482h-7.156v-1.482h2.584v-1.584h-2.255
    v-1.481h2.255v-0.899h-2.457V8.59h6.902v1.483h-2.748v0.899h2.57V12.453z M91.55,13.087l0.735-0.634h-1.09v1.584h1.241
    C92.103,13.657,91.807,13.34,91.55,13.087"/>
<path fill="#16569C" d="M102.519,5.779h1.925V8.02h4.724v7.106h-1.874v-0.874h-2.85v4.078h-1.925v-4.078h-2.851v0.912h-1.874V8.02
    h4.725V5.779z M99.668,12.504h2.85V9.768h-2.85V12.504z M107.293,9.768h-2.85v2.736h2.85V9.768z"/>
<path fill="#16569C" d="M112.916,11.731h1.217c-0.354-0.33-0.743-0.659-1.166-0.988c0.794-0.828,1.444-1.799,1.951-2.913h-2.406
    v8.638h10.107v1.469H110.84V6.362h11.715v1.469h-7.371l1.38,0.367c-0.135,0.287-0.277,0.566-0.43,0.836h5.661v1.444h-3.153
    c-0.017,0.464-0.055,0.882-0.113,1.254h3.748v1.444h-4.104c1.232,0.531,2.503,1.11,3.813,1.735l-0.912,1.469
    c-1.064-0.6-2.292-1.271-3.686-2.014c-0.718,0.802-1.786,1.482-3.205,2.039c-0.354-0.489-0.747-0.983-1.178-1.481
    c1.588-0.448,2.664-1.031,3.23-1.748h-3.319V11.731z M114.348,11.731h2.482c0.067-0.355,0.109-0.773,0.127-1.254h-1.697
    C114.973,10.909,114.668,11.326,114.348,11.731"/>
<path fill="#16569C" d="M123.125,14.315c0.807-0.975,1.43-2.043,1.868-3.204h-1.755V9.477h1.812V8.058l-1.532,0.14
    c-0.084-0.575-0.181-1.077-0.291-1.508c1.747-0.134,3.36-0.308,4.838-0.519l0.48,1.482c-0.569,0.08-1.186,0.158-1.849,0.235v1.589
    h1.647v1.634h-1.647V12.2l0.608-0.57c0.606,0.54,1.123,1.03,1.545,1.469l-1.063,0.963c-0.418-0.49-0.781-0.902-1.09-1.235v5.465
    h-1.646v-4.281c-0.397,0.836-0.844,1.613-1.342,2.331C123.564,15.784,123.37,15.109,123.125,14.315 M128.002,13.935l4.116-0.374
    V5.842h1.784v7.555l1.724-0.159l0.14,1.609l-1.863,0.171v3.274h-1.784v-3.116l-3.902,0.355L128.002,13.935z M129.445,9.958
    c0.743,0.549,1.464,1.145,2.165,1.786l-1.19,1.153c-0.573-0.609-1.259-1.221-2.052-1.837L129.445,9.958z M129.876,6.741
    c0.642,0.473,1.354,1.064,2.141,1.773l-1.178,1.165c-0.634-0.675-1.31-1.296-2.028-1.861L129.876,6.741z"/>
<path fill="#16569C" d="M136.271,13.505h5.536v-0.33l1.697-1.101h-4.636v-1.545h7.13v1.532l-2.177,1.444h4.723v1.571h-4.914v1.291
    c0,0.583-0.162,1.037-0.487,1.362c-0.324,0.325-0.821,0.489-1.49,0.494c-0.671,0.004-1.357,0.006-2.063,0.006
    c-0.118-0.582-0.262-1.14-0.431-1.672c0.642,0.034,1.229,0.051,1.761,0.051c0.591,0,0.887-0.258,0.887-0.773v-0.759h-5.536V13.505z
     M138.805,5.779c0.507,0.574,1.021,1.216,1.545,1.925l-0.563,0.38h2.115c-0.354-0.68-0.683-1.254-0.982-1.722l1.545-0.684
    c0.338,0.515,0.735,1.182,1.19,2.001l-0.873,0.405h1.551c0.579-0.831,1.067-1.554,1.463-2.166l1.71,0.938l-1.026,1.229h1.824V11.2
    h-1.772V9.629h-8.271V11.2h-1.772V8.083h2.07c-0.371-0.511-0.732-0.98-1.084-1.406L138.805,5.779z"/>
<path fill="#16569C" d="M152.572,11.148c0.625,0.811,0.937,1.854,0.937,3.129c0,0.676-0.154,1.17-0.468,1.482
    c-0.321,0.321-0.874,0.481-1.66,0.481c-0.059-0.574-0.155-1.16-0.291-1.76c0.187,0.042,0.333,0.063,0.444,0.063
    c0.354,0,0.531-0.27,0.531-0.81c0-0.879-0.317-1.719-0.95-2.521c0.304-1.174,0.592-2.275,0.862-3.306h-0.938v10.412h-1.457V6.462
    h3.965v1.254C153.244,8.831,152.919,9.975,152.572,11.148 M160.412,14.771c0.456,0.16,0.908,0.309,1.355,0.443
    c-0.11,0.828-0.211,1.414-0.305,1.761c-0.211,0.836-0.729,1.254-1.558,1.254h-0.658c-1.004,0-1.508-0.536-1.508-1.609v-2.875h-0.861
    c-0.117,1.562-0.545,2.702-1.278,3.42c-0.481,0.481-1.165,0.907-2.052,1.279c-0.362-0.54-0.719-1.009-1.064-1.406
    c0.912-0.397,1.57-0.793,1.976-1.191c0.466-0.455,0.752-1.156,0.862-2.102h-1.66v-1.469h7.613v1.469h-1.989v2.368
    c0,0.372,0.118,0.558,0.354,0.558h0.266c0.195,0,0.317-0.14,0.367-0.418C160.315,16.067,160.361,15.573,160.412,14.771
     M153.623,7.171h2.813c-0.093-0.303-0.194-0.658-0.305-1.063l1.762-0.241c0.126,0.431,0.239,0.866,0.341,1.304h2.913v2.394h-1.494
    V8.666h-4.56v0.899h-1.47V7.171z M154.244,9.882h6.295V11.3h-6.295V9.882z"/>
<path fill="#16569C" d="M164.794,11.731h1.217c-0.355-0.33-0.743-0.659-1.165-0.988c0.794-0.828,1.443-1.799,1.949-2.913h-2.405
    v8.638h10.106v1.469h-11.778V6.362h11.716v1.469h-7.372l1.381,0.367c-0.135,0.287-0.279,0.566-0.432,0.836h5.662v1.444h-3.153
    c-0.018,0.464-0.054,0.882-0.114,1.254h3.749v1.444h-4.104c1.233,0.531,2.506,1.11,3.813,1.735l-0.912,1.469
    c-1.063-0.6-2.293-1.271-3.685-2.014c-0.72,0.802-1.787,1.482-3.206,2.039c-0.354-0.489-0.746-0.983-1.177-1.481
    c1.587-0.448,2.663-1.031,3.229-1.748h-3.319V11.731z M166.226,11.731h2.482c0.067-0.355,0.11-0.773,0.126-1.254h-1.696
    C166.851,10.909,166.546,11.326,166.226,11.731"/>
<path fill="#16569C" d="M175.181,13.505h5.535v-0.33l1.696-1.101h-4.636v-1.545h7.131v1.532l-2.178,1.444h4.724v1.571h-4.914v1.291
    c0,0.583-0.163,1.037-0.487,1.362c-0.325,0.325-0.822,0.489-1.491,0.494c-0.669,0.004-1.356,0.006-2.063,0.006
    c-0.117-0.582-0.262-1.14-0.431-1.672c0.643,0.034,1.229,0.051,1.761,0.051c0.591,0,0.888-0.258,0.888-0.773v-0.759h-5.535V13.505z
     M177.714,5.779c0.507,0.574,1.021,1.216,1.545,1.925l-0.563,0.38h2.115c-0.354-0.68-0.683-1.254-0.982-1.722l1.545-0.684
    c0.339,0.515,0.735,1.182,1.191,2.001l-0.874,0.405h1.552c0.578-0.831,1.066-1.554,1.463-2.166l1.71,0.938l-1.026,1.229h1.823V11.2
    h-1.772V9.629h-8.271V11.2h-1.773V8.083h2.071c-0.371-0.511-0.733-0.98-1.083-1.406L177.714,5.779z"/>
<path fill="#16569C" d="M196.345,9.072c-0.051,1.748-0.16,3.141-0.33,4.18h4.42v1.57h-4.812c-0.018,0.051-0.052,0.127-0.103,0.228
    c1.631,0.532,3.247,1.094,4.852,1.684l-0.658,1.584c-1.706-0.718-3.403-1.394-5.092-2.027c-1.105,1.039-2.799,1.761-5.079,2.166
    c-0.413-0.717-0.773-1.283-1.077-1.697c2.711-0.389,4.443-1.034,5.194-1.938h-5.523v-1.57h4.002
    c-0.895-0.541-1.713-0.997-2.456-1.368l0.785-1.229c0.776,0.372,1.668,0.836,2.672,1.393l-0.798,1.204h1.888
    c0.211-1.081,0.329-2.475,0.354-4.18H196.345z M188.403,10.364V7.07h5.104c-0.16-0.413-0.303-0.767-0.43-1.063l2.166-0.228
    c0.126,0.346,0.27,0.777,0.431,1.291h4.47v3.294h-1.76V8.59h-8.221v1.774H188.403z M191.468,8.958
    c0.887,0.388,1.799,0.819,2.736,1.292l-0.798,1.292c-0.996-0.558-1.888-1.022-2.674-1.394L191.468,8.958z"/>
<path fill="#16569C" d="M200.917,14.138c0.929-0.084,1.908-0.194,2.938-0.329c0.01,0.532,0.019,1.038,0.026,1.519
    c-0.946,0.119-1.866,0.254-2.761,0.406L200.917,14.138z M203.069,8.388l-0.342,3.166h0.912l0.292-3.546h-2.762v-1.52h4.395
    l-0.418,5.066h0.735c-0.084,2.432-0.161,3.977-0.229,4.636c-0.059,1.021-0.446,1.613-1.164,1.773
    c-0.347,0.051-1.153,0.076-2.421,0.076c-0.074-0.616-0.159-1.186-0.253-1.71c0.523,0.059,1.086,0.097,1.686,0.114
    c0.431,0,0.663-0.202,0.697-0.608c0.05-0.557,0.097-1.477,0.139-2.761h-3.205l0.443-4.686H203.069z M211.999,11.238h-4.825v-0.71
    c-0.295,0.271-0.604,0.537-0.925,0.798c-0.244-0.523-0.52-1.055-0.823-1.596c1.368-1.005,2.466-2.279,3.293-3.825h1.925
    l-0.279,0.456c0.989,1.444,2.1,2.516,3.332,3.217c-0.296,0.473-0.587,0.996-0.873,1.571c-0.287-0.186-0.563-0.385-0.824-0.595
    V11.238z M205.944,16.367h4.332c0.498-1.537,0.874-3.014,1.127-4.433l1.57,0.405c-0.337,1.301-0.734,2.643-1.189,4.028h1.57v1.521
    h-7.41V16.367z M207.377,12.2c0.414,1.047,0.813,2.174,1.203,3.382l-1.382,0.494c-0.262-0.971-0.633-2.103-1.114-3.394L207.377,12.2
    z M209.479,7.792c-0.388,0.609-0.898,1.259-1.532,1.951h3.179C210.518,9.101,209.968,8.451,209.479,7.792 M209.731,11.681
    c0.295,1.14,0.555,2.271,0.773,3.394l-1.406,0.342c-0.168-1.055-0.406-2.199-0.71-3.432L209.731,11.681z"/>
<path fill="#16569C" d="M219.244,5.779h1.925V8.02h4.725v7.106h-1.874v-0.874h-2.851v4.078h-1.925v-4.078h-2.85v0.912h-1.875V8.02
    h4.725V5.779z M216.395,12.504h2.85V9.768h-2.85V12.504z M224.02,9.768h-2.851v2.736h2.851V9.768z"/>
<path fill="#16569C" d="M228.262,9.413l1.735,0.393c-0.363,2.009-0.836,3.871-1.419,5.586l-1.685-0.621
    C227.375,13.234,227.831,11.448,228.262,9.413 M235.418,13.757c0.759,0.313,1.397,0.554,1.912,0.723
    c-0.058,0.401-0.168,0.938-0.326,1.612c-0.158,0.673-0.345,1.109-0.561,1.307c-0.214,0.198-0.484,0.346-0.808,0.443
    c-0.322,0.097-0.712,0.146-1.169,0.146h-2.077c-1.418,0-2.127-0.717-2.127-2.153V8.54h1.874v6.712c0,0.727,0.376,1.09,1.127,1.09
    h0.646c0.381,0,0.676-0.065,0.887-0.194c0.211-0.129,0.342-0.317,0.394-0.563C235.24,15.338,235.316,14.729,235.418,13.757
     M233.062,5.74c0.734,0.929,1.524,2.027,2.369,3.293l-1.685,1.039c-0.717-1.292-1.431-2.436-2.142-3.433L233.062,5.74z
     M237.748,9.616c0.676,1.385,1.266,2.774,1.772,4.167l-1.748,0.722c-0.472-1.376-1.041-2.778-1.709-4.205L237.748,9.616z"/>
<polygon fill="#16569C" points="75.883,31.92 72.542,31.92 72.542,25.388 75.743,25.388 75.743,26.139 73.344,26.139 73.344,28.231
    75.565,28.231 75.565,28.978 73.344,28.978 73.344,31.174 75.883,31.174 "/>
<path fill="#16569C" d="M81.471,31.92h-0.976l-1.387-2.459c-0.033-0.056-0.079-0.168-0.141-0.336h-0.021
    c-0.005,0.021-0.054,0.137-0.144,0.34l-1.429,2.455h-0.979l2.066-3.281l-1.902-3.251h0.983l1.227,2.261
    c0.073,0.132,0.146,0.286,0.217,0.464h0.017c0.063-0.151,0.143-0.313,0.236-0.485l1.284-2.24h0.918l-1.94,3.24L81.471,31.92z"/>
<path fill="#16569C" d="M83.195,29.479v2.441h-0.802v-6.532h1.765c0.671,0,1.191,0.17,1.563,0.51c0.37,0.34,0.555,0.826,0.555,1.459
    c0,0.642-0.216,1.16-0.649,1.56c-0.433,0.396-0.975,0.584-1.625,0.563H83.195z M83.195,26.13v2.607h0.742
    c0.489,0,0.86-0.117,1.115-0.349c0.254-0.231,0.381-0.563,0.381-0.997c0-0.841-0.474-1.261-1.42-1.261H83.195z"/>
<polygon fill="#16569C" points="90.761,31.92 87.419,31.92 87.419,25.388 90.62,25.388 90.62,26.139 88.222,26.139 88.222,28.231
    90.443,28.231 90.443,28.978 88.222,28.978 88.222,31.174 90.761,31.174 "/>
<path fill="#16569C" d="M96.472,31.92h-0.945l-1.031-1.814c-0.206-0.362-0.395-0.608-0.566-0.738
    c-0.171-0.131-0.375-0.196-0.612-0.196h-0.578v2.749h-0.802v-6.533h1.893c0.604,0,1.078,0.153,1.42,0.46s0.513,0.735,0.513,1.286
    c0,0.906-0.459,1.493-1.379,1.764v0.021c0.171,0.076,0.318,0.185,0.443,0.325c0.124,0.141,0.285,0.381,0.482,0.721L96.472,31.92z
     M92.738,26.125v2.309h0.946c0.366,0,0.663-0.113,0.893-0.338c0.229-0.226,0.343-0.521,0.343-0.887c0-0.34-0.104-0.605-0.313-0.797
    c-0.208-0.191-0.513-0.287-0.911-0.287H92.738z"/>
<polygon fill="#16569C" points="98.698,26.101 98.101,26.101 98.101,31.208 98.698,31.208 98.698,31.92 96.7,31.92 96.7,31.208
    97.298,31.208 97.298,26.101 96.7,26.101 96.7,25.389 98.698,25.389 "/>
<path fill="#16569C" d="M105.332,31.92v-4.326c0-0.358,0.021-0.787,0.061-1.287h-0.021c-0.068,0.314-0.131,0.533-0.184,0.658
    l-2.05,4.955h-0.445l-2.046-4.918c-0.048-0.111-0.11-0.344-0.185-0.695h-0.023c0.026,0.304,0.04,0.746,0.04,1.324v4.289h-0.767
    v-6.533h1.087l1.834,4.479c0.139,0.343,0.23,0.61,0.276,0.802h0.028c0.139-0.402,0.236-0.675,0.292-0.818l1.865-4.462h1.034v6.533
    H105.332z"/>
<polygon fill="#16569C" points="111.08,31.92 107.739,31.92 107.739,25.388 110.94,25.388 110.94,26.139 108.541,26.139
    108.541,28.231 110.764,28.231 110.764,28.978 108.541,28.978 108.541,31.174 111.08,31.174 "/>
<path fill="#16569C" d="M117.33,31.92h-0.951l-3.125-5.082c-0.088-0.143-0.159-0.285-0.212-0.426h-0.024
    c0.021,0.146,0.032,0.451,0.032,0.915v4.593h-0.794v-6.533h1.006l3.041,4.994c0.145,0.236,0.23,0.387,0.257,0.451h0.017
    c-0.027-0.186-0.04-0.503-0.04-0.953v-4.492h0.794V31.92z"/>
<polygon fill="#16569C" points="122.688,26.139 120.896,26.139 120.896,31.92 120.089,31.92 120.089,26.139 118.305,26.139
    118.305,25.388 122.688,25.388 "/>
<path fill="#16569C" d="M127.859,31.92h-0.887l-0.634-1.787h-2.588l-0.598,1.787h-0.886l2.366-6.533h0.858L127.859,31.92z
     M126.091,29.395l-0.939-2.717c-0.03-0.088-0.063-0.239-0.096-0.455h-0.021c-0.03,0.195-0.063,0.349-0.101,0.455l-0.931,2.717
    H126.091z"/>
<polygon fill="#16569C" points="132.034,31.92 128.757,31.92 128.757,25.388 129.56,25.388 129.56,31.174 132.034,31.174 "/>
<path fill="#16569C" d="M138.625,31.92h-0.945l-1.03-1.814c-0.206-0.362-0.396-0.608-0.567-0.738
    c-0.17-0.131-0.375-0.196-0.612-0.196h-0.578v2.749h-0.803v-6.533h1.894c0.604,0,1.078,0.153,1.42,0.46s0.514,0.735,0.514,1.286
    c0,0.906-0.46,1.493-1.38,1.764v0.021c0.171,0.076,0.319,0.185,0.443,0.325s0.286,0.381,0.482,0.721L138.625,31.92z M134.892,26.125
    v2.309h0.946c0.366,0,0.663-0.113,0.893-0.338c0.229-0.226,0.343-0.521,0.343-0.887c0-0.34-0.104-0.605-0.313-0.797
    s-0.513-0.287-0.91-0.287H134.892z"/>
<polygon fill="#16569C" points="142.793,31.92 139.452,31.92 139.452,25.388 142.653,25.388 142.653,26.139 140.254,26.139
    140.254,28.231 142.477,28.231 142.477,28.978 140.254,28.978 140.254,31.174 142.793,31.174 "/>
<path fill="#16569C" d="M143.681,30.694c0.188,0.174,0.442,0.317,0.761,0.431c0.317,0.112,0.622,0.168,0.907,0.168
    c0.871,0,1.308-0.326,1.308-0.978c0-0.184-0.047-0.349-0.141-0.494c-0.094-0.147-0.222-0.276-0.386-0.388
    c-0.162-0.112-0.469-0.286-0.918-0.519c-0.623-0.327-1.033-0.631-1.23-0.91c-0.199-0.28-0.298-0.6-0.298-0.96
    c0-0.542,0.208-0.972,0.622-1.289c0.414-0.318,0.938-0.477,1.567-0.477c0.619,0,1.072,0.079,1.36,0.236v0.92
    c-0.374-0.273-0.848-0.41-1.419-0.41c-0.381,0-0.69,0.084-0.929,0.251c-0.24,0.166-0.359,0.399-0.359,0.697
    c0,0.266,0.083,0.479,0.249,0.646c0.165,0.164,0.524,0.392,1.078,0.679c0.609,0.306,1.037,0.612,1.279,0.919
    c0.243,0.307,0.365,0.65,0.365,1.033c0,0.574-0.198,1.014-0.594,1.32c-0.396,0.307-0.945,0.459-1.648,0.459
    c-0.245,0-0.532-0.035-0.859-0.107c-0.329-0.071-0.567-0.16-0.716-0.268V30.694z"/>
<polygon fill="#16569C" points="152.051,31.92 148.71,31.92 148.71,25.388 151.911,25.388 151.911,26.139 149.512,26.139
    149.512,28.231 151.733,28.231 151.733,28.978 149.512,28.978 149.512,31.174 152.051,31.174 "/>
<path fill="#16569C" d="M158.152,31.92h-0.887l-0.634-1.787h-2.588l-0.598,1.787h-0.887l2.367-6.533h0.858L158.152,31.92z
     M156.383,29.395l-0.938-2.717c-0.03-0.088-0.062-0.239-0.097-0.455h-0.02c-0.03,0.195-0.063,0.349-0.101,0.455l-0.931,2.717
    H156.383z"/>
<path fill="#16569C" d="M163.586,31.92h-0.945l-1.03-1.814c-0.207-0.362-0.395-0.608-0.567-0.738
    c-0.171-0.131-0.375-0.196-0.612-0.196h-0.578v2.749h-0.802v-6.533h1.893c0.604,0,1.078,0.153,1.42,0.46s0.514,0.735,0.514,1.286
    c0,0.906-0.46,1.493-1.38,1.764v0.021c0.171,0.076,0.319,0.185,0.443,0.325s0.286,0.381,0.482,0.721L163.586,31.92z M159.853,26.125
    v2.309h0.947c0.365,0,0.662-0.113,0.892-0.338c0.229-0.226,0.343-0.521,0.343-0.887c0-0.34-0.104-0.605-0.313-0.797
    c-0.208-0.191-0.513-0.287-0.91-0.287H159.853z"/>
<path fill="#16569C" d="M168.541,31.651c-0.457,0.253-1.031,0.38-1.721,0.38c-0.891,0-1.603-0.298-2.135-0.892
    c-0.532-0.596-0.798-1.383-0.798-2.36c0-1.052,0.299-1.898,0.899-2.539c0.598-0.641,1.358-0.961,2.28-0.961
    c0.595,0,1.085,0.088,1.474,0.265v0.882c-0.444-0.259-0.934-0.388-1.466-0.388c-0.691,0-1.257,0.242-1.691,0.727
    c-0.436,0.485-0.654,1.14-0.654,1.963c0,0.782,0.203,1.403,0.61,1.863s0.938,0.689,1.596,0.689c0.615,0,1.149-0.146,1.605-0.438
    V31.651z"/>
<polygon fill="#16569C" points="174.533,31.92 173.73,31.92 173.73,28.978 170.585,28.978 170.585,31.92 169.783,31.92
    169.783,25.388 170.585,25.388 170.585,28.226 173.73,28.226 173.73,25.388 174.533,25.388 "/>
<path fill="#16569C" d="M182.82,31.651c-0.457,0.253-1.032,0.38-1.722,0.38c-0.891,0-1.602-0.298-2.134-0.892
    c-0.532-0.596-0.798-1.383-0.798-2.36c0-1.052,0.299-1.898,0.899-2.539c0.599-0.641,1.358-0.961,2.281-0.961
    c0.595,0,1.084,0.088,1.473,0.265v0.882c-0.443-0.259-0.933-0.388-1.464-0.388c-0.693,0-1.258,0.242-1.693,0.727
    c-0.436,0.485-0.654,1.14-0.654,1.963c0,0.782,0.204,1.403,0.61,1.863c0.407,0.46,0.938,0.689,1.597,0.689
    c0.615,0,1.149-0.146,1.604-0.438V31.651z"/>
<polygon fill="#16569C" points="187.404,31.92 184.064,31.92 184.064,25.388 187.265,25.388 187.265,26.139 184.865,26.139
    184.865,28.231 187.088,28.231 187.088,28.978 184.865,28.978 184.865,31.174 187.404,31.174 "/>
<path fill="#16569C" d="M193.654,31.92h-0.95l-3.126-5.082c-0.088-0.143-0.159-0.285-0.213-0.426h-0.023
    c0.021,0.146,0.032,0.451,0.032,0.915v4.593h-0.794v-6.533h1.007l3.04,4.994c0.145,0.236,0.23,0.387,0.257,0.451h0.016
    c-0.026-0.186-0.039-0.503-0.039-0.953v-4.492h0.794V31.92z"/>
<polygon fill="#16569C" points="199.013,26.139 197.22,26.139 197.22,31.92 196.413,31.92 196.413,26.139 194.629,26.139
    194.629,25.388 199.013,25.388 "/>
<polygon fill="#16569C" points="203.309,31.92 199.968,31.92 199.968,25.388 203.169,25.388 203.169,26.139 200.77,26.139
    200.77,28.231 202.991,28.231 202.991,28.978 200.77,28.978 200.77,31.174 203.309,31.174 "/>
<path fill="#16569C" d="M209.021,31.92h-0.946l-1.031-1.814c-0.206-0.362-0.395-0.608-0.565-0.738
    c-0.172-0.131-0.376-0.196-0.613-0.196h-0.578v2.749h-0.803v-6.533h1.894c0.604,0,1.077,0.153,1.419,0.46
    c0.344,0.307,0.515,0.735,0.515,1.286c0,0.906-0.46,1.493-1.38,1.764v0.021c0.171,0.076,0.318,0.185,0.443,0.325
    c0.124,0.141,0.285,0.381,0.483,0.721L209.021,31.92z M205.286,26.125v2.309h0.946c0.366,0,0.664-0.113,0.892-0.338
    c0.23-0.226,0.343-0.521,0.343-0.887c0-0.34-0.104-0.605-0.312-0.797s-0.512-0.287-0.911-0.287H205.286z"/>
<polygon fill="#16569C" points="210.468,30.872 209.783,33.12 209.213,33.12 209.71,30.872 "/>
<path fill="#16569C" d="M216.075,31.651c-0.457,0.253-1.031,0.38-1.72,0.38c-0.892,0-1.603-0.298-2.134-0.892
    c-0.533-0.596-0.8-1.383-0.8-2.36c0-1.052,0.301-1.898,0.9-2.539c0.598-0.641,1.359-0.961,2.281-0.961
    c0.594,0,1.084,0.088,1.472,0.265v0.882c-0.443-0.259-0.932-0.388-1.464-0.388c-0.692,0-1.257,0.242-1.693,0.727
    c-0.435,0.485-0.653,1.14-0.653,1.963c0,0.782,0.203,1.403,0.609,1.863c0.407,0.46,0.939,0.689,1.598,0.689
    c0.614,0,1.148-0.146,1.604-0.438V31.651z"/>
<polygon fill="#16569C" points="222.068,31.92 221.267,31.92 221.267,28.978 218.121,28.978 218.121,31.92 217.319,31.92
    217.319,25.388 218.121,25.388 218.121,28.226 221.267,28.226 221.267,25.388 222.068,25.388 "/>
<polygon fill="#16569C" points="225.073,26.101 224.474,26.101 224.474,31.208 225.073,31.208 225.073,31.92 223.075,31.92
    223.075,31.208 223.673,31.208 223.673,26.101 223.075,26.101 223.075,25.389 225.073,25.389 "/>
<path fill="#16569C" d="M231.161,31.92h-0.95l-3.126-5.082c-0.087-0.143-0.158-0.285-0.212-0.426h-0.023
    c0.021,0.146,0.031,0.451,0.031,0.915v4.593h-0.794v-6.533h1.007l3.041,4.994c0.145,0.236,0.229,0.387,0.257,0.451h0.016
    c-0.026-0.186-0.04-0.503-0.04-0.953v-4.492h0.794V31.92z"/>
<path fill="#16569C" d="M237.647,31.92h-0.886l-0.634-1.787h-2.587l-0.6,1.787h-0.886l2.367-6.533h0.857L237.647,31.92z
     M235.879,29.395l-0.939-2.717c-0.03-0.088-0.061-0.239-0.096-0.455h-0.021c-0.029,0.195-0.062,0.349-0.101,0.455l-0.93,2.717
    H235.879z"/>
<path fill="#16569C" d="M77.424,42.287h-0.887l-0.634-1.789h-2.588l-0.597,1.789h-0.887l2.366-6.533h0.858L77.424,42.287z
     M75.655,39.759l-0.939-2.716c-0.029-0.087-0.061-0.238-0.096-0.455H74.6c-0.03,0.196-0.063,0.35-0.1,0.455l-0.932,2.716H75.655z"/>
<path fill="#16569C" d="M82.293,42.016c-0.457,0.253-1.031,0.379-1.721,0.379c-0.89,0-1.603-0.297-2.134-0.891
    c-0.532-0.596-0.799-1.383-0.799-2.36c0-1.052,0.3-1.897,0.899-2.539c0.599-0.641,1.359-0.962,2.282-0.962
    c0.593,0,1.084,0.088,1.472,0.266v0.883c-0.444-0.26-0.932-0.389-1.464-0.389c-0.693,0-1.257,0.242-1.693,0.728
    c-0.436,0.485-0.653,1.139-0.653,1.963c0,0.782,0.204,1.403,0.609,1.862c0.407,0.459,0.939,0.689,1.597,0.689
    c0.614,0,1.149-0.146,1.604-0.438V42.016z"/>
<path fill="#16569C" d="M88.254,42.287h-0.887l-0.633-1.789h-2.587l-0.599,1.789h-0.887l2.367-6.533h0.857L88.254,42.287z
     M86.485,39.759l-0.939-2.716c-0.029-0.087-0.061-0.238-0.096-0.455H85.43c-0.028,0.196-0.063,0.35-0.1,0.455l-0.931,2.716H86.485z"
    />
<path fill="#16569C" d="M88.988,42.286v-6.533h1.772c0.941,0,1.725,0.289,2.349,0.865c0.625,0.576,0.937,1.35,0.937,2.319
    c0,1.013-0.312,1.824-0.937,2.435c-0.624,0.609-1.429,0.914-2.412,0.914H88.988z M89.79,36.504v5.035h0.903
    c0.788,0,1.403-0.227,1.847-0.68c0.442-0.453,0.663-1.086,0.663-1.902c0-0.814-0.227-1.428-0.681-1.838
    c-0.455-0.412-1.053-0.615-1.793-0.615H89.79z"/>
<polygon fill="#16569C" points="98.422,42.287 95.081,42.287 95.081,35.753 98.282,35.753 98.282,36.504 95.883,36.504
    95.883,38.595 98.104,38.595 98.104,39.342 95.883,39.342 95.883,41.54 98.422,41.54 "/>
<path fill="#16569C" d="M105.053,42.287v-4.328c0-0.356,0.02-0.786,0.06-1.286h-0.02c-0.069,0.314-0.131,0.534-0.185,0.658
    l-2.05,4.956h-0.444l-2.047-4.918c-0.048-0.112-0.109-0.345-0.184-0.696h-0.024c0.026,0.305,0.04,0.746,0.04,1.324v4.29h-0.766
    v-6.533h1.086l1.834,4.479c0.139,0.342,0.231,0.609,0.277,0.801h0.027c0.14-0.402,0.236-0.674,0.292-0.818l1.866-4.462h1.034v6.533
    H105.053z"/>
<path fill="#16569C" d="M111.406,35.752l-2.045,4.13v2.403h-0.808v-2.383l-1.992-4.15h0.918l1.344,2.894
    c0.003,0.003,0.052,0.142,0.147,0.418h0.014c0.03-0.118,0.086-0.256,0.164-0.413l1.403-2.898H111.406z"/>
<path fill="#16569C" d="M113.954,39.098c0-1.055,0.271-1.895,0.814-2.52c0.543-0.623,1.277-0.936,2.205-0.936
    c0.864,0,1.56,0.307,2.086,0.916s0.791,1.404,0.791,2.383c0,1.06-0.271,1.9-0.811,2.522c-0.541,0.62-1.263,0.931-2.167,0.931
    c-0.882,0-1.589-0.305-2.121-0.914C114.219,40.872,113.954,40.077,113.954,39.098 M114.796,39.03c0,0.791,0.192,1.424,0.575,1.9
    c0.384,0.477,0.885,0.715,1.502,0.715c0.664,0,1.185-0.229,1.563-0.686c0.378-0.456,0.566-1.096,0.566-1.916
    c0-0.844-0.185-1.495-0.555-1.953c-0.371-0.458-0.878-0.688-1.522-0.688c-0.634,0-1.146,0.241-1.541,0.726
    C114.992,37.612,114.796,38.247,114.796,39.03"/>
<polygon fill="#16569C" points="124.086,36.504 121.687,36.504 121.687,38.689 123.909,38.689 123.909,39.43 121.687,39.43
    121.687,42.286 120.885,42.286 120.885,35.752 124.086,35.752 "/>
<path fill="#16569C" d="M131.604,42.016c-0.457,0.253-1.031,0.379-1.721,0.379c-0.891,0-1.602-0.297-2.135-0.891
    c-0.533-0.596-0.799-1.383-0.799-2.36c0-1.052,0.3-1.897,0.899-2.539c0.599-0.641,1.359-0.962,2.281-0.962
    c0.594,0,1.085,0.088,1.474,0.266v0.883c-0.444-0.26-0.934-0.389-1.466-0.389c-0.691,0-1.257,0.242-1.691,0.728
    c-0.437,0.485-0.654,1.139-0.654,1.963c0,0.782,0.203,1.403,0.61,1.862c0.405,0.459,0.938,0.689,1.596,0.689
    c0.615,0,1.15-0.146,1.605-0.438V42.016z"/>
<polygon fill="#16569C" points="137.432,42.287 136.629,42.287 136.629,39.342 133.484,39.342 133.484,42.287 132.683,42.287
    132.683,35.753 133.484,35.753 133.484,38.591 136.629,38.591 136.629,35.753 137.432,35.753 "/>
<polygon fill="#16569C" points="140.271,36.465 139.674,36.465 139.674,41.573 140.271,41.573 140.271,42.286 138.273,42.286
    138.273,41.573 138.872,41.573 138.872,36.465 138.273,36.465 138.273,35.752 140.271,35.752 "/>
<path fill="#16569C" d="M146.196,42.287h-0.951l-3.125-5.082c-0.087-0.144-0.158-0.286-0.212-0.427h-0.024
    c0.021,0.146,0.032,0.451,0.032,0.914v4.595h-0.794v-6.533h1.007l3.04,4.994c0.144,0.235,0.229,0.386,0.257,0.45h0.015
    c-0.025-0.186-0.039-0.502-0.039-0.953v-4.491h0.795V42.287z"/>
<polygon fill="#16569C" points="150.978,42.287 147.636,42.287 147.636,35.753 150.838,35.753 150.838,36.504 148.438,36.504
    148.438,38.595 150.661,38.595 150.661,39.342 148.438,39.342 148.438,41.54 150.978,41.54 "/>
<path fill="#16569C" d="M151.699,41.059c0.19,0.174,0.443,0.318,0.762,0.43c0.318,0.113,0.621,0.169,0.907,0.169
    c0.872,0,1.307-0.325,1.307-0.979c0-0.183-0.046-0.347-0.14-0.493c-0.093-0.146-0.222-0.276-0.385-0.389s-0.47-0.284-0.919-0.519
    c-0.623-0.325-1.033-0.629-1.231-0.909c-0.198-0.279-0.297-0.599-0.297-0.96c0-0.542,0.207-0.973,0.621-1.29
    c0.415-0.316,0.938-0.477,1.569-0.477c0.617,0,1.07,0.079,1.359,0.236v0.92c-0.375-0.273-0.848-0.409-1.42-0.409
    c-0.38,0-0.688,0.084-0.929,0.251c-0.239,0.167-0.359,0.398-0.359,0.697c0,0.265,0.083,0.479,0.249,0.646
    c0.165,0.165,0.525,0.391,1.079,0.68c0.609,0.305,1.036,0.611,1.28,0.918c0.243,0.307,0.364,0.651,0.364,1.032
    c0,0.575-0.198,1.015-0.594,1.321s-0.944,0.46-1.647,0.46c-0.246,0-0.533-0.036-0.861-0.108s-0.566-0.16-0.716-0.267V41.059z"/>
<polygon fill="#16569C" points="159.906,42.287 156.565,42.287 156.565,35.753 159.766,35.753 159.766,36.504 157.367,36.504
    157.367,38.595 159.589,38.595 159.589,39.342 157.367,39.342 157.367,41.54 159.906,41.54 "/>
<path fill="#16569C" d="M168.803,42.287v-4.328c0-0.356,0.021-0.786,0.061-1.286h-0.021c-0.069,0.314-0.131,0.534-0.185,0.658
    l-2.05,4.956h-0.445l-2.045-4.918c-0.049-0.112-0.109-0.345-0.185-0.696h-0.024c0.026,0.305,0.04,0.746,0.04,1.324v4.29h-0.765
    v-6.533h1.086l1.833,4.479c0.139,0.342,0.23,0.609,0.276,0.801h0.028c0.14-0.402,0.236-0.674,0.293-0.818l1.865-4.462h1.035v6.533
    H168.803z"/>
<polygon fill="#16569C" points="174.387,42.287 171.045,42.287 171.045,35.753 174.245,35.753 174.245,36.504 171.848,36.504
    171.848,38.595 174.069,38.595 174.069,39.342 171.848,39.342 171.848,41.54 174.387,41.54 "/>
<path fill="#16569C" d="M175.397,42.286v-6.533h1.772c0.942,0,1.725,0.289,2.349,0.865c0.625,0.576,0.937,1.35,0.937,2.319
    c0,1.013-0.312,1.824-0.937,2.435c-0.624,0.609-1.428,0.914-2.412,0.914H175.397z M176.199,36.504v5.035h0.903
    c0.789,0,1.403-0.227,1.847-0.68s0.664-1.086,0.664-1.902c0-0.814-0.228-1.428-0.682-1.838c-0.456-0.412-1.053-0.615-1.793-0.615
    H176.199z"/>
<polygon fill="#16569C" points="182.892,36.465 182.292,36.465 182.292,41.573 182.892,41.573 182.892,42.286 180.894,42.286
    180.894,41.573 181.49,41.573 181.49,36.465 180.894,36.465 180.894,35.752 182.892,35.752 "/>
<path fill="#16569C" d="M187.993,42.016c-0.458,0.253-1.032,0.379-1.721,0.379c-0.892,0-1.603-0.297-2.135-0.891
    c-0.532-0.596-0.798-1.383-0.798-2.36c0-1.052,0.298-1.897,0.898-2.539c0.599-0.641,1.36-0.962,2.282-0.962
    c0.594,0,1.085,0.088,1.473,0.266v0.883c-0.444-0.26-0.933-0.389-1.465-0.389c-0.692,0-1.257,0.242-1.692,0.728
    s-0.654,1.139-0.654,1.963c0,0.782,0.204,1.403,0.609,1.862c0.407,0.459,0.939,0.689,1.597,0.689c0.615,0,1.149-0.146,1.605-0.438
    V42.016z"/>
<path fill="#16569C" d="M193.953,42.287h-0.886l-0.635-1.789h-2.586l-0.6,1.789h-0.886l2.367-6.533h0.857L193.953,42.287z
     M192.185,39.759l-0.939-2.716c-0.03-0.087-0.061-0.238-0.095-0.455h-0.021c-0.03,0.196-0.062,0.35-0.101,0.455l-0.93,2.716H192.185
    z"/>
<polygon fill="#16569C" points="197.965,42.287 194.687,42.287 194.687,35.753 195.489,35.753 195.489,41.54 197.965,41.54 "/>
<path fill="#16569C" d="M200.717,41.059c0.188,0.174,0.444,0.318,0.762,0.43c0.317,0.113,0.621,0.169,0.906,0.169
    c0.872,0,1.308-0.325,1.308-0.979c0-0.183-0.047-0.347-0.141-0.493c-0.093-0.146-0.221-0.276-0.384-0.389
    c-0.164-0.112-0.471-0.284-0.919-0.519c-0.623-0.325-1.034-0.629-1.231-0.909c-0.199-0.279-0.297-0.599-0.297-0.96
    c0-0.542,0.207-0.973,0.621-1.29c0.415-0.316,0.938-0.477,1.569-0.477c0.617,0,1.07,0.079,1.358,0.236v0.92
    c-0.374-0.273-0.847-0.409-1.419-0.409c-0.38,0-0.689,0.084-0.928,0.251c-0.24,0.167-0.36,0.398-0.36,0.697
    c0,0.265,0.083,0.479,0.249,0.646c0.165,0.165,0.526,0.391,1.078,0.68c0.611,0.305,1.037,0.611,1.28,0.918s0.364,0.651,0.364,1.032
    c0,0.575-0.196,1.015-0.594,1.321c-0.396,0.307-0.945,0.46-1.647,0.46c-0.246,0-0.533-0.036-0.86-0.108
    c-0.328-0.072-0.567-0.16-0.716-0.267V41.059z"/>
<path fill="#16569C" d="M209.834,42.016c-0.458,0.253-1.032,0.379-1.721,0.379c-0.892,0-1.603-0.297-2.134-0.891
    c-0.532-0.596-0.799-1.383-0.799-2.36c0-1.052,0.3-1.897,0.899-2.539c0.598-0.641,1.359-0.962,2.281-0.962
    c0.595,0,1.085,0.088,1.473,0.266v0.883c-0.444-0.26-0.932-0.389-1.464-0.389c-0.693,0-1.257,0.242-1.694,0.728
    c-0.435,0.485-0.653,1.139-0.653,1.963c0,0.782,0.203,1.403,0.609,1.862c0.407,0.459,0.939,0.689,1.598,0.689
    c0.615,0,1.149-0.146,1.604-0.438V42.016z"/>
<polygon fill="#16569C" points="212.313,36.465 211.714,36.465 211.714,41.573 212.313,41.573 212.313,42.286 210.315,42.286
    210.315,41.573 210.912,41.573 210.912,36.465 210.315,36.465 210.315,35.752 212.313,35.752 "/>
<polygon fill="#16569C" points="216.504,42.287 213.163,42.287 213.163,35.753 216.364,35.753 216.364,36.504 213.965,36.504
    213.965,38.595 216.188,38.595 216.188,39.342 213.965,39.342 213.965,41.54 216.504,41.54 "/>
<path fill="#16569C" d="M222.59,42.287h-0.951l-3.125-5.082c-0.088-0.144-0.158-0.286-0.212-0.427h-0.024
    c0.021,0.146,0.032,0.451,0.032,0.914v4.595h-0.794v-6.533h1.006l3.041,4.994c0.144,0.235,0.229,0.386,0.257,0.45h0.016
    c-0.026-0.186-0.039-0.502-0.039-0.953v-4.491h0.794V42.287z"/>
<path fill="#16569C" d="M228.281,42.016c-0.457,0.253-1.031,0.379-1.721,0.379c-0.891,0-1.602-0.297-2.134-0.891
    c-0.533-0.596-0.799-1.383-0.799-2.36c0-1.052,0.3-1.897,0.898-2.539c0.6-0.641,1.36-0.962,2.282-0.962
    c0.595,0,1.085,0.088,1.473,0.266v0.883c-0.444-0.26-0.932-0.389-1.464-0.389c-0.692,0-1.257,0.242-1.693,0.728
    c-0.436,0.485-0.653,1.139-0.653,1.963c0,0.782,0.203,1.403,0.61,1.862c0.406,0.459,0.938,0.689,1.596,0.689
    c0.615,0,1.15-0.146,1.604-0.438V42.016z"/>
<polygon fill="#16569C" points="232.701,42.287 229.361,42.287 229.361,35.753 232.562,35.753 232.562,36.504 230.162,36.504
    230.162,38.595 232.386,38.595 232.386,39.342 230.162,39.342 230.162,41.54 232.701,41.54 "/>
<path fill="#16569C" d="M233.424,41.059c0.189,0.174,0.444,0.318,0.762,0.43c0.318,0.113,0.621,0.169,0.906,0.169
    c0.873,0,1.308-0.325,1.308-0.979c0-0.183-0.046-0.347-0.14-0.493c-0.093-0.146-0.222-0.276-0.385-0.389s-0.471-0.284-0.919-0.519
    c-0.622-0.325-1.034-0.629-1.231-0.909c-0.198-0.279-0.297-0.599-0.297-0.96c0-0.542,0.207-0.973,0.622-1.29
    c0.414-0.316,0.938-0.477,1.568-0.477c0.617,0,1.071,0.079,1.359,0.236v0.92c-0.374-0.273-0.848-0.409-1.419-0.409
    c-0.381,0-0.69,0.084-0.929,0.251c-0.24,0.167-0.36,0.398-0.36,0.697c0,0.265,0.084,0.479,0.249,0.646
    c0.166,0.165,0.526,0.391,1.079,0.68c0.61,0.305,1.036,0.611,1.28,0.918c0.242,0.307,0.363,0.651,0.363,1.032
    c0,0.575-0.196,1.015-0.593,1.321c-0.396,0.307-0.946,0.46-1.647,0.46c-0.246,0-0.533-0.036-0.861-0.108s-0.566-0.16-0.716-0.267
    V41.059z"/>
<path fill="#006CB6" d="M9.742,17.428c0,0-1.225-16.04,17.265-17.428v16.979C27.007,16.979,14.64,14.449,9.742,17.428"/>
<path fill="#5AB546" d="M29.211,17.428V0c0,0,23.482,1.979,26.642,26.836C57.184,45.731,35.567,51.03,35.567,51.03
    s12.637-3.679,11.826-17.521C46.333,21.724,29.211,17.428,29.211,17.428"/>
<path fill="#006CB6" d="M46.387,35.629c0,0,0.174,13.351-16.438,15.917V37.501C29.948,37.501,41.878,40.034,46.387,35.629"/>
<path fill="#5AB546" d="M27.564,37.125c0,0-15.774-3.68-18.581-16.399C6.677,7.944,15.344,1.459,21.143,0.274
    c0,0-23.07,4.365-21.013,25.241c4.38,24.288,27.435,26.031,27.435,26.031V37.125z"/>
</svg>
src/assets/images/home/tryNow.png
src/assets/images/home/zylogo.png
src/assets/images/layout/footImg-left.png
src/assets/images/layout/footImg-right.png
src/assets/images/serachList/2D.png
src/assets/images/serachList/3D.png
src/assets/images/serachList/list_bg.png
src/assets/js/config.ts
New file
@@ -0,0 +1,43 @@
export const requestCtx = 'http://182.92.203.7:3001' // 请求地址
export const appId = 42
export const requestTimeOut = 300000 // 请求超时时间
export const tokenKey = 'caccrd-token'
export const userInfoKey = 'accrd-userInfo' // 用户信息key
export const appRefCode = 'CACCRD'
export const goodsStore = `defaultGoodsStore${appId}` // 默认商品库(书城)
export const publicStore = `defaultPublicStore${appId}` // 默认资源开放仓储
export const publicRepository = `defaultPublicRepository${appId}` // 默认资源开放库
export const reg_tel =
  /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/ // 电话号正则
export const reg_telphone = /^0\d{2}-\d{8}$|^0\d{3}-\d{7}$/ //座机号正则
export const pathData = {
  home: '/index',
  searchList: '/home/searchList',
  detailsPage: '/home/detailsPage',
  about: '/home/about',
  ai: '/home/ai',
  aiDetails: '/home/aiDetails',
}
const refCodes = {
  // 资源
  BioChargeMap: 'BioChargeMap', //天然产物
  thirteenClassics: 'CACCRD_thirteenClassics', //十三经
  about: 'CACCRD_aboutUs', // 关于我们简介
}
const config = {
  requestCtx,
  requestTimeOut,
  tokenKey,
  userInfoKey,
  appRefCode,
  goodsStore,
  reg_tel,
  reg_telphone,
  appId,
  pathData,
  refCodes,
}
export default config
src/assets/js/iframe.js
New file
@@ -0,0 +1,32 @@
let isSelect = false;
let move = false;
document.addEventListener('mousedown', () => {
    isSelect = true;
});
document.addEventListener('mousemove', () => {
    if (isSelect) {
        move = true;
    }
});
document.addEventListener('mouseup', (e) => {
    isSelect = false;
    if (move) {
        const selection = window.getSelection();
        if (selection && selection.toString().length != 0) {
            parent.window.selectChange(e)
        }
    }
    move = false;
    e.preventDefault();
});
parent.window.document.getElementsByClassName("epub-container")[0].addEventListener("scroll", function (e) {
    parent.window.scroll(e); // 调用处理函数并传入参数
})
src/assets/js/middleGround/WebMiddleGroundApi.js
New file
@@ -0,0 +1,24 @@
// 取消接口调用能力;
// 队列的必要性??
import resource from './api/resource.js'
import store from './api/store.js'
import identity from './api/identity.js'
import ugc from './api/ugc.js'
import app from './api/app.js'
import file from './api/file.js'
import job from './api/job.js'
import edu from './api/edu.js'
const WebMiddleGroundApi = {
  resource,
  store,
  identity,
  ugc,
  app,
  file,
  job,
  edu,
}
export default WebMiddleGroundApi
src/assets/js/middleGround/api/app.js
New file
@@ -0,0 +1,57 @@
import request from "@/plugin/axios/index.ts";
const appApi = {
  // 获取用户消息列表
  getAppMessageList(data) {
    return request({
      url: "/app/api/ApiGetAppMessageList",
      method: "post",
      data
    });
  },
  // 获取用户消息详情
  getMessage(data) {
    return request({
      url: "/app/api/ApiGetMessage",
      method: "post",
      data
    });
  },
  //获取凭证
  getTicketResult(data) {
    return request({
      url: "/app/api/ApiGetTicketResult",
      method: "post",
      data
    });
  },
  //使用凭证
  useTicket(data) {
    return request({
      url:   "/app/api/ApiUseTicket",
      method: "post",
      data
    });
  },
  // 获取CmsItem按照Event统计
  getEventRankList(data) {
    return request({
      url: "/app/api/ApiGetEventRankList",
      method: "post",
      data
    });
  },
  // 获取学习时长按照Event统计
  getStaticsSum(data) {
    return request({
      url: "/app/api/ApiGetUserStaticsSum",
      method: "post",
      data
    });
  },
};
export default appApi;
src/assets/js/middleGround/api/edu.js
New file
@@ -0,0 +1,166 @@
import request from '@/plugin/axios/index.ts'
import { handleQueryResourceListData } from '../tool'
const eduApi = {
  // 获取商品下的组卷策略
  getQuizConfigListByProduct(data) {
    return request({
      url: '/edu/api/ApiGetQuizConfigListByProduct',
      method: 'post',
      data,
    })
  },
  // 获取组卷结果
  getEduQuizConfigResult(data) {
    return request({
      url: '/edu/api/ApiGetEduQuizConfigResult',
      method: 'post',
      data,
    })
  },
  //申请课程
  applyNewCourse(data) {
    return request({
      url: '/edu/api/ApiApplyNewCourse',
      method: 'post',
      data,
    })
  },
  //更新课程申请信息
  updateCourseApply(data) {
    return request({
      url: '/edu/api/ApiUpdateCourseApply',
      method: 'post',
      data,
    })
  },
  //获取我的课程
  getAppCourseList(data) {
    return request({
      url: '/edu/api/ApiGetAppCourseList',
      method: 'post',
      data,
    })
  },
  //获取已申请的课程详情
  getCourseById(data) {
    return request({
      url: '/edu/api/ApiGetCourseById',
      method: 'post',
      data,
    })
  },
  //获取创建课程中的班级列表
  getCourseClassList(data) {
    return request({
      url: '/edu/api/ApiGetCourseClassList',
      method: 'post',
      data,
    })
  },
  //创建班级信息
  newCourseClass(data) {
    return request({
      url: '/edu/api/ApiNewCourseClass',
      method: 'post',
      data,
    })
  },
  //删除班级信息
  delCourseClass(data) {
    return request({
      url: '/edu/api/ApiDelCourseClass',
      method: 'post',
      data,
    })
  },
  // 更新班级信息
  updateCourseClass(data) {
    return request({
      url: '/edu/api/ApiUpdateCourseClass',
      method: 'post',
      data,
    })
  },
  //创建课程订单
  createCourseOrder(data) {
    return request({
      url: '/store/api/CreateCourseOrder',
      method: 'post',
      data,
    })
  },
  // 免费领取课程
  makeFreeOrderPay(data) {
    return request({
      url: '/store/api/MakeFreeOrderPay',
      method: 'post',
      data,
    })
  },
  // 获取排名结果
  getRankingList(data) {
    return request({
      url: '/edu/api/ApiGetRankingList',
      method: 'post',
      data,
    })
  },
  //获取个人排名
  getRanking(data) {
    return request({
      url: '/edu/api/ApiGetTopRanking',
      method: 'post',
      data,
    })
  },
  // 新建排名记录
  newRanking(data) {
    return request({
      url: '/edu/api/ApiNewRanking',
      method: 'post',
      data,
    })
  },
  // 删除组卷规则
  delQuizConfig(data) {
    return request({
      url: '/edu/admin/DelQuizConfig',
      method: 'post',
      data,
    })
  },
  // 更新组卷规则
  updateQuizConfig(data) {
    return request({
      url: '/edu/admin/UpdateQuizConfig',
      method: 'post',
      data,
    })
  },
  // 根据ID获取组卷配置
  getQuizConfig(data) {
    return request({
      url: '/edu/admin/GetQuizConfig',
      method: 'post',
      data,
    })
  },
}
export default eduApi
src/assets/js/middleGround/api/file.js
New file
@@ -0,0 +1,94 @@
import request from "@/plugin/axios/index.ts";
const fileApi = {
  // 获取pdf总页数
  getPdfTotalPage(data) {
    return request({
      url: "/file/GetPdfTotalPage",
      method: "post",
      data
    });
  },
  // 获取pdf、word、ppt等转图片预览
  getPdfInfo(data) {
    return request({
      url: "/file/GetPdfInfo",
      method: "post",
      data
    });
  },
  //获取pdf目录
  GetPdfToc(data) {
    return request({
      url: "/file/GetPdfToc",
      method: "post",
      data
    });
  },
  //获取文件
  getPdfPageImage(params) {
    return request({
      url: '/file/GetPdfPageImage',
      method: 'get',
      responseType: 'blob',
      params
    });
  },
  //上传文件
  upload(data) {
    return request({
      url: "/file/api/ApiUpload",
      method: "post",
      data
    });
  },
  // 获取阿里云加速地址
  getAliVod(data) {
    return request({
      url: "/file/GetAliVod",
      method: "post",
      data,
    });
  },
  downloadForAuthorize(params) {
    return request({
      url: '/file/api/ApiDownloadForAuthorize',
      method: 'GET',
      responseType: 'blob',
      params
    });
  },
  // 批量下载
  downloadFiles(data) {
    return request({
      url: '/file/api/ApiDownloadFiles',
      method: 'post',
      responseType: 'blob',
      data
    });
  },
  // 批量下载get
  getDownloadFiles (params) {
    return request({
      url: '/file/api/ApiGetDownloadFiles',
      method: 'GET',
      responseType: 'blob',
      headers:{
        'md5s':params
      }
    });
  },
  // 发送下载邮件
  sendFileEmail (data) {
    return request({
      url:'/file/api/ApiSendFileWithEmail',
      method:'post',
      data
    })
  }
}
export default fileApi;
src/assets/js/middleGround/api/identity.js
New file
@@ -0,0 +1,181 @@
import request from "@/plugin/axios/index.ts";
const identityApi = {
  // 获取图形验证码
  getImgCode() {
    return request({
      url: "/identity/NewCaptcha",
      method: "post",
    });
  },
  // 验证图形验证码
  verificationImgCode(data) {
    return request({
      url: "/identity/ValidCaptcha",
      method: "post",
      data,
    });
  },
  // 获取短信验证码
  getPhoneCode(data) {
    return request({
      url: "/identity/NewSms",
      method: "post",
      data,
    });
  },
  // 验证短信验证码
  verificationPhoneCode(data) {
    return request({
      url: "/identity/api/ApiValidMobilePhone",
      method: "post",
      data,
    });
  },
  // 通过手机号注册用户
  registerAppUserWithPhone(data) {
    return request({
      url: "/identity/api/RegisterAppUserWithPhone",
      method: "post",
      data,
    });
  },
  // 账号密码登录
  loginByPassword(data) {
    return request({
      url: "/identity/api/LoginByPassword",
      method: "post",
      data,
    });
  },
  // 短信验证码登录
  loginByMobilePhone(data) {
    return request({
      url: "/identity/api/LoginByMobilePhone",
      method: "post",
      data,
    });
  },
  // 设置用户key
  setUserKey(data) {
    return request({
      url: "/identity/api/ApiAppUserSetKey",
      method: "post",
      data,
    });
  },
  // 获取用户key
  getUserKey(data) {
    return request({
      url: "/identity/api/ApiGetAppUserKey",
      method: "post",
      data,
    });
  },
  // 删除用户key
  delUserKey(data) {
    return request({
      url: "/identity/api/ApiDelAppUserKey",
      method: "post",
      data,
    });
  },
  // 获取去当前用户信息
  getCurrentAppUser() {
    return request({
      url: "/identity/api/GetCurrentAppUser",
      method: "post",
    });
  },
  // 添加用户信息
  setAppUserInfo(data) {
    return request({
      url: "/identity/api/SetAppUserInfoRequest",
      method: "post",
      data,
    });
  },
  // 用户更换绑定手机号,如没有绑定手机则自动创建
  userSetPhoneNumber(data) {
    return request({
      url: "/identity/api/ApiUserSetPhoneNumber",
      method: "post",
      data,
    });
  },
  // 检测用户是否绑定微信
  checkBuildingWeChat(data) {
    return request({
      url: "/identity/api/ApiCheckBuildingWeChat",
      method: "post",
      data,
    });
  },
  // 通过手机号重置密码
  changePasswordByMobilePhone(data) {
    return request({
      url: "/identity/api/ChangePasswordByMobilePhone",
      method: "post",
      data,
    });
  },
  // 微信开放平台扫码登录
  loginByWeChatOpenCode(data) {
    return request({
      url: "/identity/api/LoginByWeChatOpenCode",
      method: "post",
      data,
    });
  },
  // 用户绑定微信号
  bindingWeChat(data) {
    return request({
      url: "/identity/api/ApiBindingWeChat",
      method: "post",
      data,
    });
  },
  // 设置登录的用户名和密码,用户名和密码至少6位
  setLoginNameAndPassword(data) {
    return request({
      url: "/identity/api/ApiUserSetLoginNameAndPassword",
      method: "post",
      data,
    });
  },
  // 获取邮箱验证码
  getEmailCode(data) {
    return request({
      url: "/identity/api/SendVerifyEMail",
      method: "post",
      data,
    });
  },
  // 用户绑定邮箱
  bindingEmail(data) {
    return request({
      url: "/identity/api/ApiBindEMail",
      method: "post",
      data,
    });
  },
};
export default identityApi;
src/assets/js/middleGround/api/job.js
New file
@@ -0,0 +1,34 @@
import request from "@/plugin/axios/index.ts";
import { tokenKey } from "@/assets/js/config";
import toolClass from "@/assets/js/toolClass";
const jobApi = {
  // 统计
  newJobWithNewView(data) {
    return request({
      url: "/job/api/NewJobWithNewView",
      method: "post",
      data
    });
  },
  newSession(data) {
    let token = toolClass.getCookie(tokenKey);
    return request({
      url: token ? "/job/api/AppUserNewSession" : "/job/api/NewSession",
      method: "post",
      data
    });
  },
  newJobWithApiNewEvent(data){
    return request({
      url: "/job/api/NewJobWithApiNewEvent",
      method: "post",
      data
    });
  }
};
export default jobApi;
src/assets/js/middleGround/api/resource.js
New file
@@ -0,0 +1,221 @@
import request from "@/plugin/axios/index.ts";
import { publicStore, publicRepository } from "@/assets/js/config";
import { tokenKey } from "@/assets/js/config";
import { handleQueryResourceListData } from "../tool";
import toolClass from "@/assets/js/toolClass";
const resourceApi = {
  /*
    **获取资源列表&详情**
    path: 数据路径
    storeInfo: 仓储
    repositoryInfo: 仓库
    queryType: 检索类型
    paging: 分页
    sort: 排序
    fields: 自定义字段
    itemId: 获取详情时的资源ID
  */
  getItem: ({
    path,
    storeInfo = publicStore,
    repositoryInfo = publicRepository,
    queryType,
    linkType,
    paging,
    sort,
    fields,
    itemId,
    itemIds,
    itemType,
    coverSize,
    itemIdArr,
    SysType,
    tourism_isHighQualityResources,
  }) => {
    if (!path) return Promise.reject("接口请求必要参数不能为空!");
    const query = {
      AccessControl: {
        Path: path,
        StoreRefCode: storeInfo + "",
        RepositoryRefCode: repositoryInfo + "",
        Type: queryType || "\\",
        LinkType: linkType || "",
      },
      PageQuery: {
        Start: paging?.start || "0",
        Size: paging?.size || "10",
      },
      SortQuery: sort ? [sort] : [{
        LinkOrder: "Desc"
      }],
      CreateDate: [],
      Description: [],
      Name: [],
      Icon: [],
      RefCode: [],
      Type: [],
      TypeId: [],
      State: [],
      Tag: [],
      LinkInfo: [],
      LinkFile: [],
      CmsItemType: [],
      ChildrenFolderCount: [],
      ChildrenCount: [],
      ...fields,
    };
    if (itemIdArr) query["Id"] = itemIdArr;
    if (SysType) query["SysType="] = [`${SysType}`];
    if (tourism_isHighQualityResources)
      query["tourism_isHighQualityResources="] = [
        `${tourism_isHighQualityResources}`,
      ];
    if (itemId) query["Id="] = [`${itemId}`];
    if (itemIds) query["Id="] = itemIds;
    if (itemType) query["Type="] = [`${itemType}`];
    const body = { query: JSON.stringify({ Query: [{ Q1: query }] }) };
    let token = localStorage.getItem(tokenKey);
    return request({
      url: token ? "/resource/api/ApiAppUserQuery" : "/resource/api/ApiQuery",
      method: "post",
      data: body,
    }).then((resp) => {
      if (resp.length > 0) {
        const data = resp[0];
        const datas = handleQueryResourceListData({
          datas: data.datas,
          fields,
          path,
          storeInfo,
          repositoryInfo,
          coverSize,
        });
        return { datas, total: data.totalCount };
      }
      return { datas: [], total: 0 };
    });
  },
  // 模糊搜索
  EsQuery(query) {
    let { params, path, paging } = query;
    let queryBody = {
      Type: "*",
      Store: [],
      ItemType: [],
      CmsType: [],
      SysType: ["CmsItem"],
      LinkInfo: [],
      PageQuery: {
        Start: paging?.start || "0",
        Size: paging?.size || "10",
      },
    };
    // 设置不同的Path
    // 如果没有搜索关键字,则只用获取名称
    if (params.length > 0) {
      let data = {
        "||Name": [...params],
        "||tourism_content*": [...params],
        "||tourism_workflow*": [...params],
        "||tourism_notes*": [...params],
        "||tourism_caseIndex*": [...params],
        "||tourism_basicCase*": [...params],
        "||tourism_judgmentAndReasons*": [...params],
        "||tourism_legalIssuesInvolvedInThisCase*": [...params],
        "||tourism_referenceAnswerAndLegalAnalysis*": [...params],
        "||tourism_case*": [...params],
        "||tourism_clause*": [...params],
        "||tourism_unscramble*": [...params],
        "||tourism_specialRemind*": [...params],
        "||tourism_fiction*": [...params],
        "||tourism_authorityNature*": [...params],
        "||tourism_authorityGist*": [...params],
        "||tourism_penaltyGist*": [...params],
        "||tourism_penaltyTerms*": [...params],
        "||tourism_penaltyType*": [...params],
        "||tourism_remarksNote*": [...params],
        "||tourism_keyword*": [...params],
      };
      Object.assign(queryBody, data);
    } else {
      let data = {
        Name: [],
      };
      Object.assign(queryBody, data);
    }
    // 全部搜索 - 单独的某个库
    if (path != "All") {
      let data = {
        Path: [
          {
            Repository: "tourism_tourismLawsAndRegulationsDatabase",
            Path: path,
          },
        ],
      };
      Object.assign(queryBody, data);
    }
    const body = { query: JSON.stringify({ Query: [{ Q1: queryBody }] }) };
    return request({
      url: "/resource/api/ApiEsQuery",
      method: "post",
      data: body,
    }).then((res) => {
      if (res.length > 0) {
        const data = res[0];
        const datas = handleQueryResourceListData({
          datas: data.datas,
          path,
        });
        return { datas, total: data.totalCount };
      }
      return { data: [], total: 0 };
    });
  },
  //获取资源类型
  getCmsTypeByRefCode(data) {
    return request({
      url: "resource/api/ApiGetCmsTypeByRefCode",
      method: "post",
      data,
    });
  },
  //取消cms收藏
  delCmsItemLink(data) {
    return request({
      url: "/resource/api/ApiDelCmsItemLink",
      method: "post",
      data,
    });
  },
  //cms收藏
  collectCmsItem(data) {
    return request({
      url: "/resource/api/ApiAddCmsItemLink",
      method: "post",
      data,
    });
  },
  // 获取cms收藏列表
  getCmsCollectList(data) {
    const body = { query: JSON.stringify({ Query: [{ Q1: data }] }) };
    return request({
      url: "/resource/api/ApiAppUserQuery",
      method: "post",
      data: body,
    });
  },
};
export default resourceApi;
src/assets/js/middleGround/api/store.js
New file
@@ -0,0 +1,879 @@
import request from '@/plugin/axios/index.ts'
import { tokenKey, goodsStore } from '@/assets/js/config'
import { handleQueryResourceListData, handleDetailQueryRequestData } from '../tool'
const storeApi = {
  /*
    **获取商品列表**
    path: 数据路径
    storeInfo: 仓储
    channelInfo: 频道
    subAccess:
    queryType: 检索类型
    paging: 分页
    sort: 排序
    fields: 自定义字段
  */
  getProductList: ({
    path = '',
    storeInfo = goodsStore,
    storeEventIdOrRefCode = '',
    favoriteTypes = '',
    queryType,
    linkType,
    subAccess = [],
    paging = {},
    sort,
    fields,
    filterList,
    coverSize,
    mainProductId,
    handelEBooK
  }) => {
    const query = {
      AccessControl: {
        Path: path,
        StoreRefCode: storeInfo + '',
        Type: queryType || '\\',
        LinkType: linkType || ''
      },
      FavoriteTypes: favoriteTypes ? [favoriteTypes] : [],
      SubAccess: subAccess.length > 0 ? subAccess : [],
      PageQuery: {
        Start: paging.start || '0',
        Size: paging.size || '10'
      },
      SortQuery:
        sort?.length == 0
          ? []
          : sort
            ? [sort]
            : [
                {
                  LinkOrder: 'Desc'
                }
              ],
      CreateDate: [],
      Description: [],
      Name: [],
      Icon: [],
      RefCode: [],
      TypeId: [],
      SysType: [],
      State: [],
      Tag: [],
      BeginDate: [],
      EndDate: [],
      ProductLinkInfo: [],
      AllowDonate: [],
      // DonatePriceList: [],
      StoreEvent: [],
      SubProductCount: [],
      SaleMethod: [],
      SaleMethodValid: [],
      StoreEventIdOrRefCode: storeEventIdOrRefCode,
      ...fields,
      ...filterList
    }
    if (mainProductId) {
      query.AccessControl.MainProductId = mainProductId
    }
    if (handelEBooK) {
      query.ProductCmsQuery = [
        {
          QueryCms: {
            Path: '*',
            Type: '\\',
            Name: [],
            Icon: [],
            TypeId: [],
            RefCode: [],
            ChildrenCount: [],
            ChildrenFolderCount: [],
            CreateDate: [],
            SysType: [],
            SaleMethod: [],
            PageQuery: {
              Start: 0,
              Size: 9999
            },
            ProductLinkInfo: []
          }
        }
      ]
    }
    const body = {
      query: JSON.stringify({
        Query: [
          {
            Q1: query
          }
        ]
      })
    }
    let token = localStorage.getItem(tokenKey)
    let url = token ? '/store/api/ApiQueryProductByAppUser' : '/store/api/ApiQueryProduct'
    return request({
      url: url,
      method: 'post',
      data: body
    }).then((resp) => {
      if (resp.length > 0) {
        const data = resp[0]
        const datas = handleQueryResourceListData({
          datas: data.datas,
          fields,
          path,
          storeInfo,
          coverSize,
          handelEBooK
        })
        return {
          datas,
          total: data.totalCount,
          extraInfos: data.extraInfos?.StoreEvent
        }
      }
      return {
        datas: [],
        total: 0
      }
    })
  },
  /*
    **获取商品详情**
    path: 数据路径
    storeInfo: 仓储
    channelInfo: 频道
    subAccess:
    fields: 自定义字段
    productId: 商品ID
    cmsPath:cmsPath
  */
  getProductDetail: ({
    path = '',
    storeInfo = goodsStore,
    channelInfo = '',
    favoriteTypes = '',
    queryType,
    subAccess = [],
    fields,
    productId,
    cmsPath,
    cmsType,
    coverSize,
    itemId,
    itemIds,
    itemFields,
    linkTypes,
    filterList,
    handelEBooK,
    sort,
    cmsSort,
    source
  }) => {
    const subQuery = {}
    if (cmsPath) {
      subQuery['QueryCms'] = {
        Path: cmsPath + '',
        Type: cmsType || '\\',
        Name: [],
        Icon: [],
        TypeId: [],
        RefCode: [],
        Description:[],
        ChildrenCount: [],
        ChildrenFolderCount: [],
        CreateDate: [],
        SysType: [],
        SaleMethod: [],
        PageQuery: {
          Start: 0,
          Size: 9999
        },
        SortQuery: cmsSort
          ? [cmsSort]
          : [
              {
                ProductLinkOrder: 'Asc'
              }
            ],
        ProductLinkInfo: [],
        ...itemFields
      }
      if (itemId) subQuery['QueryCms']['Id='] = [`${itemId}`]
      if (itemIds) subQuery['QueryCms']['Id='] = itemIds
    } else {
      subQuery['QueryCms'] = {
        Path: '*',
        Type: '\\',
        Name: [],
        Icon: [],
        TypeId: [],
        RefCode: [],
        Description:[],
        ChildrenCount: [],
        ChildrenFolderCount: [],
        CreateDate: [],
        SysType: [],
        SaleMethod: [],
        PageQuery: {
          Start: 0,
          Size: 9999
        },
        ProductLinkInfo: []
      }
    }
    // 获取关联资源
    let linkFields = {}
    if (linkTypes && linkTypes.length) {
      for (let i = 0; i < linkTypes.length; i++) {
        const linkType = linkTypes[i]
        subQuery['QueryLink_' + linkType.linkType] = {
          Path: cmsPath + '',
          Type: '\\',
          Name: [],
          Icon: [],
          TypeId: [],
          RefCode: [],
          Description:[],
          LinkTypes: [linkType.linkType],
          PageQuery: {
            Start: 0,
            Size: 100
          },
          ProductLinkInfo: [],
          ...linkType.fields
        }
        linkFields = {
          ...linkFields,
          ...linkType.fields
        }
      }
    }
    const query = {
      AccessControl: {
        Path: path,
        StoreRefCode: storeInfo + '',
        ChannelRefCode: channelInfo + '',
        Type: queryType || '\\'
      },
      FavoriteTypes: favoriteTypes ? [favoriteTypes] : [],
      SubAccess: subAccess.length > 0 ? subAccess : [],
      PageQuery: {
        Start: '0',
        Size: '1'
      },
      'Id=': [`${productId}`],
      SortQuery: sort
        ? [sort]
        : [
            {
              LinkOrder: 'Desc'
            }
          ],
      CreateDate: [],
      Description: [],
      Name: [],
      Icon: [],
      RefCode: [],
      Description:[],
      TypeId: [],
      SysType: [],
      State: [],
      Tag: [],
      BeginDate: [],
      EndDate: [],
      ProductLinkInfo: [],
      AllowDonate: [],
      DonatePriceList: [],
      StoreEvent: [],
      SaleMethod: [],
      SaleMethodValid: [],
      CmsItemValid: [],
      ProductCmsQuery: [subQuery],
      ...fields,
      ...filterList
    }
    if (productId) query['Id='] = [`${productId}`]
    const body = {
      query: JSON.stringify({
        Query: [
          {
            Q1: query
          }
        ]
      })
    }
    let token = localStorage.getItem(tokenKey)
    let url = token ? '/store/api/ApiQueryProductByAppUser' : '/store/api/ApiQueryProduct'
    return request({
      url: url,
      method: 'post',
      data: body,
      cancelToken: source?.token
    })
      .then((resp) => {
        if (resp.length > 0) {
          const data = resp[0]
          if (data.datas.length) {
            data.datas[0].subDatas = data.datas[0].cmsDatas
            const datas = handleDetailQueryRequestData({
              item: data.datas[0],
              fields,
              itemFields: {
                ...itemFields,
                ...linkFields
              },
              path,
              coverSize,
              handelEBooK,
            })
            return {
              datas,
              total: data.totalCount
            }
          } else {
            return {
              datas: [],
              total: 0
            }
          }
        }
        return {
          datas: [],
          total: 0
        }
      })
  },
  // 获取商品详情,不返回 ChildrenCount,ChildrenFolderCount
  // (此接口为了满足不返回 ChildrenCount,ChildrenFolderCount而后续添加的) 不是中台原有的
  getProductDetailNoChildren:({
    path = '',
    storeInfo = goodsStore,
    channelInfo = '',
    favoriteTypes = '',
    queryType,
    subAccess = [],
    fields,
    productId,
    cmsPath,
    cmsType,
    coverSize,
    itemId,
    itemIds,
    itemFields,
    linkTypes,
    filterList,
    handelEBooK,
    sort,
    cmsSort,
    source
  }) => {
    const subQuery = {}
    if (cmsPath) {
      subQuery['QueryCms'] = {
        Path: cmsPath + '',
        Type: cmsType || '\\',
        Name: [],
        Icon: [],
        TypeId: [],
        RefCode: [],
        Description:[],
        // ChildrenCount: [],
        // ChildrenFolderCount: [],
        CreateDate: [],
        SysType: [],
        SaleMethod: [],
        PageQuery: {
          Start: 0,
          Size: 9999
        },
        SortQuery: cmsSort
          ? [cmsSort]
          : [
              {
                ProductLinkOrder: 'Asc'
              }
            ],
        ProductLinkInfo: [],
        ...itemFields
      }
      if (itemId) subQuery['QueryCms']['Id='] = [`${itemId}`]
      if (itemIds) subQuery['QueryCms']['Id='] = itemIds
    } else {
      subQuery['QueryCms'] = {
        Path: '*',
        Type: '\\',
        Name: [],
        Icon: [],
        TypeId: [],
        RefCode: [],
        Description:[],
        ChildrenCount: [],
        ChildrenFolderCount: [],
        CreateDate: [],
        SysType: [],
        SaleMethod: [],
        PageQuery: {
          Start: 0,
          Size: 9999
        },
        ProductLinkInfo: []
      }
    }
    // 获取关联资源
    let linkFields = {}
    if (linkTypes && linkTypes.length) {
      for (let i = 0; i < linkTypes.length; i++) {
        const linkType = linkTypes[i]
        subQuery['QueryLink_' + linkType.linkType] = {
          Path: cmsPath + '',
          Type: '\\',
          Name: [],
          Icon: [],
          TypeId: [],
          RefCode: [],
          Description:[],
          LinkTypes: [linkType.linkType],
          PageQuery: {
            Start: 0,
            Size: 100
          },
          ProductLinkInfo: [],
          ...linkType.fields
        }
        linkFields = {
          ...linkFields,
          ...linkType.fields
        }
      }
    }
    const query = {
      AccessControl: {
        Path: path,
        StoreRefCode: storeInfo + '',
        ChannelRefCode: channelInfo + '',
        Type: queryType || '\\'
      },
      FavoriteTypes: favoriteTypes ? [favoriteTypes] : [],
      SubAccess: subAccess.length > 0 ? subAccess : [],
      PageQuery: {
        Start: '0',
        Size: '1'
      },
      'Id=': [`${productId}`],
      SortQuery: sort
        ? [sort]
        : [
            {
              LinkOrder: 'Desc'
            }
          ],
      CreateDate: [],
      Description: [],
      Name: [],
      Icon: [],
      RefCode: [],
      Description:[],
      TypeId: [],
      SysType: [],
      State: [],
      Tag: [],
      BeginDate: [],
      EndDate: [],
      ProductLinkInfo: [],
      AllowDonate: [],
      DonatePriceList: [],
      StoreEvent: [],
      SaleMethod: [],
      SaleMethodValid: [],
      CmsItemValid: [],
      ProductCmsQuery: [subQuery],
      ...fields,
      ...filterList
    }
    if (productId) query['Id='] = [`${productId}`]
    const body = {
      query: JSON.stringify({
        Query: [
          {
            Q1: query
          }
        ]
      })
    }
    let token = localStorage.getItem(tokenKey)
    let url = token ? '/store/api/ApiQueryProductByAppUser' : '/store/api/ApiQueryProduct'
    return request({
      url: url,
      method: 'post',
      data: body,
      cancelToken: source?.token
    })
      .then((resp) => {
        if (resp.length > 0) {
          const data = resp[0]
          if (data.datas.length) {
            data.datas[0].subDatas = data.datas[0].cmsDatas
            const datas = handleDetailQueryRequestData({
              item: data.datas[0],
              fields,
              itemFields: {
                ...itemFields,
                ...linkFields
              },
              path,
              coverSize,
              handelEBooK,
            })
            return {
              datas,
              total: data.totalCount
            }
          } else {
            return {
              datas: [],
              total: 0
            }
          }
        }
        return {
          datas: [],
          total: 0
        }
      })
  },
  // 获取优惠券列表
  getChannelPromoteCodeList(data) {
    return request({
      url: '/store/api/ApiGetChannelPromoteCodeList',
      method: 'post',
      data
    })
  },
  // 获取用户已领取的优惠券列表
  getPromoteCodeList(data) {
    return request({
      url: '/store/api/ApiGetPromoteCodeList',
      method: 'post',
      data
    })
  },
  // 获取用户浏览排行
  getProductViewRank(data) {
    return request({
      url: '/store/api/ApiGetProductViewRank',
      method: 'post',
      data
    })
  },
  // 获取用户销售排行
  getProductSaleRank(data) {
    return request({
      url: '/store/api/ApiGetProductSaleRank',
      method: 'post',
      data
    })
  },
  // 获取商品可用优惠券
  getProductPromoteCodeList(data) {
    return request({
      url: '/store/api/ApiGetProductPromoteCodeList',
      method: 'post',
      data
    })
  },
  // 获取订单可用优惠券
  getOrderPromoteCodeList(data) {
    return request({
      url: '/store/api/GetOrderPromoteCodeList',
      method: 'post',
      data
    })
  },
  // 获取销售方式可用优惠券
  getSaleMethodPromoteCodeList(data) {
    return request({
      url: '/store/api/GetSaleMethodPromoteCodeList',
      method: 'post',
      data
    })
  },
  // 领取优惠卷
  getPromoteCode(data) {
    return request({
      url: '/store/api/ApiGetPromoteCode',
      method: 'post',
      data
    })
  },
  // 为订单使用优惠券
  updateOrderPromoteCode(data) {
    return request({
      url: '/store/api/UpdateOrderPromoteCode',
      method: 'post',
      data
    })
  },
  // 为销售方式使用优惠券
  updateSaleMethodPromoteCode(data) {
    return request({
      url: '/store/api/UpdateSaleMethodPromoteCode',
      method: 'post',
      data
    })
  },
  // 通过订单号获取订单
  getOrderByOrderNum(data) {
    return request({
      url: '/store/api/GetOrderByOrderNum',
      method: 'post',
      data
    })
  },
  // 创建订单
  initOrder(data) {
    return request({
      url: '/store/api/InitOrder',
      method: 'post',
      data
    })
  },
  // 确认订单
  confirmOrder(data) {
    return request({
      url: '/store/api/ConfirmOrder',
      method: 'post',
      data
    })
  },
  // 取消订单
  cancelOrder(data) {
    return request({
      url: '/store/api/CancelOrder',
      method: 'post',
      data
    })
  },
  // 赞赏
  CreateDonateOrder(data) {
    return request({
      url: '/store/api/CreateDonateOrder',
      method: 'post',
      data
    })
  },
  //获取用户订单列表
  getUserOrderList(data) {
    return request({
      url: '/store/api/GetUserOrderList',
      method: 'post',
      data
    })
  },
  //获取频道下的列表
  getStoreChannelList(data) {
    return request({
      url: '/store/api/ApiGetStoreChannelList',
      method: 'post',
      data
    })
  },
  //获取购物车
  getShoppingCartProductList(data) {
    return request({
      url: '/store/api/ApiGetShoppingCartProductList',
      method: 'post',
      data
    })
  },
  //添加到购物车
  addShoppingCart(data) {
    return request({
      url: '/store/api/ApiAddShoppingCart',
      method: 'post',
      data
    })
  },
  //购物车删除商品
  delShoppingCart(data) {
    return request({
      url: '/store/api/ApiDelShoppingCart',
      method: 'post',
      data
    })
  },
  //从购物车创建订单
  shoppingCartCreateOrder(data) {
    return request({
      url: '/store/api/ApiShoppingCartCreateOrder',
      method: 'post',
      data
    })
  },
  //获取已购买的商品列表
  getPurchasedProductList(data) {
    return request({
      url: '/store/api/ApiGetPurchasedProductList',
      method: 'post',
      data
    })
  },
  //调取微信支付
  makeWeChatPay(data) {
    return request({
      url: '/store/api/MakeWeChatPay',
      method: 'post',
      data
    })
  },
  //调取微信二维码支付
  makeWeChatQrPay(data) {
    return request({
      url: '/store/api/MakeWeChatQrPay',
      method: 'post',
      data
    })
  },
  // 获取激活码详情
  getActiveCode(data) {
    return request({
      url: '/store/api/ApiGetActiveCode',
      method: 'post',
      data
    })
  },
  // 使用激活码
  userActiveCode(data) {
    return request({
      url: '/store/api/ApiUseActiveCode',
      method: 'post',
      data
    })
  },
  // 使用激活码使用记录
  userActiveCodeList(data) {
    return request({
      url: '/store/api/ApiGetUsedActiveCodeList',
      method: 'post',
      data
    })
  },
  // 商品查询类型字段接口
  getProductTypeField(data) {
    return request({
      url: '/store/api/ApiGetProductTypeField',
      method: 'post',
      data
    })
  },
  // 收藏或加入书架
  addProductLink(data) {
    return request({
      url: '/store/api/ApiAddProductLink',
      method: 'post',
      data
    })
  },
  // 取消收藏或移除书架
  delProductLink(data) {
    return request({
      url: '/store/api/ApiDelProductLink',
      method: 'post',
      data
    })
  },
  //购买免费商品
  MakeFreeOrderPay(data) {
    return request({
      url: '/store/api/MakeFreeOrderPay',
      method: 'post',
      data
    })
  },
  // 申请订单开票
  requestOrderInvoice(data) {
    return request({
      url: '/store/api/RequestOrderInvoice',
      method: 'post',
      data
    })
  },
  // 获取用户钱包
  getUserWallet(data) {
    return request({
      url: '/store/api/GetWallet',
      method: 'post',
      data
    })
  },
  // 获取用户钱包记录
  getWalletHistory(data) {
    return request({
      url: '/store/api/GetWalletHistory',
      method: 'post',
      data
    })
  },
  // 通过钱包自动购买
  autoPayWithWallet(data) {
    return request({
      url: '/store/api/AutoPayWithWallet',
      method: 'post',
      data
    })
  },
  // 查询商品所在Store
  getProductStore(data) {
    return request({
      url: '/store/api/ApiGetProductStore',
      method: 'post',
      data
    })
  },
  //根据销售方式查询商品信息
  getProductBySaleMethod(data) {
    return request({
      url: '/store/api/ApiGetProductBySaleMethod',
      method: 'post',
      data
    })
  }
}
export default storeApi
src/assets/js/middleGround/api/ugc.js
New file
@@ -0,0 +1,98 @@
import request from "@/plugin/axios/index.ts";
import { tokenKey } from "@/assets/js/config";
import toolClass from "@/assets/js/toolClass.js";
const ugcApi = {
  // 获取商品点赞Topic
  getProductLikesTopic(data) {
    return request({
      url: localStorage.getItem(tokenKey)
        ? "/ugc/api/ApiAppUserGetProductLikesTopic"
        : "/ugc/api/ApiGetProductLikesTopic",
      method: "post",
      data,
    });
  },
  // 获取商品评论Topic
  getProductCommentTopic(data) {
    return request({
      url: localStorage.getItem(tokenKey)
        ? "/ugc/api/ApiAppUserGetProductCommentTopic"
        : "/ugc/api/ApiGetProductCommentTopic",
      method: "post",
      data,
    });
  },
  // 获取MessageList
  getTopicMessageList(data) {
    return request({
      url: localStorage.getItem(tokenKey)
        ? "/ugc/api/ApiAppUserGetTopicMessageList"
        : "/ugc/api/ApiGetTopicMessageList",
      method: "post",
      data,
    });
  },
  // 用户根据消息类型获取列表
  getMessageList(data) {
    return request({
      url: "/ugc/api/ApiGetMessageList",
      method: "post",
      data,
    });
  },
  // 新建Message
  newTopicMessage(data) {
    return request({
      url: "/ugc/api/ApiNewTopicMessage",
      method: "post",
      data,
    });
  },
  // 删除Message
  delTopicMessage(data) {
    return request({
      url: "/ugc/api/ApiDelTopicMessage",
      method: "post",
      data,
    });
  },
  // 更新message
  updateTopicMessage(data) {
    return request({
      url:'/ugc/api/ApiUpdateTopicMessage',
      method:'post',
      data
    })
  },
  // 获取cms评论
  getCmsItemCommentTopic(data) {
    return request({
      url: "/ugc/api/ApiGetCmsItemCommentTopic",
      method: "post",
      data,
    });
  },
  // 获取用户提交的教学资源
  getProductUserSubmitTopic(data) {
    return request({
      url: "/ugc/api/ApiGetProductUserSubmitTopic",
      method: "post",
      data,
    });
  },
  //更新TOPICMESSAGE
  // updateTopicMessage(data) {
  //   return request({
  //     url: "/ugc/api/ApiUpdateTopicMessage",
  //     method: "post",
  //     data,
  //   });
  // },
};
export default ugcApi;
src/assets/js/middleGround/tool.js
New file
@@ -0,0 +1,418 @@
import { requestCtx, appId } from '@/assets/js/config'
import bookCover from '@/assets/images/default/red-book.png'
import moment from 'moment'
// 处理列表查询结果
export function handleQueryResourceListData({
  datas,
  fields,
  path,
  storeInfo,
  repositoryInfo,
  coverSize,
  handelEBooK,
}) {
  const dataList = []
  for (let i = 0; i < datas.length; i++) {
    const item = datas[i]
    // 处理字段
    const _fields = {}
    if (fields != null) {
      for (let fieldKey in fields) {
        if (item.datas[fieldKey]) {
          const values = JSON.parse(item.datas[fieldKey])
          if (values.length > 0) {
            // 用字段名处理返回的字段值
            if (values[0].Value) {
              _fields[fieldKey] = values[0].Value
            } else if (values[0].Data) {
              _fields[fieldKey] = values[0].Data.Value
            }
            item.datas[fieldKey] = values[0]
            if (fieldKey == 'telphone') {
              item.datas[fieldKey] = values.map((item) => item.Value)
            }
          }
        }
      }
    }
    const subDatas = {}
    if (item.subDatas) {
      for (let subData of item.subDatas) {
        const tag = subData.queryTag.replace('Query', '')
        subDatas[tag] = subData.datas
      }
    }
    let obj = {
      ...item,
      id: item.id,
      name: item.datas.Name,
      icon: getPublicImage(item.datas.Icon, coverSize?.width, coverSize?.height, storeInfo),
      repositoryInfo: repositoryInfo,
      refCode: item.datas.RefCode === '[]' ? null : item.datas.RefCode,
      state: item.datas.State,
      type: item.datas.Type,
      tag: item.datas.Tag,
      creator: item.datas.Creator ? JSON.parse(item.datas.Creator) : undefined,
      storeInfo: storeInfo,
      linkType: item.datas.LinkType,
      childrenCount: parseInt(item.datas.ChildrenCount ?? '0'),
      childrenFolderCount: parseInt(item.datas.ChildrenFolderCount ?? '0'),
      childrenChannelCount: parseInt(item.datas.ChildrenChannelCount ?? '0'),
      createDate: moment(item.datas.CreateDate).format('YYYY-MM-DD'),
      beginDate: moment(item.datas.BeginDate).format('YYYY-MM-DD'),
      endDate: moment(item.datas.EndDate).format('YYYY-MM-DD'),
      description: item.datas.Description,
      sysType: item.datas.SysType,
      idPath: path + '\\' + item.id,
      typeId: parseInt(item.datas.TypeId),
      linkFile: JSON.parse(item.datas.LinkFile ?? '[]'),
      cmsItemType: item.datas.CmsItemType,
      allowDonate: item.datas.AllowDonate == 'True',
      // donatePriceList: JSON.parse(item.datas.DonatePriceList ?? "[]"),
      productLinkInfo: item.datas.ProductLinkInfo ?? '[]',
      storeEvent: JSON.parse(item.datas.StoreEvent ?? '[]'),
      linkInfo: JSON.parse(item.datas.LinkInfo ?? '[]'),
      saleMethod: JSON.parse(item.datas.SaleMethod ?? '[]'),
      subProductCount: parseInt(item.datas.SubProductCount),
      ..._fields,
      datas: item.datas,
      subDatas,
    }
    // 统一处理价格
    if (obj.defaultSaleMethod) {
      if (handelEBooK) {
        // 获取随书资源的销售方式
        let saleMethod = []
        try {
          saleMethod = obj.cmsDatas[0].datas.find(
            (item) => item.datas.RefCode == 'tourism_accompanyingResources',
          ).datas.SaleMethod
          saleMethod = JSON.parse(saleMethod)
        } catch (error) {
          saleMethod = []
        }
        if (saleMethod.length) {
          Object.keys(saleMethod[0]).map((key) => {
            let newKey = key.replace(key[0], key[0].toLowerCase())
            saleMethod[0][newKey] = saleMethod[0][key]
            delete saleMethod[0][key]
          })
          obj.defaultSaleMethod = saleMethod[0]
          obj.defaultSaleMethodId = saleMethod[0].id
          obj.alreadyBuy = obj.purchasedSaleMethodIdList.indexOf(obj.defaultSaleMethodId) > -1
        }
      }
      if (obj.defaultSaleMethod.allowEvent && obj.storeEvent.length) {
        // 已参加活动,获取有效活动并计算价格
        let time = new Date().getTime()
        // 过滤过期活动
        let event = obj.storeEvent.filter((item) => {
          let endTime = new Date(item.EndDate).getTime()
          return endTime > time
        })
        // 只处理一条有效活动
        if (event.length) {
          obj.price = (obj.defaultSaleMethod.price * event[0].Value).toFixed(2)
          obj.oldPrice = obj.defaultSaleMethod.price
          obj.storeEventId = event[0].Id
          if (
            moment().format('YYYY-MM-DD') <
            moment(obj.defaultSaleMethod.endDate).format('YYYY-MM-DD')
          ) {
            obj.defaultSaleMethodState = 'Normal'
          } else {
            obj.defaultSaleMethodState = 'Beyond'
          }
        }
      } else {
        if (
          moment().format('YYYY-MM-DD') < moment(obj.defaultSaleMethod.endDate).format('YYYY-MM-DD')
        ) {
          obj.defaultSaleMethodState = 'Normal'
        } else {
          obj.defaultSaleMethodState = 'Beyond'
        }
        obj.price = obj.defaultSaleMethod.price
        obj.oldPrice = obj.defaultSaleMethod.virtualPrice
      }
    }
    dataList.push(obj)
  }
  return dataList
}
// 处理详情查询结果
export function handleDetailQueryRequestData({
  item,
  fields,
  path,
  coverSize,
  itemFields,
  handelEBooK,
}) {
  item.fileMap = {}
  let itemFieldsData = []
  for (const key in itemFields) {
    itemFieldsData.push(key)
  }
  let fieldsData = []
  for (const key in fields) {
    fieldsData.push(key)
  }
  for (let i = 0; i < fieldsData.length; i++) {
    const field = fieldsData[i]
    item.datas[field] = JSON.parse(item.datas[field])
    const datas = item.datas[field]
    if (datas.length > 0) {
      if (datas[0].Value) {
        item[field] = datas[0].Value
        if (datas[0].Data.FileLinkList && datas[0].Data.FileLinkList.length) {
          item.fileMap = {
            ...item.fileMap,
            ...handleLinkFileInfo(
              datas[0].Data.FileLinkList.map((item) => {
                return {
                  ...item.File,
                  ...item,
                }
              }),
            ),
          }
        }
      } else if (datas[0].Data) {
        item[field] = datas[0].Data.Value
        if (datas[0].Data.FileLinkList && datas[0].Data.FileLinkList.length) {
          item.fileMap = {
            ...item.fileMap,
            ...handleLinkFileInfo(
              datas[0].Data.FileLinkList.map((item) => {
                return {
                  ...item.File,
                  ...item,
                }
              }),
            ),
          }
        }
      }
    }
  }
  // 处理cms资源
  const subDatas = item.subDatas
  const linkItemsMap = {}
  if (subDatas) {
    for (const sdata of subDatas) {
      const tag = sdata.queryTag
      for (const subItem of sdata.datas) {
        convertCmsItemBase(subItem, coverSize, handelEBooK)
        subItem.fileMap = {}
        for (let i = 0; i < itemFieldsData.length; i++) {
          const itemField = itemFieldsData[i]
          try {
            subItem.datas[itemField] = JSON.parse(subItem.datas[itemField])
          } catch (error) {
            subItem.datas[itemField] = []
          }
          const itemDatas = subItem.datas[itemField]
          if (itemDatas.length > 0) {
            if (itemDatas[0].Value) {
              subItem[itemField] = itemDatas[0].Value
              if (itemDatas[0].FileList && itemDatas[0].FileList.length) {
                subItem.fileMap = {
                  ...subItem.fileMap,
                  ...handleLinkFileInfo(itemDatas[0].FileList),
                }
              }
            } else if (itemDatas[0].Data) {
              subItem[itemField] = itemDatas[0].Data.Value
              if (itemDatas[0].Data.FileList && itemDatas[0].Data.FileList.length) {
                subItem.fileMap = {
                  ...subItem.fileMap,
                  ...handleLinkFileInfo(itemDatas[0].Data.FileList),
                }
              }
            } else if (itemDatas[0].CmsItemData) {
              subItem[itemField] = itemDatas[0].CmsItemData.Value
              if (itemDatas[0].CmsItemData.FileList && itemDatas[0].CmsItemData.FileList.length) {
                subItem.fileMap = {
                  ...subItem.fileMap,
                  ...handleLinkFileInfo(itemDatas[0].CmsItemData.FileList),
                }
              }
            }
          }
        }
        if (subItem.productLinkInfo && subItem.productLinkInfo.length)
          subItem.productLinkPath =
            subItem.productLinkInfo[subItem.productLinkInfo.length - 1].LinkPath +
            '\\' +
            subItem.productLinkInfo[subItem.productLinkInfo.length - 1].CmsItemId
        if (subItem.linkInfo && subItem.linkInfo.length)
          subItem.linkPath = subItem.linkInfo[0].LinkPath + '\\' + subItem.linkInfo[0].CmsItemId
      }
      linkItemsMap[tag] = sdata.datas
    }
  }
  convertCmsItemBase(item, coverSize, handelEBooK)
  item.idPath = path + '\\' + item.id
  item.subItems = linkItemsMap
  return item
}
const handleLinkFileInfo = (linkList) => {
  let linkFileMap = {}
  for (let z = 0; z < linkList.length; z++) {
    const linkItem = linkList[z]
    linkFileMap[linkItem.Md5] = {
      linkType: linkItem.LinkType,
      extension: linkItem.Extension,
      fileName: linkItem.FileName,
      fileType: linkItem.Type,
      md5: linkItem.Md5,
      icon: linkItem.Icon,
      size: linkItem.Size,
      // metaData: JSON.parse(linkItem.MetaData ?? "{}"),
      order: linkItem.Order,
      protectType: linkItem.ProtectType,
    }
  }
  return linkFileMap
}
const convertCmsItemBase = (item, coverSize, handelEBooK) => {
  item.name = item.datas.Name
  item.description = item.datas.Description
  item.refCode = item.datas.RefCode
  item.state = item.datas.State
  item.type = item.datas.Type
  item.tag = item.datas.Tag
  item.typeId = parseInt(item.datas.TypeId)
  item.icon = getPublicImage(item.datas.Icon, coverSize?.width, coverSize?.height)
  item.sysType = item.datas.SysType
  item.linkFile = JSON.parse(item.datas.LinkFile ?? '[]')
  item.linkType = item.datas.LinkType
  item.linkAppId = parseInt(item.datas.LinkAppId)
  item.linkStoreId = parseInt(item.datas.LinkStore)
  item.linkRepoId = item.datas.LinkRepository
  item.childrenCount = parseInt(item.datas.ChildrenCount ?? '0')
  ;(item.childrenFolderCount = parseInt(item.datas.ChildrenFolderCount ?? '0')),
    (item.childrenChannelCount = parseInt(item.datas.ChildrenChannelCount ?? '0')),
    (item.linkId = parseInt(item.datas.LinkId))
  item.linkOrg = JSON.parse(item.datas.LinkOrg ?? '[]')[0]
  item.linkDepartment = JSON.parse(item.datas.LinkDepartment ?? '[]')[0]
  item.linkInfo = JSON.parse(item.datas.LinkInfo ?? '[]')
  item.productLinkInfo = JSON.parse(item.datas.ProductLinkInfo ?? '[]')
  item.saleMethod = JSON.parse(item.datas.SaleMethod ?? '[]')
  item.allowDonate = item.datas.AllowDonate == 'True'
  // item.donatePriceList = JSON.parse(item.datas.DonatePriceList ?? "[]");
  item.createDate = moment(item.datas.CreateDate).format('YYYY-MM-DD')
  item.beginDate = moment(item.datas.BeginDate).format('YYYY-MM-DD')
  item.endDate = moment(item.datas.EndDate).format('YYYY-MM-DD')
  item.storeEvent = JSON.parse(item.datas.StoreEvent ?? '[]')
  // 统一处理价格
  if (item.defaultSaleMethod) {
    if (handelEBooK) {
      // 获取随书资源的销售方式
      let saleMethod = item.cmsDatas[0].datas.find(
        (item) => item.refCode == 'tourism_accompanyingResources',
      ).saleMethod
      if (saleMethod && saleMethod.length > 0) {
        Object.keys(saleMethod[0]).map((key) => {
          let newKey = key.replace(key[0], key[0].toLowerCase())
          saleMethod[0][newKey] = saleMethod[0][key]
          delete saleMethod[0][key]
        })
        item.defaultSaleMethod = saleMethod[0]
        item.defaultSaleMethodId = saleMethod[0].id
        item.alreadyBuy = item.purchasedSaleMethodIdList.indexOf(item.defaultSaleMethodId) > -1
      }
    }
    if (item.defaultSaleMethod.allowEvent && item.storeEvent.length) {
      // 已参加活动,获取有效活动并计算价格
      let time = new Date().getTime()
      // 过滤过期活动
      let event = item.storeEvent.filter((item) => {
        let endTime = new Date(item.EndDate).getTime()
        return endTime > time
      })
      // 只处理一条有效活动
      if (event.length) {
        item.price = (item.defaultSaleMethod.price * event[0].Value).toFixed(2)
        item.oldPrice = item.defaultSaleMethod.price
        if (
          moment().format('YYYY-MM-DD') <
          moment(item.defaultSaleMethod.endDate).format('YYYY-MM-DD')
        ) {
          item.defaultSaleMethodState = 'Normal'
        } else {
          item.defaultSaleMethodState = 'Beyond'
        }
        item.storeEventId = event[0].Id
      }
    } else {
      item.price = item.defaultSaleMethod.price
      item.oldPrice = item.defaultSaleMethod.virtualPrice
      if (
        moment().format('YYYY-MM-DD') < moment(item.defaultSaleMethod.endDate).format('YYYY-MM-DD')
      ) {
        item.defaultSaleMethodState = 'Normal'
      } else {
        item.defaultSaleMethodState = 'Beyond'
      }
    }
  }
}
export function getTopicMsgCmsItemFile(fileType, fileList) {
  let obj = {}
  fileType.forEach((item) => {
    item.sequenceNum = item.config ? JSON.parse(item.config).uuid : ''
    fileList.forEach((e) => {
      if (item.sequenceNum == e.sequenceNum) {
        try {
          if (e.fileLinkList.length > 0) {
            for (let i = 0; i < e.fileLinkList.length; i++) {
              const ele = e.fileLinkList[i]
              ele.name = ele.file.fileName
              ele.md5 = ele.file.md5
              ele.status = 'success'
            }
            obj[item.typeField.refCode] = e.fileLinkList
          } else {
            const val = JSON.parse(e.value)
            obj[item.typeField.refCode] = val
          }
        } catch (error) {
          obj[item.typeField.refCode] = e.value
        }
      }
    })
  })
  return obj
}
// 获取不受保护的图片
export function getPublicImage(md5, width, height, storeInfo) {
  let src = null
  if (md5) {
    src = requestCtx + `/file/GetPreViewImage?md5=${md5}`
  } else {
    if (storeInfo == 'jsek_bookFair') {
      // return defaultBookFair;
      return
    } else if (storeInfo == `defaultGoodsStore${appId}`) {
      return bookCover
    } else if (storeInfo == `defaultPublicStore${appId}`) {
      return bookCover
    } else {
      return ''
    }
  }
  if (width) src += `&width=${width}`
  if (height) src += `&height=${height}`
  return src
}
src/assets/js/toolClass.js
New file
@@ -0,0 +1,465 @@
import SparkMD5 from 'spark-md5'
import { getPublicImage } from '@/assets/js/middleGround/tool.js'
// import moment from "moment";
var tool = {
  secondToTime(second) {
    var minute = Math.floor(second / 60)
    var sec = second % 60
    var time
    if (second < 60) {
      time = second + '"'
    } else {
      time = sec === 0 ? minute + "'" : minute + "'" + sec + '"'
    }
    return time
  },
  setCookie: function (c_name, value, expiredays, path) {
    var exdate = new Date()
    exdate.setDate(exdate.getDate() + expiredays)
    document.cookie =
      c_name +
      '=' +
      escape(value) +
      (expiredays == null ? '' : ';expires=' + exdate.toGMTString()) +
      (path ? ';path=' + path : '')
  },
  getCookie: function (c_name) {
    if (document.cookie.length > 0) {
      var c_start = document.cookie.indexOf(c_name + '=')
      if (c_start != -1) {
        c_start = c_start + c_name.length + 1
        var c_end = document.cookie.indexOf(';', c_start)
        if (c_end == -1) c_end = document.cookie.length
        return unescape(document.cookie.substring(c_start, c_end))
      }
    }
    return ''
  },
  delCookie: function (name) {
    var exp = new Date()
    exp.setTime(exp.getTime() - 1)
    var cval = tool.getCookie(name)
    if (cval != null) document.cookie = name + '=' + cval + ';expires=' + exp.toGMTString()
  },
  // 强制保留2位小数,如:2,会在2后面补上00.即2.00
  toDecimal2(x) {
    var f
    f = parseFloat(x)
    if (isNaN(f)) {
      return false
    }
    f = Math.round(x * 100) / 100
    var s = f.toString()
    var rs = s.indexOf('.')
    if (rs < 0) {
      rs = s.length
      s += '.'
    }
    while (s.length <= rs + 2) {
      s += '0'
    }
    return s
  },
  formateTime(date) {
    var newDate = new Date(+new Date(date) + 8 * 3600 * 1000)
      .toISOString()
      .replace(/T/g, ' ')
      .replace(/\.[\d]{3}Z/, '')
    var time = new Date(newDate)
    return time.getTime()
  }
}
// 处理订单记录
// export function setOrderList(res) {
//   // 获取当前年份的开始时间
//   let currentTimestamp = moment().startOf("year");
//   let arr = [];
//   for (let i = 0; i < res.length; i++) {
//     const item = res[i];
//     // 发票状态为审核中或者审核失败,将item选中状态设置选中。
//     // UI控制禁用(显示的效果为 选中并且禁用)
//     if (item.invoiceInfo) {
//       item.checked = true;
//     } else {
//       item.checked = false;
//     }
//     // 判断是否超出申请发票的日期
//     item.exceedingTheSpecifiedTime = moment(item.createDate).isBefore(
//       currentTimestamp
//     );
//     if (item.saleMethodLinks.length > 0) {
//       let itemName = null;
//       let itemIcon = null;
//       let cmsItemList = null;
//       try {
//         cmsItemList = item.saleMethodLinks[0].orderSaleMethod.cmsItemList[0];
//       } catch (error) {
//         cmsItemList = null;
//       }
//       if (cmsItemList && cmsItemList.icon) {
//         itemName = cmsItemList.name;
//         itemIcon = cmsItemList.icon;
//       } else {
//         itemName = item.saleMethodLinks[0].orderSaleMethod.product.name;
//         itemIcon = item.saleMethodLinks[0].orderSaleMethod.product.icon;
//       }
//       item.saleMethodLinks[0].title = itemName;
//       item.saleMethodLinks[0].icon = getPublicImage(itemIcon);
//     } else {
//       const itemIcon = require("@/assets/images/bookCity/place_img.png");
//       const saleMethodLink = [];
//       const obj = {
//         icon: itemIcon,
//         orderSaleMethod: {
//           price: item.payPrice,
//         },
//       };
//       saleMethodLink.push(obj);
//       item.saleMethodLinks = saleMethodLink;
//     }
//     if (item.state == "Success") {
//       item.CustomState = "支付成功";
//     }
//     if (item.state == "Cancel") {
//       item.CustomState = "取消支付";
//     }
//     if (item.state == "WaitPay") {
//       item.CustomState = "等待支付";
//     }
//     if (item.state == "WaitDeliver") {
//       item.CustomState = "正在支付";
//     }
//     arr.push(item);
//   }
//   return arr;
// }
//处理表单提交数据
export function worksData(res) {
  let arr = []
  for (let i = 0; i < res.length; i++) {
    const item = res[i]
    if (item.typeField) {
      if (item.typeField.config) {
        item.typeField.options = JSON.parse(item.typeField.config).option
      }
      arr.push(item.typeField)
    }
  }
  return arr
}
export function worksDataBytool(res, value, linkList) {
  let arr = []
  let nrr = []
  if (linkList && linkList.length > 0) {
    linkList.forEach((e) =>
      nrr.push({
        linkProtectType: e.linkProtectType,
        linkType: e.linkType,
        md5: e.md5
      })
    )
  }
  res.forEach((item) => {
    const obj = {
      baseType: item.typeField.baseType,
      order: 0,
      typeFieldId: item.typeField.id,
      sequenceNum: item.config ? JSON.parse(item.config).uuid : '',
      newDataAndFileLinkListRequest: []
    }
    for (let k in value) {
      if (item.typeField.refCode === k) {
        if (item.typeField.type == 'File') {
          try {
            obj.strValue = JSON.stringify(value[k].map((citem) => citem.md5))
          } catch (error) {
            obj.strValue = ''
          }
          obj.newDataAndFileLinkListRequest = nrr
        } else {
          if (typeof value[k] == 'object') {
            obj.strValue = JSON.stringify(value[k])
          } else {
            if (obj.baseType === 'String') {
              obj.strValue = value[k] + ''
            } else if (obj.baseType === 'Text') {
              obj.textValue = value[k] + ''
            } else {
              obj.strValue = value[k] + ''
            }
          }
        }
      }
    }
    // if (obj.strValue || obj.textValue) {
    arr.push(obj)
    // }
  })
  return arr
}
export function UpdateworksDataBytool(initData, res, value, linkList) {
  let arr = [];
  let newArr = [];
  for (let i = 0; i < initData.length; i++) {
    const ele = initData[i];
    for (let j = 0; j < res.length; j++) {
      const item = res[j];
      if (item.sequenceNum == ele.sequenceNum) {
        item.refCode = ele.typeField.refCode;
      }
    }
  }
  initData.forEach((citem) => {
    const updateOldData = res.find((f) => f.sequenceNum == citem.sequenceNum);
    if (updateOldData) {
      const obj = {
        baseType: citem.typeField.baseType,
        order: 0,
        id: updateOldData.id,
        typeFieldId: citem.typeField.id,
        sequenceNum: citem.sequenceNum,
        setDataAndFileLinkListRequest: [],
      };
      for (let k in value) {
        if (citem.typeField.refCode === k) {
          if (typeof value[k] == "object" && k != "region") {
            obj.strValue = JSON.stringify(linkList);
            obj.setDataAndFileLinkListRequest = linkList;
          } else if (typeof value[k] == "object" && k == "region") {
            obj.strValue = value[k]?.join("/");
            obj.setDataAndFileLinkListRequest = [{ area: value[k] }];
          } else {
            obj.strValue = value[k].toString();
          }
        }
      }
      if (obj.strValue) {
        arr.push(obj);
      }
    } else {
      const newObj = {
        baseType: citem.typeField.baseType,
        order: 0,
        typeFieldId: citem.typeField.id,
        sequenceNum: citem.sequenceNum,
        setDataAndFileLinkListRequest: [],
      };
      for (let k in value) {
        if (citem.typeField.refCode === k) {
          if (typeof value[k] == "object") {
            newObj.strValue = JSON.stringify(linkList);
            newObj.setDataAndFileLinkListRequest = linkList;
          } else {
            newObj.strValue = value[k].toString();
          }
        }
      }
      if (newObj.strValue) {
        newArr.push(newObj);
      }
    }
  });
  return {
    updateData: arr,
    newData: newArr,
  };
}
export function download(url) {
  const iframe = document.createElement('iframe')
  iframe.setAttribute('hidden', 'hidden')
  document.body.appendChild(iframe)
  iframe.onload = () => {
    if (iframe) {
      iframe.setAttribute('src', 'about:blank')
    }
  }
  iframe.setAttribute('src', url)
}
/**
 * 获取一个UUID
 * @param len
 * @param radix
 * @returns {string}
 */
export function uuid(len = 32, radix = 16) {
  const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
  let uuid = [],
    i
  radix = radix || chars.length
  if (len) {
    // Compact form
    for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)]
  } else {
    // rfc4122, version 4 form
    let r
    // rfc4122 requires these characters
    uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
    uuid[14] = '4'
    // Fill in random data.  At i==19 set the high bits of clock sequence as
    // per rfc4122, sec. 4.1.5
    for (i = 0; i < 36; i++) {
      if (!uuid[i]) {
        r = 0 | (Math.random() * 16)
        uuid[i] = chars[i === 19 ? (r & 0x3) | 0x8 : r]
      }
    }
  }
  return uuid.join('')
}
export function getFileMd5(file, chunkSize) {
  return new Promise((resolve, reject) => {
    let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
    let chunks = Math.ceil(file.size / chunkSize)
    let currentChunk = 0
    let spark = new SparkMD5.ArrayBuffer()
    let fileReader = new FileReader()
    fileReader.onload = function (e) {
      spark.append(e.target.result)
      currentChunk++
      if (currentChunk < chunks) {
        loadNext()
      } else {
        const md5 = spark.end()
        resolve(md5)
      }
    }
    fileReader.onerror = function (e) {
      reject(e)
    }
    function loadNext() {
      let start = currentChunk * chunkSize
      let end = start + chunkSize
      if (end > file.size) {
        end = file.size
      }
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
    }
    loadNext()
  })
}
// 处理时间,用于显示音视频当前时间
// export function realFormatSecond(time) {
//   let duration = parseInt(time);
//   let minute = parseInt(duration / 60);
//   let sec = (duration % 60) + "";
//   let isM0 = ":";
//   if (minute == 0) {
//     minute = "00";
//   } else if (minute < 10) {
//     minute = "0" + minute;
//   }
//   if (sec.length == 1) {
//     sec = "0" + sec;
//   }
//   return minute + isM0 + sec;
// }
// export function parseHtml(content) {
//   const tagReg =
//     /<\/?div[^>]*>|<\/?span[^>]*>|<\/?table[^>]*>|<\/?th[^>]*>|<\/?thead>|<\/?tbody>|<\/?tr>|<\/?td[^>]*>|<br[^>]*>|<\/?p[^>]*>|<\/?sub>|<\/?sup>|<\/?font[^>]*>|<img[^>]*>|<\/?a[^>]*>|\n|\\n/gi;
//   const escapeReg =
//     /&(lt|gt|le|ge|nbsp|amp|quot|times|Alpha|Beta|Gamma|Delta|Epsilon|Zeta|Eta|Theta|Iota|Kappa|Lambda|MU|NU|Xi|Omicron|Pi|Rho|Sigma|Tau|Upsilon|Phi|Chi|Psi|Omega|alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigmaf|sigma|tau|upsilon|phi|chi|psi|omega|thetasym|upsih|piv|circ|tilde|ndash|permil|lsquo|rsquo|ldquo|rdquo|prime);/gi;
//   const escapeElements = {
//     lt: "<",
//     gt: ">",
//     le: "≤",
//     ge: "≥",
//     nbsp: " ",
//     amp: "&",
//     quot: '""',
//     times: "×",
//     Alpha: "Α",
//     Beta: "Β",
//     Gamma: "Γ",
//     Delta: "Δ",
//     Epsilon: "Ε",
//     Zeta: "Ζ",
//     Eta: "Η",
//     Theta: "Θ",
//     Iota: "Ι",
//     Kappa: "Κ",
//     Lambda: "Λ",
//     Mu: "Μ",
//     Nu: "Ν",
//     Xi: "Ξ",
//     Omicron: "Ο",
//     Pi: "Π",
//     Rho: "Ρ",
//     Sigma: "Σ",
//     Tau: "Τ",
//     Upsilon: "Υ",
//     Phi: "Φ",
//     Chi: "Χ",
//     Psi: "Ψ",
//     Omega: "Ω",
//     alpha: "α",
//     beta: "β",
//     gamma: "γ",
//     delta: "δ",
//     epsilon: "ε",
//     zeta: "ζ",
//     eta: "η",
//     theta: "θ",
//     iota: "ι",
//     kappa: "κ",
//     lambda: "λ",
//     mu: "μ",
//     nu: "ν",
//     xi: "ξ",
//     omicron: "ο",
//     pi: "π",
//     rho: "ρ",
//     sigmaf: "ς",
//     sigma: "σ",
//     tau: "τ",
//     upsilon: "υ",
//     phi: "φ",
//     chi: "χ",
//     psi: "ψ",
//     omega: "ω",
//     thetasym: "ϑ",
//     upsih: "ϒ",
//     piv: "ϖ",
//     circ: "ˆ",
//     tilde: "˜",
//     ndash: "–",
//     permil: "‰",
//     lsquo: "‘",
//     rsquo: "’",
//     ldquo: "“",
//     rdquo: "”",
//     prime: "′",
//   };
//   const contentWithoutTag = content.replace(tagReg, "");
//   const contentWithOnlyOneSpace = contentWithoutTag.replace(/ {2,}/g, " ");
//   return contentWithOnlyOneSpace.replace(
//     escapeReg,
//     (all, t) => escapeElements[t]
//   );
// }
export default {
  ...tool,
  uuid,
  getFileMd5,
  worksDataBytool,
  UpdateworksDataBytool,
  getPublicImage,
  worksData
  // parseHtml,
}
src/assets/js/userAction.js
New file
@@ -0,0 +1,135 @@
import config from "@/assets/js/config";
import jobApi from "./middleGround/api/job"; // newJobWithNewView // newSession,
export function setSessionGuid(type, id) {
  var cityCode = null;
  var SnIp = null;
  try {
    // eslint-disable-next-line
    SnIp = window.returnCitySN;
  } catch (error) {
    SnIp = null;
    console.log(error);
  }
  if (SnIp != undefined && SnIp != null) {
    cityCode = SnIp;
  } else {
    cityCode = {
      cip: "0.0.0.0",
      cname: "未知",
    };
  }
  const _city = cityCode.cname.substring(3);
  const _province = cityCode.cname.substring(0, 3);
  const params = {
    appRefCode: config.appRefCode,
    hostName: config.requestCtx,
    ipAddress: cityCode.cip,
    browser: myBrowser(),
    os: navigator.platform,
    device: "pc",
    province: _province,
    city: _city ? _city : _province,
  };
  jobApi.newSession(params).then(res => {
    storage.set("sessionGuid", res, 30);
    setNewView(type, id);
  });
}
export const storage = {
  /*
   * set 存储方法
   * @ param {String}     key 键
   * @ param {String}     value 值,
   * @ param {String}     expired 过期时间,以分钟为单位,非必须
   */
  set(key, val, expired) {
    if (typeof val !== "string") {
      val = JSON.stringify(val);
    }
    window.sessionStorage.setItem(key, val);
    if (expired) {
      window.sessionStorage.setItem(
        `${key}__expires__`,
        `${Date.now() + 1000 * 60 * expired}`
      );
    }
  },
  /*
   * get 获取方法
   * @ param {String}     key 键
   * @ param {String}     expired 存储时为非必须字段,所以有可能取不到,默认为 Date.now+1
   */
  get(key) {
    const expired =
      window.sessionStorage.getItem(`${key}__expires__`) || Date.now + 1;
    const now = Date.now();
    if (now >= expired) {
      window.sessionStorage.removeItem(key);
      return;
    }
    let val = window.sessionStorage.getItem(key);
    try {
      val = JSON.parse(val);
    } catch (e) {
      return e;
    }
    return val;
  },
};
function myBrowser() {
  const userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
  const isOpera = userAgent.indexOf("Opera") > -1;
  if (isOpera) {
    //判断是否Opera浏览器
    return "Opera";
  }
  if (userAgent.indexOf("Firefox") > -1) {
    //判断是否Firefox浏览器
    return "Firefox";
  }
  if (userAgent.indexOf("Chrome") > -1) {
    return "Chrome";
  }
  if (userAgent.indexOf("Safari") > -1) {
    //判断是否Safari浏览器
    return "Safari";
  }
  if (
    userAgent.indexOf("compatible") > -1 &&
    userAgent.indexOf("MSIE") > -1 &&
    !isOpera
  ) {
    //判断是否IE浏览器
    return "IE";
  }
  return "";
}
export function setNewView(type, id) {
  if (!sessionStorage.getItem("sessionGuid")) {
    setSessionGuid(type, id);
  }
  const sessionGuid = sessionStorage.getItem("sessionGuid");
  const fromPath = sessionStorage.getItem("fromPath");
  const toPath = sessionStorage.getItem("toPath");
  if (sessionGuid) {
    let params = {
      sessionGuid: sessionGuid,
      appRefCode: config.appRefCode,
      type: "View",
      url: toPath == null ? "/" : toPath,
      ref: fromPath == null ? "/" : fromPath,
    };
    if (id) {
      params[type] = id;
    }
    jobApi.newJobWithNewView(params).then(res => {});
  }
}
src/assets/logo.svg
New file
@@ -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>
src/assets/style/base.css
New file
@@ -0,0 +1,279 @@
/* color palette from <https://github.com/vuejs/theme> */
:root {
  --vt-c-white: #ffffff;
  --vt-c-white-soft: #f8f8f8;
  --vt-c-white-mute: #f2f2f2;
  --vt-c-black: #181818;
  --vt-c-black-soft: #222222;
  --vt-c-black-mute: #282828;
  --vt-c-indigo: #2c3e50;
  --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
  --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
  --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
  --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
  --vt-c-text-light-1: var(--vt-c-indigo);
  --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
  --vt-c-text-dark-1: var(--vt-c-white);
  --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
  --color-background: var(--vt-c-white);
  --color-background-soft: var(--vt-c-white-soft);
  --color-background-mute: var(--vt-c-white-mute);
  --color-border: var(--vt-c-divider-light-2);
  --color-border-hover: var(--vt-c-divider-light-1);
  --color-heading: var(--vt-c-text-light-1);
  --color-text: var(--vt-c-text-light-1);
  --section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
  :root {
    --color-background: var(--vt-c-black);
    --color-background-soft: var(--vt-c-black-soft);
    --color-background-mute: var(--vt-c-black-mute);
    --color-border: var(--vt-c-divider-dark-2);
    --color-border-hover: var(--vt-c-divider-dark-1);
    --color-heading: var(--vt-c-text-dark-1);
    --color-text: var(--vt-c-text-dark-2);
  }
}
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  font-weight: normal;
}
html {
  width: 100%;
  height: 100%;
}
body {
  width: 100%;
  height: 100%;
  min-height: 100vh;
  color: var(--color-text);
  background: var(--color-background);
  transition:
    color 0.5s,
    background-color 0.5s;
  font-family:
    Inter,
    -apple-system,
    BlinkMacSystemFont,
    'Segoe UI',
    Roboto,
    Oxygen,
    Ubuntu,
    Cantarell,
    'Fira Sans',
    'Droid Sans',
    'Helvetica Neue',
    sans-serif;
  font-size: 14px;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
body {
  width: 100%;
  height: 100%;
  min-height: 100vh;
  color: var(--color-text);
  background: var(--color-background);
  transition:
    color 0.5s,
    background-color 0.5s;
  font-family:
    Inter,
    -apple-system,
    BlinkMacSystemFont,
    'Segoe UI',
    Roboto,
    Oxygen,
    Ubuntu,
    Cantarell,
    'Fira Sans',
    'Droid Sans',
    'Helvetica Neue',
    sans-serif;
  font-size: 14px;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
/* em, */
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  /* vertical-align: baseline; */
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
  display: block;
}
body {
  line-height: 1;
  margin: 0 !important;
}
ol,
ul {
  list-style: none;
}
blockquote,
q {
  quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
  content: '';
  content: none;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}
::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
::-webkit-scrollbar-track-piece {
  background-color: rgba(0, 0, 0, 0.2);
  -webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:vertical {
  height: 5px;
  background-color: rgba(125, 125, 125, 0.7);
  -webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:horizontal {
  width: 5px;
  background-color: rgba(125, 125, 125, 0.7);
  -webkit-border-radius: 6px;
}
body {
  -webkit-text-size-adjust: none;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
src/assets/style/main.css
New file
@@ -0,0 +1,89 @@
@import './base.css';
/* @font-face {
  font-family: 'Source Han Serif';
  src: url('../fonts/Source_Han.otf') format('truetype');
} */
#app {
  width: 100%;
  height: 100%;
}
body {
  font-size: 14px;
  font-family: 'Source Han Serif';
}
page {
  display: block;
  width: 100%;
  height: 100%;
}
/* 用于居中内容显示 */
.contentBox {
  box-sizing: border-box;
}
.hover {
  cursor: pointer;
  transition: all 0.2s;
}
.move {
  font-size: 16px;
  font-family:
    Microsoft YaHei,
    Microsoft YaHei-Regular;
  font-weight: 400;
  text-align: left;
  color: #ff6d00 !important;
  line-height: 38px;
}
/* 垂直居中 */
.ai-c {
  align-items: center;
}
/* 两边对齐 */
.jc-sb {
  justify-content: space-between;
}
.clear:after,
.clear:before {
  content: '';
  display: block;
  clear: both;
}
.flex {
  display: flex;
}
.flex1 {
  flex: 1;
}
.fl {
  float: left;
}
.fr {
  float: right;
}
.hide-txt {
  line-height: 16px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media screen and (max-width: 1200px) {
  .rightList {
    right: 0 !important;
  }
}
src/assets/style/variable.less
New file
@@ -0,0 +1,4 @@
@primary-color: black;
@active-txt-color: #BB5B5C;
@default-banner-txt-color: #9E9E9E;
@black_txt_color: #2C2C2C;
src/components/HelloWorld.vue
New file
@@ -0,0 +1,41 @@
<script setup lang="ts">
defineProps<{
  msg: string
}>()
</script>
<template>
  <div class="greetings">
    <h1 class="green">{{ msg }}</h1>
    <h3>
      You’ve successfully created a project with
      <a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
      <a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>. What's next?
    </h3>
  </div>
</template>
<style scoped>
h1 {
  font-weight: 500;
  font-size: 2.6rem;
  position: relative;
  top: -10px;
}
h3 {
  font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
  text-align: center;
}
@media (min-width: 1024px) {
  .greetings h1,
  .greetings h3 {
    text-align: left;
  }
}
</style>
src/components/TheWelcome.vue
New file
@@ -0,0 +1,94 @@
<script setup lang="ts">
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
</script>
<template>
  <WelcomeItem>
    <template #icon>
      <DocumentationIcon />
    </template>
    <template #heading>Documentation</template>
    Vue’s
    <a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
    provides you with all information you need to get started.
  </WelcomeItem>
  <WelcomeItem>
    <template #icon>
      <ToolingIcon />
    </template>
    <template #heading>Tooling</template>
    This project is served and bundled with
    <a href="https://vite.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
    recommended IDE setup is
    <a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a>
    +
    <a href="https://github.com/vuejs/language-tools" target="_blank" rel="noopener">Vue - Official</a>. If
    you need to test your components and web pages, check out
    <a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a>
    and
    <a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a>
    /
    <a href="https://playwright.dev/" target="_blank" rel="noopener">Playwright</a>.
    <br />
    More instructions are available in
    <a href="javascript:void(0)" @click="openReadmeInEditor"><code>README.md</code></a
    >.
  </WelcomeItem>
  <WelcomeItem>
    <template #icon>
      <EcosystemIcon />
    </template>
    <template #heading>Ecosystem</template>
    Get official tools and libraries for your project:
    <a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
    <a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
    <a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
    <a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
    you need more resources, we suggest paying
    <a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
    a visit.
  </WelcomeItem>
  <WelcomeItem>
    <template #icon>
      <CommunityIcon />
    </template>
    <template #heading>Community</template>
    Got stuck? Ask your question on
    <a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>
    (our official Discord server), or
    <a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
      >StackOverflow</a
    >. You should also follow the official
    <a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener">@vuejs.org</a>
    Bluesky account or the
    <a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
    X account for latest news in the Vue world.
  </WelcomeItem>
  <WelcomeItem>
    <template #icon>
      <SupportIcon />
    </template>
    <template #heading>Support Vue</template>
    As an independent project, Vue relies on community backing for its sustainability. You can help
    us by
    <a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
  </WelcomeItem>
</template>
src/components/WelcomeItem.vue
New file
@@ -0,0 +1,87 @@
<template>
  <div class="item">
    <i>
      <slot name="icon"></slot>
    </i>
    <div class="details">
      <h3>
        <slot name="heading"></slot>
      </h3>
      <slot></slot>
    </div>
  </div>
</template>
<style scoped>
.item {
  margin-top: 2rem;
  display: flex;
  position: relative;
}
.details {
  flex: 1;
  margin-left: 1rem;
}
i {
  display: flex;
  place-items: center;
  place-content: center;
  width: 32px;
  height: 32px;
  color: var(--color-text);
}
h3 {
  font-size: 1.2rem;
  font-weight: 500;
  margin-bottom: 0.4rem;
  color: var(--color-heading);
}
@media (min-width: 1024px) {
  .item {
    margin-top: 0;
    padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
  }
  i {
    top: calc(50% - 25px);
    left: -26px;
    position: absolute;
    border: 1px solid var(--color-border);
    background: var(--color-background);
    border-radius: 8px;
    width: 50px;
    height: 50px;
  }
  .item:before {
    content: ' ';
    border-left: 1px solid var(--color-border);
    position: absolute;
    left: 0;
    bottom: calc(50% + 25px);
    height: calc(50% - 25px);
  }
  .item:after {
    content: ' ';
    border-left: 1px solid var(--color-border);
    position: absolute;
    left: 0;
    top: calc(50% + 25px);
    height: calc(50% - 25px);
  }
  .item:first-of-type:before {
    display: none;
  }
  .item:last-of-type:after {
    display: none;
  }
}
</style>
src/components/icons/IconCommunity.vue
New file
@@ -0,0 +1,7 @@
<template>
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
    <path
      d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
    />
  </svg>
</template>
src/components/icons/IconDocumentation.vue
New file
@@ -0,0 +1,7 @@
<template>
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
    <path
      d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
    />
  </svg>
</template>
src/components/icons/IconEcosystem.vue
New file
@@ -0,0 +1,7 @@
<template>
  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
    <path
      d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
    />
  </svg>
</template>
src/components/icons/IconSupport.vue
New file
@@ -0,0 +1,7 @@
<template>
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
    <path
      d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
    />
  </svg>
</template>
src/components/icons/IconTooling.vue
New file
@@ -0,0 +1,19 @@
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
<template>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    aria-hidden="true"
    role="img"
    class="iconify iconify--mdi"
    width="24"
    height="24"
    preserveAspectRatio="xMidYMid meet"
    viewBox="0 0 24 24"
  >
    <path
      d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
      fill="currentColor"
    ></path>
  </svg>
</template>
src/layout/components/crumbPage.vue
New file
@@ -0,0 +1,130 @@
<template>
  <div class="crumbs">
    <div class="breadcrumbBox" v-if="crumbsData.length > 0">
      <p style="float: left">位置:</p>
      <div :class="!item.path && !item.pathName
          ? 'breadcrumbItem'
          : index == crumbsData.length - 1
            ? 'breadcrumbItem'
            : 'breadcrumbItem isLink'
        " v-for="(item, index) in crumbsData" :key="index" @click="toPage(item, index)">
        <span :title="item.name">{{ item.name }}</span>
        <el-icon class="breadcrumbIcon" v-if="index < crumbsData.length - 1">
          <ArrowRight />
        </el-icon>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { useBreadcrumbStore } from '@/store'
import { useRouter } from 'vue-router'
const props = defineProps<{ type: string; crumbsKey: string }>()
const router = useRouter()
const crumbStore = useBreadcrumbStore()
const crumbsData = ref()
watch(
  [() => props.crumbsKey, () => props.type],
  (newValue, oldValue) => {
    crumbsData.value = crumbStore.crumbList[props.type][props.crumbsKey]
  },
  { immediate: true, deep: true }
)
const toPage = (data: any, index: any) => {
  if (index < crumbsData.value.length - 1 && (data.path || data.pathName)) {
    // 判断是否需要记录面包屑
    if (data.isCrumbs) {
      let saveData = crumbsData.value.filter(
        (cItem: any, cIndex: any) => cIndex != 0 && cIndex <= index
      )
      crumbStore.setCrumbs({
        type: data.type,
        data: saveData,
        callback: (key: any) => {
          let query = { ...data.query, crumbsKey: key }
          if (data.pathName) {
            router.push({
              name: data.pathName,
              query: query
            })
          }
          if (data.path) {
            router.push({
              path: data.path,
              query: query
            })
          }
        }
      })
    } else {
      router.push({
        name: data.pathName,
        path: data.path,
        query: data.query
      })
    }
  }
  return false
}
</script>
<style lang="less" scoped>
.crumbs {
  width: 100%;
  // padding: 6px 0;
  .breadcrumbBox {
    font-size: 14px;
    overflow: hidden;
    height: 60px;
    display: flex;
    align-items: center;
    p {
      height: 20px;
      line-height: 20px;
    }
    .breadcrumbItem {
      max-width: 200px;
      display: flex;
      align-items: center;
      height: 20px;
      line-height: 20px;
      float: left;
      color: #545c63;
      &.isLink {
        text-decoration: none;
        transition: color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
        color: #303133;
        &:hover {
          color: #ff6c00;
          cursor: pointer;
        }
      }
      .breadcrumbIcon {
        margin: 0 6px;
        font-weight: 400;
        color: #545c63;
      }
      span {
        width: 100%;
        overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      }
    }
  }
  img {
    width: 100%;
    height: 5px;
  }
}
</style>
src/layout/components/footerPage.vue
New file
@@ -0,0 +1,117 @@
<template>
  <div class="footerBox">
    <div class="footerBox-main">
      <ul class="main-left">
        <li class="footer-title">{{ t('message.About') }}</li>
        <li>{{ t('message.webPolicies') }}</li>
        <li>{{ t('message.Help') }}</li>
      </ul>
      <ul class="main-center">
        <li class="footer-title">{{ t('message.FriendlyLinks') }}</li>
        <li>
          {{ t('message.ChinaAcademyofChineseMedicalSciences') }}
        </li>
        <li>
          {{ t('message.NationalGenomicsDataCenter') }}
        </li>
      </ul>
      <ul class="main-center">
        <li class="footer-title"><br></li>
        <li>
          {{ t('message.NationalAdministrationofTraditionalChineseMedicine') }}
        </li>
        <li>
          {{ t('message.GraduateSchoolofChinaAcademyofChineseMedicalSciences') }}
        </li>
      </ul>
      <div class="main-right">
        <img src="../../assets/images/layout/footImg-left.png" alt="">
        <img src="../../assets/images/layout/footImg-right.png" alt=""></img>
      </div>
    </div>
    <div class="footerBox-footer">
      <p>{{ t('message.COPYRIGHT2021ChinaAcademyofChineseMedical') }}</p>
    </div>
  </div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
const { locale, t } = useI18n();
</script>
<style lang="less" scoped>
.footerBox {
  width: 100%;
  height: 190px;
  min-width: 1200px;
  color: #fff;
  background-color: #f0f0f0;
  background-color: #01644C;
}
.footerBox-main {
  height: 142px;
  width: 60%;
  margin: 0 auto;
  padding: 20px 0;
  display: flex;
}
.main-left {
  margin-right: 8%;
  li {
    text-wrap: nowrap;
    margin-bottom: 10px;
  }
}
.footer-title {
  font-weight: bold;
}
.main-center {
  li {
    text-wrap: nowrap;
    margin-bottom: 10px;
    margin-right: 10px;
    cursor: pointer;
  }
}
.main-list {
  display: flex;
  li {
    text-wrap: nowrap;
  }
}
.main-right {
  display: flex;
  img {
    margin: 0 10px;
  }
}
.footerBox-footer {
  height: 48px;
  background-color: #015742;
  p {
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
  }
}
</style>
src/layout/components/headerPage.vue
New file
@@ -0,0 +1,127 @@
<template>
  <div class="pageHeader">
    <div class="header-box">
      <ul class="page-title">
        <img class="zylogo" src="../../assets/images/home/zylogo.png" alt="">
        <li class="separator"></li>
        <img class="sylogo" src="../../assets/images/home/sylogo.svg" alt="">
        <li class="title-text">{{ t('message.logoTitle') }}</li>
      </ul>
      <div class="page-select">
        <el-select v-model="currentLocale" placeholder="Language" style="width: 120px">
          <el-option v-for="item in availableLocales" :key="item.value" :label="t(item.label)" :value="item.value" />
        </el-select>
      </div>
    </div>
  </div>
  <!-- 导航栏 -->
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
import { inject, reactive, computed } from 'vue'
const config: any = inject('config')
const router = useRouter()
import { useI18n } from 'vue-i18n';
const { locale, t } = useI18n();
const availableLocales = [
  { value: 'zh', label: 'langSelector.chinese' },
  { value: 'en', label: 'langSelector.english' },
];
const currentLocale = computed({
  get: () => locale.value,
  set: (value) => {
    locale.value = value;
    // (可选) 将语言偏好保存到 localStorage,以便下次记住用户选择
    localStorage.setItem('user-locale', value);
  },
});
</script>
<style lang="less" scoped>
.pageHeader {
  display: flex;
  justify-content: center;
  width: 100%;
  background-color: #ecf9f6;
}
.header-box {
  width: 65%;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.page-title {
  display: flex;
  align-items: center;
  justify-content: center;
}
.zylogo {
  width: 21%;
}
.separator {
  list-style: none;
  width: 20px;
  height: 20px;
  margin-right: 15px;
  position: relative;
}
/* 2. 创建第一个伪元素('\' 斜杠) */
.separator::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  /* 和容器一样宽 */
  height: 1px;
  /* 线条粗细 */
  border-top: 1px dashed #ccc;
  /* 虚线样式 */
  transform: translateY(-50%) rotate(45deg);
  /* 先垂直居中,再旋转45度 */
}
/* 3. 创建第二个伪元素('/' 斜杠) */
.separator::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  /* 和容器一样宽 */
  height: 1px;
  /* 线条粗细 */
  border-top: 1px dashed #ccc;
  /* 虚线样式 */
  transform: translateY(-50%) rotate(-45deg);
  /* 先垂直居中,再反向旋转45度 */
}
.sylogo {
  padding-right: 18px;
  border-right: 1px solid #0c73b8;
  width: 21%;
}
.title-text {
  padding-left: 14px;
  font-weight: bold;
  font-size: 20px;
}
</style>
src/layout/components/navPage.vue
New file
@@ -0,0 +1,87 @@
<template>
  <div class="navPage">
    <div class="navBox">
        <ul class="navList flex ai-c jc-sb">
          <li v-for="item in navList" :key="item.path"
            :class="{ active: route.query.type ? `/${route.query.type}` == item.path : route.path.indexOf(item.path) > -1 }"
            @click="goPage(item.path)">
            <img :src="route.path.indexOf(item.path) ? item.activeIcon : item.defaultIcon">
            <span>{{ item.name }}</span>
          </li>
        </ul>
    </div>
  </div>
</template>
<script lang="ts" setup>
import contrast from '@/assets/images/header/contrast_icon.svg'
import activeContrast from '@/assets/images/header/active_contrast_icon.svg'
import annotate from '@/assets/images/header/annotate_icon.svg'
import activeAnnotate from '@/assets/images/header/active_annotate_icon.svg'
import us from '@/assets/images/header/us_icon.svg'
import activeUs from '@/assets/images/header/active_us_icon.svg'
import { useRoute, useRouter } from 'vue-router'
import { ref, inject} from 'vue'
const router = useRouter()
const route = useRoute()
const config:any = inject('config')
const navList = ref([
  {
    name: '对读模式',
    path: config.pathData.comparison,
    defaultIcon:contrast,
    activeIcon:activeContrast
  },
  {
    name: '注释模式',
    path: config.pathData.annotation,
    defaultIcon:annotate,
    activeIcon:activeAnnotate
  },
  {
    name: '关于我们',
    path:  config.pathData.about,
    defaultIcon:us,
    activeIcon:activeUs
  },
])
const goPage = (path: string) => {
  router.push(path)
}
</script>
<style lang="less" scoped>
.navPage{
  height: 76px;
  .navBox {
    width: 600px;
    height: 100%;
    margin: 0 auto;
    .navList {
      height: 76px;
      li {
        display: flex;
        align-items: center;
        height: 76px;
        line-height: 76px;
        color: @default-banner-txt-color;
        width: 150px;
        font-size: 18px;
        font-weight: bold;
        text-align: center;
        cursor: pointer;
        span {
          margin-left: 7px;
        }
      }
    }
    .active {
      color: @active-txt-color !important;
      background-size: 150px;
    }
  }
}
</style>
src/layout/pageLayout.vue
New file
@@ -0,0 +1,46 @@
<template>
  <div class="layoutBox">
    <Header v-if="showHeader" class="header"></Header>
    <div class="layoutContentBox" id="layout">
      <RouterView />
    </div>
    <Footer class="footer"></Footer>
  </div>
</template>
<script setup lang="ts">
import { RouterView, useRoute } from 'vue-router'
import Header from './components/headerPage.vue'
import Footer from './components/footerPage.vue'
import { computed } from 'vue';
// 获取当前路由对象
const route = useRoute();
// 使用计算属性,根据路由的 meta 信息决定是否显示 Header
// 如果 meta.showHeader 不存在,默认为 true
const showHeader = computed(() => {
  return route.meta.showHeader !== false;
});
</script>
<style lang="less" scoped>
.layoutBox {
  width: 100%;
  min-width: 1200px;
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: url('../assets/images/default/BG.jpg') no-repeat;
  background-size: cover;
  .layoutContentBox {
    flex: 1;
  }
  .header {
    flex-shrink: 0;
    width: 100%;
  }
}
</style>
src/locales/en.json
New file
@@ -0,0 +1,45 @@
{
    "langSelector": {
        "chinese": "中文",
        "english": "English"
    },
    "message": {
        "welcome": "Welcome",
        "description": "This is an internationalization demo page.",
        "hello": "Hello, world!",
        "about": "About Us",
        "logoTitle": "BioChargeMap Natural Products Repository",
        "homeTitle": "Smart Search for Small Molecules",
        "aiTitle": "Smart Search for Small Molecules",
        "aiText": "Explore chemical structures, bioactivities, and more — powered by AI.",
        "searchResult": "SEARCH RESULT",
        "synonyms": "Synonyms",
        "ID": "ID",
        "MolecularFormula": "Molecular Formula",
        "MolecularWeight": "Molecular Weight",
        "Smiles": "Smiles",
        "XLogP3": "XLogP3",
        "HydrogenBondDonorCount": "Hydrogen Bond Donor Count",
        "HydrogenBondAcceptorCount": "Hydrogen Bond Acceptor Count",
        "FormalCharge": "Formal Charge",
        "PubmedID": "Pubmed ID",
        "Pubmedlink": "Pubmed link",
        "download": "Download",
        "GetImage": "Get Image",
        "compoundSummary": "COMPOUND SUMMARY",
        "About": "About",
        "webPolicies": "Web Policies",
        "Help": "Help",
        "FriendlyLinks": "Friendly Links",
        "ChinaAcademyofChineseMedicalSciences": "China Academy of Chinese Medical Sciences",
        "NationalGenomicsDataCenter": "National Genomics Data Center",
        "NationalAdministrationofTraditionalChineseMedicine": "National Administration of Traditional Chinese Medicine",
        "GraduateSchoolofChinaAcademyofChineseMedicalSciences": "Graduate School of China Academy of Chinese Medical Sciences",
        "COPYRIGHT2021ChinaAcademyofChineseMedical": "COPYRIGHT 2021 China Academy of Chinese Medical",
        "SeeMore": "See More",
        "Compounds": "Compounds",
        "Example": "Example",
        "LookAi": "Looking for smarter insights on chemical compounds? Just ask AI.",
        "Tryinto": "Try into"
    }
}
src/locales/zh.json
New file
@@ -0,0 +1,45 @@
{
    "langSelector": {
        "chinese": "中文",
        "english": "English"
    },
    "message": {
        "welcome": "欢迎使用",
        "description": "这是一个国际化演示页面。",
        "hello": "你好",
        "about": "关于我们",
        "logoTitle": "生物电荷图天然产物库",
        "homeTitle": "智能搜索小分子",
        "aiTitle": "智能搜索小分子",
        "aiText": "探索化学结构、生物活性等——由人工智能驱动。",
        "searchResult": "搜索结果",
        "synonyms": "同义词",
        "ID": "ID",
        "MolecularFormula": "分子式",
        "MolecularWeight": "分子量",
        "Smiles": "Smiles",
        "XLogP3": "XLogP3",
        "HydrogenBondDonorCount": "氢键供体",
        "HydrogenBondAcceptorCount": "氢键受体",
        "FormalCharge": "形式电荷",
        "PubmedID": "Pubmed ID",
        "Pubmedlink": "Pubmed link",
        "download": "下载",
        "GetImage": "获取图片",
        "compoundSummary": "复合摘要",
        "About": "关于我们",
        "webPolicies": "网站政策",
        "Help": "帮助",
        "FriendlyLinks": "友情链接",
        "ChinaAcademyofChineseMedicalSciences": "中国中医科学院",
        "NationalGenomicsDataCenter": "国家基因组科学数据中心",
        "NationalAdministrationofTraditionalChineseMedicine": "国家中医药管理局",
        "GraduateSchoolofChinaAcademyofChineseMedicalSciences": "中国中医科学院研究生院",
        "COPYRIGHT2021ChinaAcademyofChineseMedical": "版权所有 © 2021 中国中医科学院",
        "SeeMore": "查看更多",
        "Compounds": "化合物",
        "Example": "示例",
        "LookAi": "寻找更智能的化合物见解?问问AI吧。",
        "Tryinto": "试试看"
    }
}
src/main.ts
New file
@@ -0,0 +1,57 @@
import './assets/style/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import { createI18n } from 'vue-i18n'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import locale from 'element-plus/es/locale/lang/zh-cn'
// 自定义配置
import config from '@/assets/js/config'
// 请求处理
import MG from './assets/js/middleGround/WebMiddleGroundApi.js'
import toolClass from '@/assets/js/toolClass.js'
// 引入语言文件
import en from './locales/en.json'
import zh from './locales/zh.json'
const messages = {
  en: en,
  zh: zh,
}
// 创建i18n实例
const i18n = createI18n({
  locale: 'en', // 设置默认语言环境为中文
  fallbackLocale: 'zh',
  messages, // 设置资源
})
const app = createApp(App)
app.use(i18n) // 使用i18n插件
app.provide('config', config)
app.provide('MG', MG)
app.provide('toolClass', toolClass)
app.use(createPinia())
app.use(router)
app.use(ElementPlus, { locale })
app.use(ElementPlus, { locale })
// 全局注册element icon
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}
app.mount('#app')
router.beforeEach((to, from, next) => {
  window.scrollTo({ top: 0 }) // 将滚动条位置设为0
  next()
})
src/plugin/axios/index.ts
New file
@@ -0,0 +1,83 @@
import axios from 'axios'
import myConfig from '@/assets/js/config'
import toolClass from '@/assets/js/toolClass.js'
import router from '@/router'
// 创建 axios 实例
const service = axios.create({
  baseURL: myConfig.requestCtx,
  timeout: myConfig.requestTimeOut, // 请求超时时间
})
// 请求拦截器
service.interceptors.request.use(
  (config) => {
    let token = localStorage.getItem(myConfig.tokenKey)
    if (token) config.headers['Authorization'] = `bearer ${token}`
    return config
  },
  (error) => {
    // 发送失败
    Promise.reject(error)
  },
)
// 响应拦截器
service.interceptors.response.use(
  (response) => {
    // dataAxios 是 axios 返回数据中的 data
    const dataAxios = response.data
    if (typeof dataAxios.data === 'boolean') {
      return dataAxios.data
    }
    if (response.config.responseType == 'blob') {
      return dataAxios
    }
    const { success } = dataAxios
    if (dataAxios.currentDate) {
      sessionStorage.currentDate = new Date(dataAxios.currentDate).getTime()
    }
    // 根据 code 进行判断
    if (success) {
      return dataAxios.data ? dataAxios.data : dataAxios
    } else {
      // 提示错误
    }
  },
  (error) => {
    if ((error.response && error.response.status == 401) || error.code == 'ERR_NETWORK') {
      localStorage.removeItem(myConfig.tokenKey)
      localStorage.removeItem('jesk-userInfo')
      localStorage.removeItem('alreadyElectronicBook')
      localStorage.removeItem('alreadyPaperBook')
      localStorage.removeItem('electronicBookList')
      localStorage.removeItem('paperBookList')
      sessionStorage.removeItem('cartNumber')
      // router.replace({
      //   path: '/home',
      //   query: {
      //     showLogin: '1'
      //   }
      // })
      const url = window.location.hash.slice(1)
      console.log(url)
      if (url.includes('showLogin=1')) {
        router.push(url)
      } else {
        if (url.includes('?')) {
          router.push(url + '&showLogin=1')
        } else {
          router.push(url + '?showLogin=1')
        }
      }
    } else {
      if (error.response && error.response.data && error.response.data.error) {
        console.error(error.response.data.error.msg)
      } else {
        console.error('请求发生错误')
      }
    }
    return Promise.reject(error)
  },
)
export default service
src/router/index.ts
New file
@@ -0,0 +1,49 @@
import { createRouter, createWebHistory } from 'vue-router'
import HomePage from '../views/home/index.vue'
import PageLayout from '../layout/pageLayout.vue'
import { pathData } from '../assets/js/config'
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      redirect: '/index',
    },
    {
      path: '/index',
      name: 'layout',
      component: PageLayout,
      redirect: { name: 'home' },
      children: [
        {
          path: pathData.home,
          name: 'home',
          component: HomePage,
          meta: { showHeader: false },
        },
        {
          path: pathData.searchList,
          name: 'searchList',
          component: () => import('../views/searchList/index.vue'),
        },
        {
          path: pathData.detailsPage,
          name: 'detailsPage',
          component: () => import('@/views/detailsPage/index.vue'),
        },
      ],
    },
    {
      path: pathData.ai,
      name: 'AI',
      component: () => import('@/views/ai/index.vue'),
    },
    {
      path: pathData.aiDetails,
      name: 'aiDetails',
      component: () => import('@/views/ai/aiDetails.vue'),
    },
  ],
})
export default router
src/stores/counter.ts
New file
@@ -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 }
})
src/types/ai.d.ts
New file
@@ -0,0 +1,4 @@
export type ai = {
  historylist: Array<any>
  inputValue: string
}
src/types/aiDetails.d.ts
New file
@@ -0,0 +1,5 @@
export type aiDetails = {
  historylist: Array<any>
  inputValue: string
  message: Object
}
src/types/details.d.ts
New file
@@ -0,0 +1,3 @@
export type details = {
  list: Array<any>
}
src/types/home.d.ts
New file
@@ -0,0 +1,3 @@
export type home = {
  searchText: string
}
src/types/searchlist.d.ts
New file
@@ -0,0 +1,4 @@
export type searchList = {
  searchText: any
  list: Array<any>
}
src/views/ai/aiDetails.vue
New file
@@ -0,0 +1,454 @@
<template>
    <div class="chat-box">
        <div class="chat-box-left">
            <div class="new-chat">
                <el-icon>
                    <Plus />
                </el-icon>
                <div>New conversation</div>
            </div>
            <div class="chat-list" v-for="(item, index) in pageData.historylist">
                <div :title="item.content" @click="goAi(item)">{{ item.content }}</div>
            </div>
        </div>
        <div class="chat-box-right">
            <Header class="header"></Header>
            <!-- 聊天框内容容器 -->
            <div class="chat-box-content" ref="messagesContainer">
                <!-- 当前时间显示 -->
                <div class="chat-date">{{ currentTime }}</div>
                <!-- 底部信息展示 -->
                <div class="chat-back-info">
                    <!-- 头像 -->
                    <div class="back-avator">
                        <img src="../../assets/images/home/AI_logo.png" alt="" />
                    </div>
                    <!-- 基础图书信息 -->
                    <div class="base-book-box">
                        您好!我是您的AI智能助手,专注于小分子结构领域!我可以帮助您轻松获取与小分子结构相关的信息。您可以这样问我:“Aspirin是什么?”“xx的物理化学属性都是什么?”让小分子结构知识触手可及!
                    </div>
                </div>
                <!-- 消息列表 -->
                <div v-for="(item, index) in pageData.message" :key="index" class="chat-box-content-item">
                    <div v-if="item.type === 'user'" class="chat-date">{{ item.time }}</div>
                    <div :class="['message', item.type === 'user' ? 'user-message' : 'assistant-message']">
                        <!-- 助手头像 -->
                        <el-avatar class="assistant-avatar" :size="screenWidth > 375 ? 60 : 30"
                            :src="[item.type === 'user' ? userProfilePicture : assistantAvatar]" />
                        <!-- 消息内容 -->
                        <div :class="['message-content', item.type === 'user' ? 'user-message-content' : '']">
                            <!-- 用户消息 -->
                            <div class="user-message-text" v-if="item.type === 'user'" v-html="item.content"></div>
                            <!-- AI 图片消息 -->
                            <div :class="['message-text', 'requestText' + index].join(' ')"
                                v-if="item.type != 'user' && item.txtType == 'txt'">
                                <p class="message-text-title">
                                    AI智能助手为您找到以下{{ pageData.inputValue }}的信息内容如下:
                                </p>
                                <iframe class="message-text-iframe" ref="iframeRef" v-if="item.iframeSrc != ''"
                                    :src="item.iframeSrc" frameborder="0"></iframe>
                                <div v-html="item.content"></div>
                                <p class="message-text-titleOne">以上内容由AI生成,仅供参考。</p>
                            </div>
                            <!-- AI 文本消息 -->
                            <!-- <div :class="['Ai-message-text', 'requestText' + index].join(' ')"
              v-if="item.type != 'user' && item.txtType == 'txt'">
              <div v-html="item.content"></div>
            </div> -->
                            <!-- 消息底部时间 -->
                            <div class="message-footer" v-if="item.type != 'user'">
                                <span class="message-time">{{ item.time }}</span>
                            </div>
                        </div>
                    </div>
                    <!-- 加载中状态 -->
                    <div v-if="loading && index == message.length - 1"
                        class="message assistant-message loading-message">
                        <el-avatar class="assistant-avatar" :size="screenWidth > 375 ? 60 : 30"
                            :src="assistantAvatar" />
                        <div :class="['message-content', item.type === 'user' ? 'user-message-content' : '']">
                            <div class="message-text-loading">
                                <span class="dot-loading">思考中...</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <!-- 输入框 -->
            <div class="chat-footer">
                <!-- 输入框 -->
                <div class="chat-text">
                    <el-input type="textarea" :autosize="{ minRows: 3, maxRows: 3 }" placeholder=""
                        v-model="pageData.inputValue" @keyup.enter="handleEnter($event)" />
                </div>
                <!-- 功能选择区域 -->
                <div class="select">
                    <div class="select-right">
                        <div class="select-item">
                            <img @click="sendMsg()" :src="currentImage" alt="" />
                        </div>
                    </div>
                </div>
            </div>
            <div class="main-footer">
                Information displayed here is AI model generated and should not be considered as legal, finance or
                investment advice. You should always seek advice from a qualified <br />professional. Request
                consultation.
            </div>
        </div>
    </div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import type { aiDetails } from '@/types/aiDetails'
import current from '@/assets/images/ai/current.png'
import noCurrent from '@/assets/images/ai/noCurrent.png'
import dayjs from 'dayjs'
import Header from '@/layout/components/headerPage.vue'
const pageData = reactive<aiDetails>({
    historylist: [
        {
            content: "What is the quarterly water bill?",
        },
        {
            content: "How much are the council rates per quarter?",
        },
        {
            content: "What are the quarterly strata fees?",
        },
        {
            content: "What are the quarterly strata fees?",
        },
    ],
    inputValue: "",
    message: "",
})
const currentTime = ref(dayjs(new Date()).format('MM/DD HH:mm:ss'))
const currentImage = computed(() => {
    return pageData.inputValue.trim() === '' ? noCurrent : current;
});
const goAi = (e: any) => {
    pageData.inputValue = e.content;
};
</script>
<style lang="less" scoped>
.chat-box {
    display: flex;
    height: 100%;
    width: 100%;
}
.chat-box-left {
    width: 14%;
    border-right: 1px solid #F0F0F0;
    padding: 13px 17px;
    .new-chat {
        height: 34px;
        background: linear-gradient(90deg, #006CB6 0%, #01644C 100%);
        border-radius: 30px 30px 30px 30px;
        margin-top: 45px;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #fff;
        cursor: pointer;
        div {
            margin-left: 5px;
            font-weight: 400;
            font-size: 12px;
        }
    }
    .chat-list {
        width: 100%;
        margin-top: 28px;
        div {
            line-height: 1.5em;
            cursor: pointer;
            width: 100%;
            margin-top: 20px;
            overflow: hidden;
            text-wrap: nowrap;
        }
    }
}
.chat-box-right {
    width: 86%;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    .chat-box-content {
        width: 100%;
        height: calc(100vh - 150px);
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        overflow: auto;
        align-items: flex-start;
        .chat-send {
            width: 100%;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            align-items: flex-end;
            margin-bottom: 20px;
            .chat-send-info {
                width: 263px;
                height: 40px;
                background: #af8b56;
                border-radius: 20px;
                line-height: 40px;
                padding: 0 20px;
                color: #fff;
            }
            .chat-message {
                width: 263px;
                height: 40px;
                background: #fff;
                border-radius: 20px;
                line-height: 40px;
                padding: 0 20px;
                color: #000;
            }
        }
        .chat-date {
            color: #999;
            width: 100%;
            text-align: center;
            margin-bottom: 30px;
            margin-top: 30px;
        }
        .chat-send {
            width: 100%;
            display: flex;
            justify-content: flex-end;
            margin-bottom: 20px;
            .chat-send-info {
                width: 263px;
                height: 40px;
                background: #af8b56;
                border-radius: 20px;
                line-height: 40px;
                padding: 0 20px;
                color: #fff;
            }
        }
        .chat-back-info {
            margin-bottom: 20px;
            display: flex;
            justify-content: flex-start;
            // min-height: 90px;
            padding: 16px;
            .back-avator {
                margin-right: 10px;
                img {
                    width: 32px;
                }
            }
            .base-book-box {
                display: flex;
                width: 800px;
                padding: 20px 47px;
                box-sizing: border-box;
                background-color: #f7fffc;
                border-radius: 20px;
            }
        }
        .back-item {
            width: 349px;
            height: auto;
            background: #ffffff;
            border-radius: 20px;
            margin-left: 100px;
            margin-bottom: 20px;
            .back-item-title {
                width: 80%;
                height: 60px;
                display: flex;
                align-items: center;
                padding: 0 10px;
                margin: auto;
                border-bottom: 1px solid #e9d8bf;
            }
            .hot-question {
                cursor: pointer;
                &:hover {
                    color: #d2a25b;
                }
            }
            img {
                margin-right: 10px;
            }
            ul li {
                list-style: none;
                margin: 20px 0 20px 0;
                display: flex;
                justify-content: flex-start;
                align-items: center;
            }
            .chat-change {
                display: flex;
                justify-content: flex-end;
                align-items: center;
                padding: 0 20px;
                color: #d2a25b;
                margin-bottom: 10px;
                cursor: pointer;
                img {
                    cursor: pointer;
                }
            }
        }
        .chat-box-content-item {
            width: 100%;
        }
    }
    .chat-box-content::-webkit-scrollbar {
        width: 1px;
    }
    /* 隐藏水平滚动条 */
    .chat-box-content::-webkit-scrollbar {
        height: 0;
    }
    .chat-footer {
        width: 62%;
        min-width: 800px;
        border-radius: 8px 8px 8px 8px;
        border: 1px solid #E8E8E8;
        padding: 9px 13px;
        box-sizing: border-box;
        margin-bottom: 10px;
    }
    ::v-deep(.chat-text) {
        // height: 100%;
        display: flex;
        align-items: center;
        margin-bottom: 10px;
        .el-textarea__inner {
            overflow: auto;
            height: 100% !important;
            border: none !important;
            outline: none !important;
            box-shadow: none !important;
            background-color: transparent !important;
            resize: none !important;
        }
        img {
            cursor: pointer;
            min-height: 25px;
        }
    }
    .select {
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: space-between;
        .select-left,
        .select-right {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: flex-start;
            .upload-demo {
                height: 24px;
            }
            svg {
                cursor: pointer;
            }
            .select-item {
                display: flex;
                align-items: center;
                padding: 2px 10px;
                box-sizing: border-box;
                border: 1px solid #e9d8bf;
                border-radius: 15px;
                font-size: 14px;
                font-family:
                    Microsoft YaHei,
                    Microsoft YaHei-Regular;
                font-weight: 400;
                color: #e1c49a;
                img {
                    height: 34px;
                    cursor: pointer;
                }
            }
        }
        .select-right {
            display: flex;
            align-items: center;
            justify-content: flex-end;
            .select-item {
                border: 0;
            }
        }
    }
    .main-footer {
        text-align: center;
        font-weight: 400;
        font-size: 12px;
        color: #BABABA;
        line-height: 1.4em;
    }
}
</style>
src/views/ai/index.vue
New file
@@ -0,0 +1,268 @@
<template>
    <div class="chat-box">
        <div class="chat-box-left">
            <img class="logo" src="../../assets/images/home/zylogo.png" alt="">
            <div class="new-chat">
                <el-icon>
                    <Plus />
                </el-icon>
                <div>New conversation</div>
            </div>
            <div class="chat-list" v-for="(item, index) in pageData.historylist">
                <div :title="item.content" @click="goAi(item)">{{ item.content }}</div>
            </div>
        </div>
        <div class="chat-box-right">
            <div class="main-title">
                Hello,l am <img src="../../assets/images/home/AI_logo.png" alt=""> Al Assistant
            </div>
            <div class="main-introduce">
                Ask anything about molecular structures, properties, or potential targets. Get instant AI-powered
                insights<br /> from our curated small molecule library.
            </div>
            <!-- 输入框 -->
            <div class="chat-footer">
                <!-- 输入框 -->
                <div class="chat-text">
                    <el-input type="textarea" :autosize="{ minRows: 3, maxRows: 3 }" placeholder=""
                        v-model="pageData.inputValue" @keyup.enter="handleEnter($event)" />
                </div>
                <!-- 功能选择区域 -->
                <div class="select">
                    <div class="select-right">
                        <div class="select-item">
                            <img @click="sendMsg()" :src="currentImage" alt="" />
                        </div>
                    </div>
                </div>
            </div>
            <div class="main-footer">
                Information displayed here is AI model generated and should not be considered as legal, finance or
                investment advice. You should always seek advice from a qualified <br />professional. Request
                consultation.
            </div>
        </div>
    </div>
</template>
<script lang="ts" setup>
import { reactive, computed } from 'vue'
import type { ai } from '@/types/ai'
import current from '@/assets/images/ai/current.png'
import noCurrent from '@/assets/images/ai/noCurrent.png'
import { pathData } from '@/assets/js/config'
import router from '@/router'
const pageData = reactive<ai>({
    historylist: [
        {
            content: "What is the quarterly water bill?",
        },
        {
            content: "How much are the council rates per quarter?",
        },
        {
            content: "What are the quarterly strata fees?",
        },
        {
            content: "What are the quarterly strata fees?",
        },
    ],
    inputValue: ""
})
const currentImage = computed(() => {
    return pageData.inputValue.trim() === '' ? noCurrent : current;
});
const goAi = (e: any) => {
    pageData.inputValue = e.content;
};
const sendMsg = () => {
    const query = { searchText: pageData.inputValue };
    router.push({ path: pathData.aiDetails, query })
};
</script>
<style lang="less" scoped>
.chat-box {
    display: flex;
    height: 100%;
    width: 100%;
}
.chat-box-left {
    width: 14%;
    border-right: 1px solid #F0F0F0;
    padding: 13px 17px;
    .logo {
        width: 100%;
    }
    .new-chat {
        height: 34px;
        background: linear-gradient(90deg, #006CB6 0%, #01644C 100%);
        border-radius: 30px 30px 30px 30px;
        margin-top: 45px;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #fff;
        cursor: pointer;
        div {
            margin-left: 5px;
            font-weight: 400;
            font-size: 12px;
        }
    }
    .chat-list {
        width: 100%;
        margin-top: 28px;
        div {
            line-height: 1.5em;
            cursor: pointer;
            width: 100%;
            margin-top: 20px;
            overflow: hidden;
            text-wrap: nowrap;
        }
    }
}
.chat-box-right {
    width: 86%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    .main-title {
        display: flex;
        align-items: center;
        font-weight: 500;
        font-size: 22px;
        color: #000000;
        line-height: 40px;
        img {
            margin: 0 5px;
            height: 48px;
        }
    }
    .main-introduce {
        text-align: center;
        margin: 10px 0 48px 0;
        font-weight: 400;
        font-size: 12px;
        color: #BABABA;
        line-height: 1.4em;
    }
    .chat-footer {
        width: 62%;
        min-width: 800px;
        border-radius: 8px 8px 8px 8px;
        border: 1px solid #E8E8E8;
        padding: 9px 13px;
        box-sizing: border-box;
        margin-bottom: 10px;
    }
    ::v-deep(.chat-text) {
        // height: 100%;
        display: flex;
        align-items: center;
        margin-bottom: 10px;
        .el-textarea__inner {
            overflow: auto;
            height: 100% !important;
            border: none !important;
            outline: none !important;
            box-shadow: none !important;
            background-color: transparent !important;
            resize: none !important;
        }
        img {
            cursor: pointer;
            min-height: 25px;
        }
    }
    .select {
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: space-between;
        .select-left,
        .select-right {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: flex-start;
            .upload-demo {
                height: 24px;
            }
            svg {
                cursor: pointer;
            }
            .select-item {
                display: flex;
                align-items: center;
                padding: 2px 10px;
                box-sizing: border-box;
                border: 1px solid #e9d8bf;
                border-radius: 15px;
                font-size: 14px;
                font-family:
                    Microsoft YaHei,
                    Microsoft YaHei-Regular;
                font-weight: 400;
                color: #e1c49a;
                img {
                    height: 34px;
                    cursor: pointer;
                }
            }
        }
        .select-right {
            display: flex;
            align-items: center;
            justify-content: flex-end;
            .select-item {
                border: 0;
            }
        }
    }
    .main-footer {
        text-align: center;
        font-weight: 400;
        font-size: 12px;
        color: #BABABA;
        line-height: 1.4em;
    }
}
</style>
src/views/detailsPage/index.vue
New file
@@ -0,0 +1,308 @@
<template>
    <page>
        <div class="detailsPage">
            <div class="detailsPage-box">
                <div class="details-result">
                    {{ t('message.compoundSummary') }}
                </div>
                <div class="details-main" v-for="(item, index) in pageData.list" :key="index">
                    <div class="details-name">{{ item.name }}</div>
                    <div class="details-box">
                        <div class="details-box-left">
                            <div class="left-item">
                                <div class="left-item-title">{{ t('message.ID') }}</div>
                                <div class="left-item-content">{{ item.ID }}</div>
                            </div>
                            <div class="left-item">
                                <div class="left-item-title">{{ t('message.MolecularFormula') }}</div>
                                <div class="left-item-content">{{ item.MolecularFormula }}</div>
                            </div>
                            <div class="left-item">
                                <div class="left-item-title">{{ t('message.MolecularWeight') }}</div>
                                <div class="left-item-content">{{ item.MolecularWeight }}</div>
                            </div>
                            <div class="left-item">
                                <div class="left-item-title">{{ t('message.Smiles') }}</div>
                                <div class="left-item-content">{{ item.Smiles }}</div>
                            </div>
                            <div class="left-item">
                                <div class="left-item-title">{{ t('message.XLogP3') }}</div>
                                <div class="left-item-content">{{ item.XLogP3 }}</div>
                            </div>
                            <div class="left-item">
                                <div class="left-item-title">{{ t('message.HydrogenBondDonorCount') }}</div>
                                <div class="left-item-content">{{ item.HydrogenBondDonorCount }}</div>
                            </div>
                            <div class="left-item">
                                <div class="left-item-title">{{ t('message.HydrogenBondAcceptorCount') }}</div>
                                <div class="left-item-content">{{ item.HydrogenBondAcceptorCount }}</div>
                            </div>
                            <div class="left-item">
                                <div class="left-item-title">{{ t('message.FormalCharge') }}</div>
                                <div class="left-item-content">{{ item.FormalCharge }}</div>
                            </div>
                            <div class="left-item">
                                <div class="left-item-title">{{ t('message.PubmedID') }}</div>
                                <div class="left-item-content">{{ item.PubmedID }}</div>
                            </div>
                            <div class="left-item">
                                <div class="left-item-title">{{ t('message.Pubmedlink') }}</div>
                                <div class="left-item-content">{{ item.Pubmedlink }}</div>
                            </div>
                        </div>
                        <div class="details-box-right">
                            <div class="right-img2D">
                                <img :src="item.img2D" alt="">
                                <div>2D</div>
                            </div>
                            <div class="right-img3D">
                                <img :src="item.img3D" alt="">
                                <div>3D</div>
                            </div>
                        </div>
                    </div>
                    <div class="details-others">
                        <div v-for="(citem, dindex) in item.content" :key="dindex">
                            <div class="others-box-title">
                                <div class="title-icon"></div>
                                <div class="title-text">{{ citem.name }}</div>
                            </div>
                            <div class="others-box-content">
                                <div class="content-download">
                                    <img v-if="citem.type == 'Conformer'" src="../../assets/images/details/getImage.png"
                                        alt="">
                                    <div v-if="citem.type == 'Conformer'" class="content-text">{{ t('message.GetImage')
                                    }}</div>
                                    <img src="../../assets/images/details/download.png" alt="">
                                    <div class="content-text">{{ t('message.download') }}</div>
                                </div>
                                <div class="content-main">
                                    <iframe class="message-text-iframe" ref="iframeRef" :src="citem.iframeSrc"
                                        frameborder="0"></iframe>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </page>
</template>
<script setup lang="ts">
import { inject, reactive } from 'vue'
import { useI18n } from 'vue-i18n';
const { locale, t } = useI18n();
import type { details } from '@/types/details'
import img2D from '../../assets/images/serachList/2D.png'
import img3D from '../../assets/images/serachList/3D.png'
const pageData = reactive<details>({
    list: [
        {
            name: 'Aspirin',
            ID: "224456FRET",
            XLogP3: "1.2",
            FormalCharge: "123",
            img2D: img2D,
            img3D: img3D,
            HydrogenBondDonorCount: "1",
            HydrogenBondAcceptorCount: "4",
            PubmedID: "0",
            Pubmedlink: "https://pubchem.ncbi.nlm.nih.gov/compound/#CID#",
            content: [
                {
                    name: "Charge Distribution",
                    type: "text",
                },
                {
                    name: "Herbs Containing This Ingredient",
                    type: "text",
                },
                {
                    name: "2D Structure",
                    type: "Conformer",
                },
                {
                    name: "3D Conformer",
                    type: "Conformer",
                    iframeSrc: "11",
                },
            ]
        },
    ]
})
</script>
<style lang="less" scoped>
.detailsPage {
    border-top: 1px solid #D9D9D9;
    background-color: #ecf9f6;
}
.detailsPage-box {
    width: 63%;
    margin: 0 auto;
    padding: 0 0 25px 0;
    .details-result {
        padding: 23px 0;
    }
    .details-name {
        font-family: Inter, Inter;
        font-weight: 500;
        font-size: 48px;
    }
    .details-box {
        width: 100%;
        background: #FFFFFF;
        border-radius: 10px 10px 10px 10px;
        padding: 19px 27px 45px 27px;
        margin-top: 20px;
        margin-bottom: 24px;
        display: flex;
    }
    .details-box-left {
        width: 70%;
        position: relative;
        .left-item {
            width: 100%;
            display: flex;
            margin-bottom: 22px;
        }
        .left-item-title {
            width: 35%;
            font-family: Inter, Inter;
            font-weight: 400;
            font-size: 13px;
            color: #385B53;
        }
        .left-item-content {
            font-family: Inter, Inter;
            font-weight: 400;
            font-size: 13px;
            color: #000;
        }
    }
    .details-box-left::after {
        content: '';
        /* 伪元素必须设置 content 属性 */
        position: absolute;
        top: 0;
        right: 0;
        width: 1px;
        /* 边框的宽度 */
        height: 100%;
        /* 与父元素等高 */
        /* 直接设置背景为渐变 */
        background: linear-gradient(180deg,
                rgba(255, 255, 255, 0),
                rgba(184, 184, 184, 1),
                rgba(255, 255, 255, 0));
    }
    .details-box-right {
        width: 30%;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: space-around;
        .right-img2D {
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        .right-img3D {
            display: flex;
            flex-direction: column;
            align-items: center;
        }
    }
    .details-others {
        width: 100%;
        background: #FFFFFF;
        border-radius: 10px 10px 10px 10px;
        padding: 19px 27px 45px 27px;
        margin-top: 20px;
        margin-bottom: 24px;
        .others-box-title {
            display: flex;
            align-items: center;
            .title-icon {
                display: block;
                width: 5px;
                height: 33px;
                background: linear-gradient(180deg, #5AB546 0%, #01644C 100%);
                border-radius: 0px 0px 0px 0px;
                margin-right: 10px;
            }
            .title-text {
                font-family: Inter, Inter;
                font-weight: normal;
                font-size: 20px;
                color: #333;
            }
        }
        .others-box-content {
            margin-top: 37px;
            width: 100%;
            .content-download {
                width: 100%;
                display: flex;
                justify-content: end;
                align-items: center;
                background-color: #F0F0F0;
                border-radius: 5px 5px 0px 0px;
                padding: 7px 21px;
                cursor: pointer;
                img {
                    height: 24px;
                }
                .content-text {
                    margin-right: 10px
                }
            }
            .content-main {
                width: 100%;
                height: 282px;
                border: 1px solid #EBEBEB;
                border-radius: 0px 0px 5px 5px;
                margin-bottom: 20px;
            }
        }
    }
}
</style>
src/views/home/index.vue
New file
@@ -0,0 +1,375 @@
<template>
    <page>
        <div class="page">
            <div class="page-select">
                <el-select v-model="currentLocale" placeholder="Language" style="width: 120px">
                    <el-option v-for="item in availableLocales" :key="item.value" :label="t(item.label)"
                        :value="item.value" />
                </el-select>
            </div>
            <div class="page-main">
                <ul class="page-title">
                    <li class="zylogo"><img src="../../assets/images/home/zylogo.png" alt=""></li>
                    <li class="separator"></li>
                    <li class="sylogo"><img src="../../assets/images/home/sylogo.svg" alt=""></li>
                    <li class="title-text">{{ t('message.logoTitle') }}</li>
                </ul>
                <div class="page-content">
                    <div class="page-content-name">{{ t('message.aiTitle') }}</div>
                    <div class="page-content-text">{{ t('message.aiText') }}</div>
                </div>
                <div class="page-search">
                    <div class="search-data">
                        <div class="left-See">{{ t('message.SeeMore') }} ></div>
                        <div class="left-data">121M</div>
                        <div class="left-text">{{ t('message.Compounds') }}</div>
                    </div>
                    <div class="search-main">
                        <div class="searchTop">
                            <div class="searchInputBox">
                                <input v-model="pageData.searchText" type="text" placeholder="" />
                                <el-button color="#16569C" :icon="Search" class="search-btn" round
                                    @click="gotoPage()"></el-button>
                            </div>
                            <ul class="searchExample">
                                <li class="example">{{ t('message.Example') }}:</li>
                                <li class="example-item">aspirin</li>
                                <li class="example-item">aspirin</li>
                            </ul>
                        </div>
                        <div class="searchBottom">
                            <div class="ailogo"><img src="../../assets/images/home/AI_logo.png" alt="">
                                <div>
                                    {{ t('message.LookAi') }}
                                </div>
                            </div>
                            <div class="tryinto" @click="goAi()">
                                <div> {{ t('message.Tryinto') }}</div>
                                <img src="../../assets/images/home/rightArrow.png" alt="">
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </page>
</template>
<script setup lang="ts">
import { inject, ref, computed, reactive } from 'vue'
import { useI18n } from 'vue-i18n';
import { Search } from '@element-plus/icons-vue'
import type { home } from '@/types/home'
import { pathData } from '@/assets/js/config'
const { locale, t } = useI18n();
const config: any = inject('config')
import router from '@/router'
const availableLocales = [
    { value: 'zh', label: 'langSelector.chinese' },
    { value: 'en', label: 'langSelector.english' },
];
const pageData = reactive<home>({
    searchText: ""
})
const currentLocale = computed({
    get: () => locale.value,
    set: (value) => {
        locale.value = value;
        // (可选) 将语言偏好保存到 localStorage,以便下次记住用户选择
        localStorage.setItem('user-locale', value);
    },
});
const gotoPage = () => {
    const query = { searchText: pageData.searchText };
    router.push({ path: pathData.searchList, query })
}
const goAi = () => {
    router.push({ path: pathData.ai, })
}
</script>
<style lang="less" scoped>
.page {
    height: calc(100vh - 190px);
    width: 100%;
    min-width: 1200px;
    background: url("../../assets/images/home/home_bg.png") no-repeat;
    background-size: cover;
    background-position: center center;
}
.page-select {
    padding-top: 21px;
    margin-left: 72%;
}
.page-main {
    width: 60%;
    margin: 0 auto;
}
.page-title {
    margin-top: 55px;
    display: flex;
    justify-content: center;
    align-items: center;
}
.zylogo {
    img {
        width: 225px;
    }
}
.separator {
    list-style: none;
    width: 20px;
    height: 20px;
    margin-right: 15px;
    position: relative;
}
/* 2. 创建第一个伪元素('\' 斜杠) */
.separator::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    /* 和容器一样宽 */
    height: 1px;
    /* 线条粗细 */
    border-top: 1px dashed #ccc;
    /* 虚线样式 */
    transform: translateY(-50%) rotate(45deg);
    /* 先垂直居中,再旋转45度 */
}
/* 3. 创建第二个伪元素('/' 斜杠) */
.separator::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    /* 和容器一样宽 */
    height: 1px;
    /* 线条粗细 */
    border-top: 1px dashed #ccc;
    /* 虚线样式 */
    transform: translateY(-50%) rotate(-45deg);
    /* 先垂直居中,再反向旋转45度 */
}
.sylogo {
    padding-right: 18px;
    border-right: 1px solid #0c73b8;
    img {
        width: 204px;
    }
}
.title-text {
    padding-left: 14px;
    font-weight: bold;
    font-size: 20px;
}
.page-content {
    margin-top: 7.5%;
    .page-content-name {
        text-align: center;
        font-family: Inter, Inter;
        font-weight: bold;
        font-size: 48px;
    }
    .page-content-text {
        text-align: center;
        margin-top: 24px;
    }
}
.page-search {
    margin-top: 7.5%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .search-data {
        width: 17.8%;
        height: auto;
        background-image: url("../../assets/images/home/search-left.png");
        background-size: cover;
        background-position: center center;
        border: 1px dashed #949796;
        border-radius: 5px;
        img {
            width: 100%;
            opacity: 0.7;
        }
        .left-See {
            text-align: right;
            padding-right: 10px;
            margin: 10px 0 49px 0;
            color: #5AB546;
            cursor: pointer;
        }
        .left-data {
            text-align: center;
            font-weight: 500;
            font-size: 33px;
            color: #000000;
        }
        .left-text {
            text-align: center;
            margin-top: 11px;
            margin-bottom: 50px;
            font-family: Inter, Inter;
            font-weight: 400;
            font-size: 13px;
        }
    }
    .search-main {
        width: 80.2%;
        border-radius: 10px;
        border: 1px solid #136E56;
    }
    .searchTop {
        background-color: #fff;
        padding: 41px 0 0 0;
        border-radius: 10px 10px 0px 0px;
    }
    .searchInputBox {
        height: 57px;
        width: 91%;
        margin: 0 auto;
        color: #DFDFDF;
        display: flex;
        align-items: center;
        border: 1px solid #DFDFDF;
        border-radius: 500px;
        overflow: hidden;
        background-color: white;
        padding-left: 10px;
    }
    .search-btn {
        height: 100%;
        width: 8.1%;
        border-radius: 60px;
    }
    .searchInputBox input {
        flex: 1;
        width: 50%;
        height: 90%;
        font-family: STSongti-SC-Regular;
        font-size: 14px;
        letter-spacing: 0.5px;
        border: none;
        outline: none
    }
    .searchExample {
        width: 91%;
        margin: 0 auto;
        padding: 10px 0;
        display: flex;
        .example {
            font-family: Inter, Inter;
            font-weight: 500;
            font-size: 14px;
            text-align: left;
            font-style: normal;
            text-transform: none;
            color: linear-gradient(0deg, #5AB546 0%, #006CB6 100%);
        }
        .example-item {
            border-radius: 15px;
            background-color: #f3f3f3;
            margin-right: 15px;
            margin-left: 15px;
            padding: 2px 5px;
        }
    }
    .searchBottom {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 10px 30px;
        border-radius: 0 0 10px 10px;
        background: linear-gradient(90deg, #E8F5F0 0%, #E3F4FF 100%);
        .ailogo {
            display: flex;
            align-items: center;
            height: 32px;
            img {
                height: 100%;
                margin-right: 20px;
            }
        }
        .tryinto {
            display: inline-flex;
            align-items: center;
            font-weight: bold;
            font-size: 16px;
            color: transparent;
            background: linear-gradient(0deg, #5AB546 0%, #006CB6 100%);
            background-clip: text;
            -webkit-background-clip: text;
            position: relative;
            line-height: 1.5;
            cursor: pointer;
            img {
                padding-left: 10px;
                height: 15px;
            }
        }
    }
}
.large-icon :deep(.el-icon) {
    /* 方法 A: 使用 Element Plus 的 CSS 变量 (推荐) */
    --el-icon-size: 24px;
    /* 或者你想要的任何尺寸 */
    /* 方法 B: 直接设置字体大小 (同样有效) */
    /* font-size: 24px; */
}
/* 如果你只想针对这个特定的按钮,可以更精确地选择器 */
.search-btn :deep(.el-icon) {
    --el-icon-size: 24px;
}
</style>
src/views/searchList/index.vue
New file
@@ -0,0 +1,319 @@
<template>
    <page>
        <div class="searchList">
            <div class="search-input">
                <div class="searchInputBox">
                    <input v-model="pageData.searchText" type="text" placeholder="" />
                    <el-button color="#16569C" :icon="Search" class="search-btn" round
                        @click="getList(pageData.searchText)" style=""></el-button>
                </div>
            </div>
            <div class="search-list">
                <div class="search-result">
                    {{ t('message.searchResult') }} ({{ pageData.list.length }})
                </div>
                <div class="search-item" v-for="(item, index) in pageData.list" :key="index" @click="goPage(item)">
                    <div class="search-item-name">{{ item.name }}</div>
                    <div class="search-item-synonyms">
                        <span>{{ t('message.synonyms') }}:</span>{{ item.synonyms }}
                    </div>
                    <div class="search-item-box">
                        <div class="box-left">
                            <div class="box-left-item">
                                <span>{{ t('message.ID') }}:</span>{{ item.ID }}
                            </div>
                            <div class="box-left-MolecularFormula">
                                <span>{{ t('message.MolecularFormula') }}:</span>
                                <div v-html="item.MolecularFormula"></div>
                            </div>
                            <div class="box-left-item">
                                <span>{{ t('message.MolecularWeight') }}:</span>{{ item.MolecularWeight }}
                            </div>
                            <div class="box-left-item">
                                <span>{{ t('message.Smiles') }}:</span>{{ item.Smiles }}
                            </div>
                            <div class="box-left-item">
                                <span>{{ t('message.XLogP3') }}:</span>{{ item.XLogP3 }}
                            </div>
                            <div class="box-left-item">
                                <span>{{ t('message.HydrogenBondDonorCount') }}:</span>{{ item.HydrogenBondDonorCount }}
                            </div>
                            <div class="box-left-item">
                                <span>{{ t('message.HydrogenBondAcceptorCount') }}:</span>{{
                                    item.HydrogenBondAcceptorCount }}
                            </div>
                            <div class="box-left-item">
                                <span>{{ t('message.FormalCharge') }}:</span>{{ item.FormalCharge }}
                            </div>
                        </div>
                        <div class="box-right">
                            <div>
                                <img :src="item.img2D" alt="" />
                                <div>2D</div>
                            </div>
                            <div>
                                <img :src="item.img3D" alt="" />
                                <div>3D</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </page>
</template>
<script setup lang="ts">
import { inject, reactive, onMounted } from 'vue'
import { Search } from '@element-plus/icons-vue'
import type { searchList } from '@/types/searchlist'
import { useI18n } from 'vue-i18n'
const { locale, t } = useI18n()
import { pathData } from '@/assets/js/config'
import router from '@/router'
import img2D from '../../assets/images/serachList/2D.png'
import img3D from '../../assets/images/serachList/3D.png'
import MG from '@/assets/js/middleGround/WebMiddleGroundApi.js'
const config: any = inject('config')
const pageData = reactive<searchList>({
    searchText: '',
    list: [
        {
            name: 'Aspirin',
            FormalCharge:
                '9999999999999999999999999999999999999999999999999999999999999999999999989999999999999999999999999999999999999999999',
            img2D: img2D,
            img3D: img3D,
        },
    ],
})
onMounted(() => {
    pageData.searchText = router.currentRoute.value.query.searchText
    getList(pageData.searchText)
})
const getList = (txt: any) => {
    const searchData = {
        'Name*': pageData.searchText
    }
    console.log(searchData);
    MG.resource.getItem({
        path: config.refCodes.BioChargeMap,
        queryType: '*',
        paging: { start: 0, size: 999999999 },
        searchList: [
            {
                compareType: '',
                keywords: txt ?? "",
                field: 'string',
                subSearches: ['string'],
            },
        ],
        sort: {
            LinkOrder: 'Desc',
        },
        fields: {
            ID: '',
            Synonyms: [],
            MolecularWeight: [],
            SMILE: [],
            XLogP3: [],
            HydrogenBondDonorCount: [],
            HydrogenBondAcceptorCount: [],
            FormalCharge: [],
            ChargeDistribution: [],
            PubChemCID: [],
            PubmedLink: [],
            '2DStructure': [],
            '3DConformer': [],
            MolecularFormula: [],
            SynonymsLine: [],
            ...searchData
        }
    }).then((res: any) => {
        if (res.datas.length > 0) {
            res.datas.forEach((item: any) => {
                // item.SynonymsLine = item.Synonyms.join(';')
            })
            pageData.list = res.datas
        }
    })
}
const goPage = (item: any) => {
    router.push(pathData.detailsPage)
}
</script>
<style lang="less" scoped>
.searchList {
    height: 100%;
    background-color: #ecf9f6;
}
.search-input {
    width: 100%;
    background-image: url('../../assets/images/serachList/list_bg.png');
    background-size: cover;
    background-position: center center;
    padding: 28px 0 51px 0;
    .searchInputBox {
        width: 60%;
        height: 57px;
        margin: 0 auto;
        color: #dfdfdf;
        display: flex;
        align-items: center;
        border: 1px solid #dfdfdf;
        border-radius: 500px;
        overflow: hidden;
        background-color: white;
        padding-left: 10px;
    }
    .searchInputBox input {
        flex: 1;
        width: 50%;
        height: 90%;
        font-family: STSongti-SC-Regular;
        font-size: 14px;
        letter-spacing: 0.5px;
        border: none;
        outline: none;
    }
    .search-btn {
        height: 100%;
        width: 7.1%;
        border-radius: 60px;
    }
}
.search-list {
    width: 64%;
    margin: 0 auto;
    padding: 25px 0;
    overflow-y: auto;
}
.search-result {
    padding-bottom: 23px;
}
.search-item {
    width: 100%;
    background: #ffffff;
    border-radius: 10px 10px 10px 10px;
    padding: 17px 27px;
    margin-bottom: 24px;
    &:hover {
        cursor: pointer;
        border: 2px solid;
        border-image: linear-gradient(90deg, rgba(0, 108, 182, 1), rgba(1, 100, 76, 1)) 2 2;
        border-radius: 10px 10px 10px 10px;
    }
    .search-item-name {
        font-weight: normal;
        font-size: 18px;
        color: #2d806c;
        padding-bottom: 12px;
    }
    .search-item-synonyms {
        padding-bottom: 12px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        span {
            padding-right: 5px;
            font-family: Inter, Inter;
            font-weight: 400;
            font-size: 13px;
            color: #385b53;
        }
    }
    .search-item-box {
        display: flex;
    }
    .box-left {
        width: 65%;
        position: relative;
        .box-left-item {
            font-family: Inter, Inter;
            font-weight: 400;
            font-size: 13px;
            color: #000;
            padding-bottom: 12px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .box-left-MolecularFormula {
            display: flex;
            div {
                font-size: 13px;
            }
        }
        span {
            padding-right: 5px;
            font-family: Inter, Inter;
            font-weight: 400;
            font-size: 13px;
            color: #385b53;
        }
    }
    .box-left::after {
        content: '';
        /* 伪元素必须设置 content 属性 */
        position: absolute;
        top: 0;
        right: 0;
        width: 1px;
        /* 边框的宽度 */
        height: 100%;
        /* 与父元素等高 */
        /* 直接设置背景为渐变 */
        background: linear-gradient(180deg,
                rgba(255, 255, 255, 0),
                rgba(184, 184, 184, 1),
                rgba(255, 255, 255, 0));
    }
    .box-right {
        width: 35%;
        padding: 30px 48px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        img {
            padding-bottom: 20px;
        }
        div {
            display: flex;
            flex-direction: column;
            align-items: center;
        }
    }
}
.fl {
    display: flex;
}
</style>
tsconfig.app.json
New file
@@ -0,0 +1,12 @@
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "exclude": ["src/**/__tests__/*"],
  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
tsconfig.json
New file
@@ -0,0 +1,11 @@
{
  "files": [],
  "references": [
    {
      "path": "./tsconfig.node.json"
    },
    {
      "path": "./tsconfig.app.json"
    }
  ]
}
tsconfig.node.json
New file
@@ -0,0 +1,20 @@
{
  "extends": "@tsconfig/node18/tsconfig.json",
  "include": [
    "vite.config.*",
    "vitest.config.*",
    "cypress.config.*",
    "nightwatch.conf.*",
    "playwright.config.*",
    "eslint.config.*"
  ],
  "compilerOptions": {
    "noEmit": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "types": [
      "node"
    ]
  }
}
vite.config.ts
New file
@@ -0,0 +1,36 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import ElementPlus from 'unplugin-element-plus/vite'
// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    ElementPlus({
      useSource: true,
    }),
  ],
  base: './',
  server: {
    host: '0.0.0.0',
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },
  css: {
    // 预处理器配置项
    preprocessorOptions: {
      less: {
        math: 'always',
        additionalData: `@import "@/assets/style/variable.less";`,
      },
      scss: {
        additionalData: `@use "@/assets/element/index.scss" as *;`,
      },
    },
  },
})