Browse Source

AI小财神框架

dong
hongxilin 2 months ago
parent
commit
5f987688d8
  1. 13
      .env.development
  2. 19
      .env.production
  3. 213
      .eslintrc-auto-import.json
  4. 24
      .gitignore
  5. 3
      .vscode/extensions.json
  6. 11
      README.md
  7. 43
      build/utils.js
  8. 44
      build/vite/build.js
  9. 26
      build/vite/plugin/autoImport.js
  10. 21
      build/vite/plugin/autocomponents.js
  11. 34
      build/vite/plugin/compress.js
  12. 37
      build/vite/plugin/index.js
  13. 19
      build/vite/plugin/mock.js
  14. 43
      build/vite/proxy.js
  15. 18
      index.html
  16. 7073
      package-lock.json
  17. 66
      package.json
  18. 1
      public/vite.svg
  19. 11
      src/App.vue
  20. 70
      src/api/AIxiaocaishen.js
  21. BIN
      src/assets/img/AIchat/AIgif1.gif
  22. BIN
      src/assets/img/AIchat/AIgif2.gif
  23. BIN
      src/assets/img/AIchat/AIgif3.gif
  24. BIN
      src/assets/img/AIchat/AIgif4.gif
  25. BIN
      src/assets/img/homePage/AIicon.png
  26. BIN
      src/assets/img/homePage/announcement.png
  27. BIN
      src/assets/img/homePage/bk.png
  28. BIN
      src/assets/img/homePage/coin-plus.png
  29. BIN
      src/assets/img/homePage/coin.png
  30. BIN
      src/assets/img/homePage/count-box.png
  31. BIN
      src/assets/img/homePage/get-count-all.png
  32. BIN
      src/assets/img/homePage/get-count.png
  33. BIN
      src/assets/img/homePage/logo.png
  34. BIN
      src/assets/img/homePage/madeInHL.png
  35. BIN
      src/assets/img/homePage/tail/language.png
  36. BIN
      src/assets/img/homePage/tail/msg-box.png
  37. BIN
      src/assets/img/homePage/tail/msg.png
  38. BIN
      src/assets/img/homePage/tail/send.png
  39. BIN
      src/assets/img/homePage/tail/think-active.png
  40. BIN
      src/assets/img/homePage/tail/think-no-active.png
  41. BIN
      src/assets/img/homePage/tail/voice.png
  42. 1
      src/assets/vue.svg
  43. 214
      src/auto-import.d.ts
  44. 11
      src/components.d.ts
  45. 10
      src/config/env.development.js
  46. 9
      src/config/env.production.js
  47. 36
      src/config/index.js
  48. 14
      src/main.js
  49. 31
      src/router/index.js
  50. 184
      src/store/dataList.js
  51. 107
      src/store/userPessionCode.js
  52. 66
      src/utils/index.js
  53. 18
      src/utils/languageService.js
  54. 129
      src/utils/request.js
  55. 18
      src/utils/scroll.js
  56. 50
      src/utils/setHeight.js
  57. 16
      src/utils/skeletonLoader.js
  58. 42
      src/utils/storage.js
  59. 57
      vite.config.js

13
.env.development

@ -0,0 +1,13 @@
# must start with VITE_
VITE_ENV = 'development'
VITE_OUTPUT_DIR = 'dev'
# public path
VITE_PUBLIC_PATH = /
#新数据接口
VITE_APP_API_BASE_URL = "http://39.101.133.168:8828/link"
# Whether to open mock
VITE_USE_MOCK = true

19
.env.production

@ -0,0 +1,19 @@
# must start with VITE_
VITE_ENV = 'production'
VITE_OUTPUT_DIR = 'dist'
# public path
VITE_PUBLIC_PATH = /AIxiaocaishen
# Whether to open mock
VITE_USE_MOCK = true
#新数据接口
VITE_APP_API_BASE_URL = https://api.homilychart.com/link
# Whether to enable gzip or brotli compression
# Optional: gzip | brotli | none
# If you need multiple forms, you can use `,` to separate
VITE_BUILD_COMPRESS = 'none'
# Whether to delete origin files when using compress, default false
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false

213
.eslintrc-auto-import.json

@ -0,0 +1,213 @@
{
"globals": {
"asyncComputed": true,
"autoResetRef": true,
"biSyncRef": true,
"computed": true,
"computedInject": true,
"controlledComputed": true,
"controlledRef": true,
"createApp": true,
"createEventHook": true,
"createGlobalState": true,
"createReactiveFn": true,
"createSharedComposable": true,
"createUnrefFn": true,
"customRef": true,
"debouncedRef": true,
"debouncedWatch": true,
"defineAsyncComponent": true,
"defineComponent": true,
"eagerComputed": true,
"effectScope": true,
"EffectScope": true,
"extendRef": true,
"getCurrentInstance": true,
"getCurrentScope": true,
"h": true,
"ignorableWatch": true,
"inject": true,
"isDefined": true,
"isReadonly": true,
"isRef": true,
"makeDestructurable": true,
"markRaw": true,
"nextTick": true,
"onActivated": true,
"onBeforeMount": true,
"onBeforeUnmount": true,
"onBeforeUpdate": true,
"onClickOutside": true,
"onDeactivated": true,
"onErrorCaptured": true,
"onKeyStroke": true,
"onLongPress": true,
"onMounted": true,
"onRenderTracked": true,
"onRenderTriggered": true,
"onScopeDispose": true,
"onServerPrefetch": true,
"onStartTyping": true,
"onUnmounted": true,
"onUpdated": true,
"pausableWatch": true,
"provide": true,
"reactify": true,
"reactifyObject": true,
"reactive": true,
"reactiveComputed": true,
"reactiveOmit": true,
"reactivePick": true,
"readonly": true,
"ref": true,
"refDefault": true,
"resolveComponent": true,
"shallowReactive": true,
"shallowReadonly": true,
"shallowRef": true,
"syncRef": true,
"templateRef": true,
"throttledRef": true,
"throttledWatch": true,
"toRaw": true,
"toReactive": true,
"toRef": true,
"toRefs": true,
"triggerRef": true,
"tryOnBeforeUnmount": true,
"tryOnMounted": true,
"tryOnScopeDispose": true,
"tryOnUnmounted": true,
"unref": true,
"unrefElement": true,
"until": true,
"useActiveElement": true,
"useAsyncQueue": true,
"useAsyncState": true,
"useAttrs": true,
"useBase64": true,
"useBattery": true,
"useBreakpoints": true,
"useBroadcastChannel": true,
"useBrowserLocation": true,
"useCached": true,
"useClamp": true,
"useClipboard": true,
"useColorMode": true,
"useConfirmDialog": true,
"useCounter": true,
"useCssModule": true,
"useCssVar": true,
"useCssVars": true,
"useCycleList": true,
"useDark": true,
"useDebounce": true,
"useDebouncedRefHistory": true,
"useDebounceFn": true,
"useDeviceMotion": true,
"useDeviceOrientation": true,
"useDevicePixelRatio": true,
"useDevicesList": true,
"useDisplayMedia": true,
"useDocumentVisibility": true,
"useDraggable": true,
"useElementBounding": true,
"useElementByPoint": true,
"useElementHover": true,
"useElementSize": true,
"useElementVisibility": true,
"useEventBus": true,
"useEventListener": true,
"useEventSource": true,
"useEyeDropper": true,
"useFavicon": true,
"useFetch": true,
"useFocus": true,
"useFocusWithin": true,
"useFps": true,
"useFullscreen": true,
"useGeolocation": true,
"useIdle": true,
"useInfiniteScroll": true,
"useIntersectionObserver": true,
"useInterval": true,
"useIntervalFn": true,
"useKeyModifier": true,
"useLastChanged": true,
"useLocalStorage": true,
"useMagicKeys": true,
"useManualRefHistory": true,
"useMediaControls": true,
"useMediaQuery": true,
"useMemoize": true,
"useMemory": true,
"useMounted": true,
"useMouse": true,
"useMouseInElement": true,
"useMousePressed": true,
"useMutationObserver": true,
"useNavigatorLanguage": true,
"useNetwork": true,
"useNow": true,
"useOffsetPagination": true,
"useOnline": true,
"usePageLeave": true,
"useParallax": true,
"usePermission": true,
"usePointer": true,
"usePointerSwipe": true,
"usePreferredColorScheme": true,
"usePreferredDark": true,
"usePreferredLanguages": true,
"useRafFn": true,
"useRefHistory": true,
"useResizeObserver": true,
"useRoute": true,
"useRouter": true,
"useScreenSafeArea": true,
"useScriptTag": true,
"useScroll": true,
"useScrollLock": true,
"useSessionStorage": true,
"useShare": true,
"useSlots": true,
"useSpeechRecognition": true,
"useSpeechSynthesis": true,
"useStorage": true,
"useStorageAsync": true,
"useStyleTag": true,
"useSwipe": true,
"useTemplateRefsList": true,
"useTextSelection": true,
"useThrottle": true,
"useThrottledRefHistory": true,
"useThrottleFn": true,
"useTimeAgo": true,
"useTimeout": true,
"useTimeoutFn": true,
"useTimestamp": true,
"useTitle": true,
"useToggle": true,
"useTransition": true,
"useUrlSearchParams": true,
"useUserMedia": true,
"useVibrate": true,
"useVirtualList": true,
"useVModel": true,
"useVModels": true,
"useWakeLock": true,
"useWebNotification": true,
"useWebSocket": true,
"useWebWorker": true,
"useWebWorkerFn": true,
"useWindowFocus": true,
"useWindowScroll": true,
"useWindowSize": true,
"watch": true,
"watchAtMost": true,
"watchEffect": true,
"watchOnce": true,
"watchWithFilter": true,
"whenever": true
}
}

24
.gitignore

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

3
.vscode/extensions.json

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}

11
README.md

@ -0,0 +1,11 @@
# Vue 3 + Vite
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
Learn more about IDE Support for Vue in the [Vue Docs Scaling up Guide](https://vuejs.org/guide/scaling-up/tooling.html#ide-support).
npm install router
npm install axios
npm install dayjs --save
npm install element-plus --save element-plus组件库
npm install @element-plus/icons-vue

43
build/utils.js

@ -0,0 +1,43 @@
import fs from 'fs'
import path from 'path'
// 移除未使用的导入
/**
* 是否是 dev 环境
* @export
* @param {string} mode
* @return {boolean}
*/
export function isDevFn(mode) {
return mode === 'development';
}
/**
* 是否是 prod 环境
* @export
* @param {string} mode
* @return {boolean}
*/
export function isProdFn(mode) {
return mode === 'production';
}
/**
* Read all environment variable configuration files to process.env
*/
export function wrapperEnv(envConf) {
const ret = {};
for (const envName of Object.keys(envConf)) {
let realName = envConf[envName].replace(/\\n/g, '\n');
realName = realName === 'true' ? true : realName === 'false' ? false : realName;
ret[envName] = realName;
if (typeof realName === 'string') {
process.env[envName] = realName;
} else if (typeof realName === 'object') {
process.env[envName] = JSON.stringify(realName);
}
}
return ret;
}

44
build/vite/build.js

@ -0,0 +1,44 @@
export function createBuild(viteEnv) {
const { VITE_OUTPUT_DIR } = viteEnv;
return {
sourcemap: false, // 是否启用
outDir: VITE_OUTPUT_DIR,
cssCodeSplit: true, // 禁用 CSS 代码拆分,将整个项目中的所有 CSS 将被提取到一个 CSS 文件中
brotliSize: false, // 关闭打包计算
target: 'esnext',
minify: 'terser', // 混淆器, terser 构建后文件体积更小, esbuild
// 小于此阈值的导入或引用资源将内联为 base64 编码,以避免额外的 http 请求。设置为 0 可以完全禁用此项
assetsInlineLimit: 4096,
chunkSizeWarningLimit: 2000, // chunk 大小警告的限制(以 kbs 为单位)
assetsDir: 'static', // 静态资源目录
// rollup 打包配置
rollupOptions: {
output: {
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: (chunkInfo) => {
if (chunkInfo.name) {
const info = chunkInfo.name.split('.');
let extType = info[info.length - 1];
if (/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/i.test(chunkInfo.name)) {
extType = 'media';
} else if (/\.(png|jpe?g|gif|svg)(\?.*)?$/.test(chunkInfo.name)) {
extType = 'images';
} else if (/\.(woff2?|eot|ttf|otf)(\?.*)?$/i.test(chunkInfo.name)) {
extType = 'fonts';
}
return `static/${extType}/[name]-[hash][extname]`;
}
return 'static/[ext]/[name]-[hash].[ext]';
}
}
},
// 压缩配置
terserOptions: {
compress: {
drop_console: false, // 生产环境移除console
drop_debugger: true // 生产环境移除debugger
}
}
};
}

26
build/vite/plugin/autoImport.js

@ -0,0 +1,26 @@
/**
* Introduces component library styles on demand.
* https://github.com/antfu/unplugin-auto-import
*/
import AutoImport from 'unplugin-auto-import/vite'
export function configAutoImportPlugin() {
return AutoImport({
include: [
/\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
/\.vue$/,
/\.vue\?vue/, // .vue
/\.md$/ // .md
],
imports: ['vue', 'vue-router', '@vueuse/core'],
// 可以选择auto-import.d.ts生成的位置,使用ts建议设置为'src/auto-import.d.ts'
dts: 'src/auto-import.d.ts',
// eslint globals Docs - https://eslint.org/docs/user-guide/configuring/language-options#specifying-globals
// 生成全局声明文件,给eslint用
eslintrc: {
enabled: true, // Default `false`
filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
}
})
}

21
build/vite/plugin/autocomponents.js

@ -0,0 +1,21 @@
/**
* Introduces component library styles on demand.
* https://github.com/antfu/unplugin-vue-components
*/
import Components from 'unplugin-vue-components/vite'
import ViteComponents, { VantResolver } from 'unplugin-vue-components/resolvers'
export function configAutoComponentsPlugin() {
return Components({
// 指定组件位置,默认是src/components
dirs: ['src/components'],
extensions: ['vue', 'tsx'],
// 配置文件生成位置
dts: 'src/components.d.ts',
// 搜索子目录
deep: true,
// 允许子目录作为组件的命名空间前缀。
directoryAsNamespace: false
// include:[]
})
}

34
build/vite/plugin/compress.js

@ -0,0 +1,34 @@
/**
* Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated
* https://github.com/anncwb/vite-plugin-compression
*/
import compressPlugin from 'vite-plugin-compression'
export function configCompressPlugin(
compress,
deleteOriginFile = false
) {
const compressList = compress.split(',')
const plugins = []
if (compressList.includes('gzip')) {
plugins.push(
compressPlugin({
ext: '.gz',
deleteOriginFile
})
)
}
if (compressList.includes('brotli')) {
plugins.push(
compressPlugin({
ext: '.br',
algorithm: 'brotliCompress',
deleteOriginFile
})
)
}
return plugins
}

37
build/vite/plugin/index.js

@ -0,0 +1,37 @@
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
// import { configMockPlugin } from './mock'
import { configAutoImportPlugin } from './autoImport'
import { configAutoComponentsPlugin } from './autocomponents'
import { configCompressPlugin } from './compress'
export function createVitePlugins(viteEnv, isBuild) {
const { VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv
const vitePlugins = [
// have to
vue(),
// have to
vueJsx({
// include: /\.(jsx|tsx)/
})
]
// unplugin-vue-components
vitePlugins.push(configAutoComponentsPlugin())
// unplugin-auto-import
vitePlugins.push(configAutoImportPlugin())
// // vite-plugin-mock
// VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild))
// The following plugins only work in the production environment
if (isBuild) {
// rollup-plugin-gzip
vitePlugins.push(
configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE)
)
}
return vitePlugins
}

19
build/vite/plugin/mock.js

@ -0,0 +1,19 @@
/**
* Mock plugin for development and production.
* https://github.com/anncwb/vite-plugin-mock
*/
// import { viteMockServe } from 'vite-plugin-mock'
// export function configMockPlugin(isBuild: boolean) {
// return viteMockServe({
// ignore: /^_/,
// mockPath: 'mock',
// localEnabled: !isBuild,
// prodEnabled: isBuild,
// injectCode: `
// import { setupProdMockServer } from '../mock/_createProductionServer';
// setupProdMockServer();
// `
// })
// }
export {}

43
build/vite/proxy.js

@ -0,0 +1,43 @@
/**
* Generate proxy
* @param list
*/
export function createProxy() {
return {
// 字符串简写写法
// '/foo': 'http://localhost:4567',
// 选项写法
// '/api': {
// target: process .env.VITE_APP_API_BASE_URL || 'http://192.168.8.93:3001',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, '')
// },
// // 全球指数
// '/hcm': {
// target: process.env.VITE_APP_API_BASE_URL_HCM || 'http://192.168.8.93:3001',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/hcm/, '')
// },
// // 时空预测
// '/pre': {
// target: process.env.VITE_APP_API_BASE_URL_AI || 'http://192.168.8.93:3001',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/pre/, '')
// }
// 正则表达式写法
// '^/fallback/.*': {
// target: 'http://jsonplaceholder.typicode.com',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/fallback/, '')
// }
// 使用 proxy 实例
// "/api": {
// target: "http://jsonplaceholder.typicode.com",
// changeOrigin: true,
// configure: (proxy, options) => {
// // proxy 是 'http-proxy' 的实例
// },
// },
}
}

18
index.html

@ -0,0 +1,18 @@
<!doctype html>
<html lang="cn">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="src/assets/img/homePage/AIicon.png">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0" /> -->
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
<title>AI小财神</title>
</head>
<body style="margin: 0px; padding: 0px;">
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

7073
package-lock.json
File diff suppressed because it is too large
View File

66
package.json

@ -0,0 +1,66 @@
{
"name": "aixiaocaishen",
"version": "0.0.0",
"scripts": {
"dev": "vite --mode development",
"test": "vite --mode test",
"prod": "vite --mode production",
"build": "vite build",
"build:test": "vite build --mode test",
"typecheck": "vue-tsc --noEmit",
"preview": "npm run build && vite preview --port 5050",
"preview:dist": "vite preview",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"lint:lint-staged": "lint-staged",
"prepare": "husky install"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@types/jszip": "^3.4.1",
"@vueuse/core": "^7.5.3",
"axios": "^0.24.0",
"dayjs": "^1.10.7",
"echarts": "^3.8.2",
"element-plus": "^2.9.6",
"fast-glob": "^3.3.3",
"mitt": "^3.0.1",
"pinia": "^2.0.9",
"pinia-plugin-persistedstate": "^1.0.3",
"reset-css": "^5.0.2",
"vconsole": "^3.15.1",
"vue": "^3.2.26",
"vue-i18n": "^10.0.3",
"vue-request": "^1.2.3",
"vue-router": "^4.0.12"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.1.0",
"@types/lodash": "^4.14.168",
"@types/mockjs": "^1.0.4",
"@types/node": "^16.18.108",
"@vitejs/plugin-vue": "^2.3.4",
"@vitejs/plugin-vue-jsx": "^1.3.3",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^10.0.0",
"autoprefixer": "^10.4.2",
"eslint": "^8.5.0",
"eslint-plugin-vue": "^8.2.0",
"husky": "^7.0.4",
"less": "^4.2.0",
"less-loader": "^12.2.0",
"lint-staged": "^12.1.7",
"mockjs": "^1.1.0",
"postcss-px-to-viewport": "^1.1.1",
"prettier": "^2.5.1",
"sass": "^1.46.0",
"typescript": "^4.9.4",
"unplugin-auto-import": "^0.5.10",
"unplugin-vue-components": "^0.17.11",
"vite": "^2.7.7",
"vite-plugin-compression": "^0.4.0",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-style-import": "^1.4.1",
"vue-global-api": "^0.4.1",
"vue-tsc": "^0.29.8"
}
}

1
public/vite.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

11
src/App.vue

@ -0,0 +1,11 @@
<script setup>
const projectRoutes = [
'/homePage'
]
</script>
<template>
<router-view></router-view>
</template>
<style scoped></style>

70
src/api/AIxiaocaishen.js

@ -0,0 +1,70 @@
import request from '../utils/request'
const APIurl = import.meta.env.VITE_APP_API_BASE_URL
//各个模块权限code接口
export const pessionAPI = function (params) {
return request({
url: `${APIurl}/api/brain/privilege`,
method: 'post',
data: new URLSearchParams(params),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
//数据接口
export const dataListAPI = function (params) {
// URLSearchParams只接受全部字符串的数据
// 将传入数据转化成字符串
const StringParams = new URLSearchParams(
Object.entries(params).map(([key, value]) => [key, String(value)])
)
return request({
url: `${APIurl}/api/brain/data`,
method: 'post',
data: StringParams,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
//统计用户行为接口
export const computedUsersAPI = function (params) {
return request({
url: `${APIurl}/BrainStatistics/getStatistic`,
method: 'post',
data: new URLSearchParams(params),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
// 获取回复接口
export const getReplyAPI = function (params) {
return request({
url: `https://api.coze.cn/v1/workflow/stream_run`,
method: 'post',
data: JSON.stringify(params),
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer pat_TJbuxUiZdl6U3oiiSeceQnHg5XdaZsWpxc6oIozc2Auhd9YuyBvFslJJQUFUym1F'
}
})
}
export const getReplyStreamAPI = function (params) {
return fetch(`https://api.coze.cn/v1/workflow/stream_run`,
{
method: 'POST',
body: JSON.stringify(params),
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer pat_TJbuxUiZdl6U3oiiSeceQnHg5XdaZsWpxc6oIozc2Auhd9YuyBvFslJJQUFUym1F'
}
}
)
}

BIN
src/assets/img/AIchat/AIgif1.gif

After

Width: 750  |  Height: 550  |  Size: 4.2 MiB

BIN
src/assets/img/AIchat/AIgif2.gif

After

Width: 750  |  Height: 550  |  Size: 5.8 MiB

BIN
src/assets/img/AIchat/AIgif3.gif

After

Width: 750  |  Height: 550  |  Size: 7.3 MiB

BIN
src/assets/img/AIchat/AIgif4.gif

After

Width: 750  |  Height: 550  |  Size: 3.5 MiB

BIN
src/assets/img/homePage/AIicon.png

After

Width: 87  |  Height: 87  |  Size: 16 KiB

BIN
src/assets/img/homePage/announcement.png

After

Width: 52  |  Height: 56  |  Size: 3.5 KiB

BIN
src/assets/img/homePage/bk.png

After

Width: 750  |  Height: 1624  |  Size: 920 KiB

BIN
src/assets/img/homePage/coin-plus.png

After

Width: 22  |  Height: 22  |  Size: 948 B

BIN
src/assets/img/homePage/coin.png

After

Width: 61  |  Height: 44  |  Size: 4.9 KiB

BIN
src/assets/img/homePage/count-box.png

After

Width: 170  |  Height: 36  |  Size: 1.1 KiB

BIN
src/assets/img/homePage/get-count-all.png

After

Width: 192  |  Height: 70  |  Size: 7.5 KiB

BIN
src/assets/img/homePage/get-count.png

After

Width: 108  |  Height: 18  |  Size: 3.1 KiB

BIN
src/assets/img/homePage/logo.png

After

Width: 196  |  Height: 50  |  Size: 11 KiB

BIN
src/assets/img/homePage/madeInHL.png

After

Width: 158  |  Height: 22  |  Size: 2.1 KiB

BIN
src/assets/img/homePage/tail/language.png

After

Width: 61  |  Height: 61  |  Size: 6.1 KiB

BIN
src/assets/img/homePage/tail/msg-box.png

After

Width: 733  |  Height: 122  |  Size: 13 KiB

BIN
src/assets/img/homePage/tail/msg.png

After

Width: 55  |  Height: 51  |  Size: 1.8 KiB

BIN
src/assets/img/homePage/tail/send.png

After

Width: 61  |  Height: 61  |  Size: 2.5 KiB

BIN
src/assets/img/homePage/tail/think-active.png

After

Width: 240  |  Height: 61  |  Size: 20 KiB

BIN
src/assets/img/homePage/tail/think-no-active.png

After

Width: 240  |  Height: 61  |  Size: 8.0 KiB

BIN
src/assets/img/homePage/tail/voice.png

After

Width: 61  |  Height: 61  |  Size: 5.7 KiB

1
src/assets/vue.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

214
src/auto-import.d.ts

@ -0,0 +1,214 @@
// Generated by 'unplugin-auto-import'
// We suggest you to commit this file into source control
declare global {
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const biSyncRef: typeof import('@vueuse/core')['biSyncRef']
const computed: typeof import('vue')['computed']
const computedInject: typeof import('@vueuse/core')['computedInject']
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
const controlledRef: typeof import('@vueuse/core')['controlledRef']
const createApp: typeof import('vue')['createApp']
const createEventHook: typeof import('@vueuse/core')['createEventHook']
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
const customRef: typeof import('vue')['customRef']
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const EffectScope: typeof import('vue')['EffectScope']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const isDefined: typeof import('@vueuse/core')['isDefined']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
const onLongPress: typeof import('@vueuse/core')['onLongPress']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const reactify: typeof import('@vueuse/core')['reactify']
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
const reactive: typeof import('vue')['reactive']
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
const reactivePick: typeof import('@vueuse/core')['reactivePick']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const refDefault: typeof import('@vueuse/core')['refDefault']
const resolveComponent: typeof import('vue')['resolveComponent']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const syncRef: typeof import('@vueuse/core')['syncRef']
const templateRef: typeof import('@vueuse/core')['templateRef']
const throttledRef: typeof import('@vueuse/core')['throttledRef']
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
const toRaw: typeof import('vue')['toRaw']
const toReactive: typeof import('@vueuse/core')['toReactive']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const triggerRef: typeof import('vue')['triggerRef']
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
const unref: typeof import('vue')['unref']
const unrefElement: typeof import('@vueuse/core')['unrefElement']
const until: typeof import('@vueuse/core')['until']
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
const useCached: typeof import('@vueuse/core')['useCached']
const useClamp: typeof import('@vueuse/core')['useClamp']
const useClipboard: typeof import('@vueuse/core')['useClipboard']
const useColorMode: typeof import('@vueuse/core')['useColorMode']
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
const useCounter: typeof import('@vueuse/core')['useCounter']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVar: typeof import('@vueuse/core')['useCssVar']
const useCssVars: typeof import('vue')['useCssVars']
const useCycleList: typeof import('@vueuse/core')['useCycleList']
const useDark: typeof import('@vueuse/core')['useDark']
const useDebounce: typeof import('@vueuse/core')['useDebounce']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
const useElementSize: typeof import('@vueuse/core')['useElementSize']
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
const useEventBus: typeof import('@vueuse/core')['useEventBus']
const useEventListener: typeof import('@vueuse/core')['useEventListener']
const useEventSource: typeof import('@vueuse/core')['useEventSource']
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
const useFavicon: typeof import('@vueuse/core')['useFavicon']
const useFetch: typeof import('@vueuse/core')['useFetch']
const useFocus: typeof import('@vueuse/core')['useFocus']
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
const useFps: typeof import('@vueuse/core')['useFps']
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
const useMemoize: typeof import('@vueuse/core')['useMemoize']
const useMemory: typeof import('@vueuse/core')['useMemory']
const useMounted: typeof import('@vueuse/core')['useMounted']
const useMouse: typeof import('@vueuse/core')['useMouse']
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
const useNetwork: typeof import('@vueuse/core')['useNetwork']
const useNow: typeof import('@vueuse/core')['useNow']
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
const useParallax: typeof import('@vueuse/core')['useParallax']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
const useScroll: typeof import('@vueuse/core')['useScroll']
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
const useShare: typeof import('@vueuse/core')['useShare']
const useSlots: typeof import('vue')['useSlots']
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
const useStorage: typeof import('@vueuse/core')['useStorage']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
const useThrottle: typeof import('@vueuse/core')['useThrottle']
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
const useTimeout: typeof import('@vueuse/core')['useTimeout']
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
const useTitle: typeof import('@vueuse/core')['useTitle']
const useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
const watch: typeof import('vue')['watch']
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
const watchEffect: typeof import('vue')['watchEffect']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}
export {}

11
src/components.d.ts

@ -0,0 +1,11 @@
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/vue-next/pull/3399
declare module 'vue' {
export interface GlobalComponents {
HelloWorld: typeof import('./components/HelloWorld.vue')['default']
}
}
export { }

10
src/config/env.development.js

@ -0,0 +1,10 @@
// 本地环境配置
export default {
env: 'development',
title: '开发',
baseUrl: '', // 项目地址
// baseApi: 'http://39.101.133.168:8828/link', // 本地api请求地址,如果使用了代理,设置成'/'
baseApi: '', // 使用了代理设置成'/'
APPSECRET: 'xxx',
$cdn: 'https://imgs.solui.cn'
}

9
src/config/env.production.js

@ -0,0 +1,9 @@
// 正式
export default {
env: 'production',
title: '生产',
baseUrl: '', // 正式项目地址
baseApi: 'https://api.homilychart.com/scms/api', // 正式api请求地址
APPSECRET: 'xxx',
$cdn: 'https://imgs.solui.cn'
}

36
src/config/index.js

@ -0,0 +1,36 @@
// 定义配置对象结构
const IConfig = {
env: '', // 开发环境
title: '', // 项目title
baseUrl: '', // 项目地址
baseApi: '', // api请求地址
$cdn: '' // cdn公共资源路径
};
const envMap = {}; // 存储不同环境下的配置文件
// import.meta.globEager 批量导入指定目录下的模块-------导入所有的js文件(路径:模块内容)
const globalModules = import.meta.globEager('./*.js', { eager: true });
console.log('已加载所有环境模块:', globalModules)
Object.entries(globalModules).forEach(([key, value]) => {
// key.match(/\.\/env\.(\S*)\.ts/)
const name = key.replace(/\.\/env\.(.*)\.js$/, '$1'); // 解析出环境名称
envMap[name] = value; // 模块的内容
});
// 检查环境变量是否存在
if (!import.meta.env.VITE_ENV) {
console.error('VITE_ENV 环境变量未定义,请检查配置。');
}
// 根据环境引入不同配置
const config = envMap[import.meta.env.VITE_ENV] ? envMap[import.meta.env.VITE_ENV].default : null;
if (!config) {
console.error(`未找到对应 ${import.meta.env.VITE_ENV} 环境的配置文件,请检查。`);
}
console.log('根据环境引入不同配置', config);
export { config };

14
src/main.js

@ -0,0 +1,14 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import 'reset-css';
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(router)
app.use(ElementPlus)
app.mount('#app')

31
src/router/index.js

@ -0,0 +1,31 @@
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
redirect: 'homePage'
},
{
path: '/homePage',
name: 'homePage',
component: () => import('@/views/homePage.vue')
},
{
path: '/AIchat',
name: 'AIchat',
component: () => import('@/views/AIchat.vue'),
meta: { title: 'AI对话' }
},
{
path: '/AIfind',
name: 'AIfind',
component: () => import('@/views/AIfind.vue'),
meta: { title: '发现' }
},
]
// 创建路由实例
const router = createRouter({
history: createWebHistory(import.meta.env.VITE_PUBLIC_PATH),
routes
})
// 导出
export default router

184
src/store/dataList.js

@ -0,0 +1,184 @@
import { defineStore } from 'pinia'
import { ref, watch } from 'vue'
import { useUserStore } from './userPessionCode'
import { useLanguage } from '@/utils/languageService'
import { dataListAPI } from '@/api/sword'
// import { useSkeletonStore } from '@/utils/skeletonLoader'
import { useRoute } from 'vue-router'
// const skeletonStore = useSkeletonStore()
const { t } = useLanguage()
export const useDataStore = defineStore('data', () => {
const route = useRoute()
console.log(route, '地址栏携带的参数。。。。。。')
const userStore = useUserStore()
const brainDataList = ref(null)
const swordDataList = ref(null)
const priceDataList = ref(null)
const timeDataList = ref(null)
const showALLData = ref(null)
const HomePage = ref(null)
const AIBull = ref(null)
const AIGoldBull = ref(null)
const AIRadar = ref(null)
const loading = ref(false)
const getQueryVariable = (variable) => {
const query = window.location.search.substring(1)
const vars = query.split('&')
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split('=')
if (pair[0] === variable) {
return pair[1]
}
}
return ''
}
// 使用示例,获取地址栏参数
// const token = ref(getQueryVariable('token'))
// const market = ref(getQueryVariable('market'))
// const code = ref(getQueryVariable('code'))
// console.log(token.value) // 输出 token 的值,例如 "111"
const fetchChartData = async () => {
const getTokenString = String(localStorage.getItem('localToken'))
const getMarketString = String(localStorage.getItem('localMarket'))
const getCodeString = String(localStorage.getItem('localCode'))
// const getMarket = String()
try {
const res = await dataListAPI({
token: getTokenString || '',
market: getMarket() || getMarketString || 'gb',
code: getQueryVariable('code') || getCodeString || 'NDX',
language: t.value.suoxie,
brainPrivilegeState: userStore.brainPerssion,
swordPrivilegeState: userStore.swordPerssion,
stockForecastPrivilegeState: userStore.pricePerssion,
spaceForecastPrivilegeState: userStore.timePerssion,
aibullPrivilegeState: userStore.aibullPerssion,
aigoldBullPrivilegeState: userStore.aiGnbullPerssion,
airadarPrivilegeState: userStore.airadarPerssion,
marketList: userStore.aiGoldMarketList
})
brainDataList.value = res.data.Brain
swordDataList.value = res.data.Sword
priceDataList.value = res.data.StockForecast
timeDataList.value = res.data.SpaceForecast
showALLData.value = res.data.ShowAll
HomePage.value = res.data.HomePage
AIBull.value = res.data.AIBull
AIGoldBull.value = res.data.AIGoldBull
AIRadar.value = res.data.AIRadar
} catch (error) {
console.error('获取图表数据出错:', error)
} finally {
loading.value = false
console.log('数据获取过程结束')
}
}
// 获取路径上market的值
const getMarket = () => {
let market = ''
const queryMarket = getQueryVariable('market')
if (queryMarket) {
if (['sg', 'my', 'in', 'hk', 'th', 'vi', 'usa', 'can', 'gb', 'cn'].includes(queryMarket)) {
return queryMarket
} else {
switch (queryMarket) {
case 'SGX': return 'sg'
case 'BMB': return 'my'
case 'IDX': return 'in'
case 'HKEX': return 'hk'
case 'SET': return 'th'
case 'HN': return 'vi'
case 'HONSE': return 'vi'
case 'AMERA': return 'usa'
case 'NYSE': return 'usa'
case 'NASDAQ': return 'usa'
case 'DLD': return 'can'
case 'DLDCY': return 'can'
case 'GINDEX': return 'gb'
case 'BZ': return 'cn'
case 'SH': return 'cn'
case 'SZ': return 'cn'
default: return '无市场数据'
}
}
}
return market
}
const isLoading = ref(true)
const initData = async () => {
isLoading.value = true
try {
} catch (error) {
console.error('Error loading data:', error)
} finally {
isLoading.value = false
}
}
watch(
() => [userStore.isReady, t.value?.suoxie],
([isReady, language]) => {
console.log('isReady 或 language 变化:', { isReady, language })
if (isReady) {
// // 在组件挂载时显示骨架屏
// skeletonStore.startLoading()
setTimeout(() => {
fetchChartData()
}, 500) // 重新发起 API 请求
}
},
{ immediate: true, deep: true }
),
// watchEffect(() => {
// const isReady = userStore.isReady;
// const getCodeString1 = ref(localStorage.getItem('localCode'));
// const getMarketString1 = ref(localStorage.getItem('localMarket'));
// console.log({isReady, getCodeString1, getMarketString1}, '监听变化');
// if (isReady && getCodeString1.value && getMarketString1.value) {
// console.log('条件满足,发起 API 请求');
// skeletonStore.startLoading(); // 显示骨架屏
// fetchChartData(); // 发起 API 请求
// }
// }),
watch(
() => route.query,
(newQuery, oldQuery) => {
if (newQuery.market || newQuery.code) {
fetchChartData()
}
}
),
watch(
() => userStore.aibullPerssion,
(newValue) => {
if (newValue === 1) {
fetchChartData()
}
}
)
initData()
return {
brainDataList,
swordDataList,
priceDataList,
timeDataList,
showALLData,
HomePage,
AIBull,
AIGoldBull,
loading,
AIRadar,
fetchChartData,
initData,
getMarket,
getQueryVariable
}
})

107
src/store/userPessionCode.js

@ -0,0 +1,107 @@
import { defineStore } from 'pinia'
import { ref, onMounted } from 'vue'
import { pessionAPI } from '@/api/sword'
// import VConsole from 'vconsole'
import { useAppBridge } from '@/assets/js/useAppBridge.js'
// const vConsole = new VConsole()
export const useUserStore = defineStore('user', () => {
const brainPerssion = ref(0)
const swordPerssion = ref(0)
const pricePerssion = ref(0)
const timePerssion = ref(0)
const aibullPerssion = ref(0)
const aiGnbullPerssion = ref(0)
const aiGoldMarketList = ref([])
const airadarPerssion = ref(0)
const userRole = ref('')
const loading = ref(false)
const isReady = ref(false)
const getAppToken = ref('')
const getQueryVariable = (variable) => {
const query = window.location.search.substring(1)
const vars = query.split('&')
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split('=')
if (pair[0] === variable) {
return pair[1]
}
}
return ''
}
const fetchUserInfo = async () => {
// const getTokenString = localStorage.getItem('localToken')
// ? String(localStorage.getItem('localToken'))
// : '' // 存储token
// const getRouteString = decodeURIComponent(String(getQueryVariable('token'))) // 地址栏的token
// mock没有token
// const getTokenString = ''
// const getRouteString = '' // 地址栏的token
// useAppBridge().packageFun(
// 'JWgetStorage',
// (response) => {
// const res = JSON.parse(response) // 解析返回的结果
// getAppToken.value = res.data
// console.log('获取到的 token权限:', getAppToken.value) // 这里是你获取到的 token
// },
// 5,
// {
// key: 'token'
// }
// )
getAppToken.value = localStorage.getItem('localToken')
? String(localStorage.getItem('localToken'))
: ''
loading.value = true
try {
const requestParams = {
...{ token: getAppToken.value || '' }
}
const res = await pessionAPI(requestParams)
// 更新状态
brainPerssion.value = res.data.brainExpireStatus
swordPerssion.value = res.data.swordExpireStatus
pricePerssion.value = res.data.stockForecastExpireStatus
timePerssion.value = res.data.spaceForecastExpireStatus
aibullPerssion.value = res.data.aibullExpireStatus
aiGnbullPerssion.value = res.data.aigoldBullExpireStatus
airadarPerssion.value = res.data.airadarExpireStatus
aiGoldMarketList.value = res.data.marketList
userRole.value = res.data.userRole
isReady.value = true
} catch (err) {
console.error('Error fetching user data:', err)
} finally {
loading.value = false
}
}
const init = () => {
if (!isReady.value) {
fetchUserInfo()
}
}
onMounted(() => {
init()
})
return {
brainPerssion,
swordPerssion,
pricePerssion,
timePerssion,
aibullPerssion,
aiGnbullPerssion,
airadarPerssion,
aiGoldMarketList,
userRole,
loading,
isReady,
init,
fetchUserInfo
}
})

66
src/utils/index.js

@ -0,0 +1,66 @@
import { config } from '@/config'
/**
* 动态设置浏览器标题
* @param title
*/
export const setDocumentTitle = (title) => {
document.title = title || config.title;
};
/**
* 处理await成功失败信息
* 参考https://juejin.cn/post/6844903767129718791
* @param {*} promise
*/
export function awaitWrap(promise) {
return promise
.then((data) => [null, data])
.catch((err) => [err, null]);
}
/*
* 第一种方法
* @param paramName
* 用来获取url中的某个参数
*/
export const getQueryParamByKey = (paramName) => {
let url = document.location.toString();
// 如果url中有特殊字符则需要进行一下解码
url = decodeURI(url);
const arrObj = url.split('?');
if (arrObj.length > 1) {
const arrPara = arrObj[1].split('&');
let arr;
for (let i = 0; i < arrPara.length; i++) {
arr = arrPara[i].split('=');
if (arr != null && arr[0] == paramName) {
return decodeURIComponent(arr[1]);
}
}
return '';
} else {
return '';
}
};
/*
* 用来获取url中的所有参数
* let url = 'http://192.168.1.122:9020/?appId=wxf4b72971eacba4d6&loginScene=1#/'
*/
export const getQueryParams = (url = document.location.toString()) => {
// 如果url中有特殊字符则需要进行一下解码
url = decodeURI(url);
const arr1 = url.split('?');
const obj = {};
if (arr1.length > 1) {
const index = arr1[1].indexOf('#');
arr1[1] = index == -1 ? arr1[1] : arr1[1].slice(0, index);
const arr2 = arr1[1].split('&');
for (let i = 0; i < arr2.length; i++) {
const curArr = arr2[i].split('=');
obj[curArr[0]] = decodeURIComponent(curArr[1]);
}
}
return obj;
};

18
src/utils/languageService.js

@ -0,0 +1,18 @@
import { ref, computed } from 'vue'
import { t, changeLanguage, availableLanguages, languagePacks } from '../lang/index'
export const useLanguage = () => {
const translate = computed(() => (key) => {
return t.value && key in t.value ? t.value[key] : key
})
const currentLanguage = computed(() => t.value?.language || '简体中文')
return {
t,
translate,
changeLanguage,
availableLanguages,
languagePacks,
currentLanguage
}
}

129
src/utils/request.js

@ -0,0 +1,129 @@
import axios from 'axios'
import { ElMessage } from 'element-plus'
import { config } from '@/config'
const ERROR_MESSAGES = {
badRequest: '请求错误(400)',
unauthorized: '未授权,请登录(401)',
forbidden: '拒绝访问(403)',
notFound: `请求地址出错: ${'[具体 URL 将在这里被替换]'}`,
methodNotAllowed: '请求方法未允许(405)',
requestTimeout: '请求超时(408)',
internalServerError: '服务器内部错误(500)',
notImplemented: '服务未实现(501)',
badGateway: '网络错误(502)',
serviceUnavailable: '服务不可用(503)',
gatewayTimeout: '网络超时(504)',
httpVersionNotSupported: 'HTTP 版本不受支持(505)',
defaultConnectionError: '连接错误: [原始错误消息]',
networkError: '网络异常,请检查后重试!',
serverFailure: '连接到服务器失败,请联系管理员'
}
const service = axios.create({
baseURL: '', // url = base url + request url+
timeout: 5000,
withCredentials: false // send cookies when cross-domain requests
// headers: {
// // clear cors
// 'Cache-Control': 'no-cache',
// Pragma: 'no-cache'
// }
})
const setErrorMsg = (error) => {
if (error && error.response) {
switch (error.response.status) {
case 400:
error.message = ERROR_MESSAGES.badRequest
break
case 401:
error.message = ERROR_MESSAGES.unauthorized
break
case 403:
error.message = ERROR_MESSAGES.forbidden
break
case 404:
error.message = ERROR_MESSAGES.notFound.replace(
'[具体 URL 将在这里被替换]',
error.response.config.url
)
break
case 405:
error.message = ERROR_MESSAGES.methodNotAllowed
break
case 408:
error.message = ERROR_MESSAGES.requestTimeout
break
case 500:
error.message = ERROR_MESSAGES.internalServerError
break
case 501:
error.message = ERROR_MESSAGES.notImplemented
break
case 502:
error.message = ERROR_MESSAGES.badGateway
break
case 503:
error.message = ERROR_MESSAGES.serviceUnavailable
break
case 504:
error.message = ERROR_MESSAGES.gatewayTimeout
break
case 505:
error.message = ERROR_MESSAGES.httpVersionNotSupported
break
default:
error.message = ERROR_MESSAGES.defaultConnectionError.replace(
'[原始错误消息]',
error.message
)
}
} else {
if (error.message === 'Network Error') {
error.message = ERROR_MESSAGES.networkError
} else {
error.message = ERROR_MESSAGES.serverFailure
}
}
return error.message
}
// Request interceptors
service.interceptors.request.use(
(config) => {
// 在此处添加请求头等,如添加 token
// if (store.state.token) {
// config.headers['Authorization'] = `Bearer ${store.state.token}`
// }
return config
},
(error) => {
return Promise.reject(error)
}
)
// Response interceptors
service.interceptors.response.use(
async (response) => {
// await new Promise(resovle => setTimeout(resovle, 3000));
// if (response.config.loadingInstance) {
// response.config.loadingInstance.close();
// }
const res = response.data
if (res.code !== 200) {
const errorMsg = res.msg || 'Unkonw error'
ElMessage.error(errorMsg)
// return Promise.reject(new Error(res.msg || 'Error'))
} else {
return response.data
}
},
(error) => {
const errorMessage = setErrorMsg(error)
ElMessage.error(errorMessage)
return Promise.reject(error)
}
)
export default service

18
src/utils/scroll.js

@ -0,0 +1,18 @@
export function getWindowScrollTop(win) {
let scrollTop = 0
// 获取父窗口滚动偏移
if (win.document.documentElement && win.document.documentElement.scrollTop) {
scrollTop = win.document.documentElement.scrollTop
} else if (win.document.body) {
scrollTop = win.document.body.scrollTop
}
// 如果嵌套在 iframe 中,计算 iframe 的位置
if (win.frameElement) {
const iframeRect = win.frameElement.getBoundingClientRect()
scrollTop += iframeRect.top // 加上 iframe 在父窗口中的偏移
}
return scrollTop
}

50
src/utils/setHeight.js

@ -0,0 +1,50 @@
// export default {
// install(app: App) {
// // 注册功能根据app参数
// app.mixin({
// // 引入全局使用
// mounted() {
// setTimeout(() => {
// console.log('Sending height message')
// // console.log((this.$el as HTMLElement).offsetHeight);
// ;(this.$el as HTMLElement).offsetHeight
// window.parent.postMessage(
// // 向父窗口发送消息
// {
// data: {
// type: 'duobaoqibingHeight',
// data: (this.$el as HTMLElement).offsetHeight // 发送当前高度
// }
// },
// '*'
// )
// }, 800)
// }
// })
// }
// }
// 给父级发送高度
export const setHeight = (el) => {
const sendHeight = () => {
const height = el.offsetHeight;
// 打印高度到控制台
console.log('Current height:', height);
window.parent.postMessage(
{
data: {
type: 'duobaoqibingHeight',
data: el.offsetHeight
}
},
'*'
);
// 滚动到顶部
window.scrollTo({ top: 0, behavior: 'smooth' });
};
console.log(el.offsetHeight);
// 初始发送高度
setTimeout(sendHeight, 800);
};

16
src/utils/skeletonLoader.js

@ -0,0 +1,16 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useSkeletonStore = defineStore('skeleton', () => {
const isLoading = ref(false)
function startLoading() {
isLoading.value = true
}
function endLoading() {
isLoading.value = false
}
return { isLoading, startLoading, endLoading }
})

42
src/utils/storage.js

@ -0,0 +1,42 @@
/**
* 封装操作localstorage本地存储的方法
*/
export const storage = {
//存储
set(key, value) {
localStorage.setItem(key, JSON.stringify(value))
},
//取出数据
get(key) {
const value = localStorage.getItem(key)
if (value && value != 'undefined' && value != 'null') {
return JSON.parse(value)
}
},
// 删除数据
remove(key) {
localStorage.removeItem(key)
}
}
/**
* 封装操作sessionStorage本地存储的方法
*/
export const sessionStorage = {
//存储
set(key, value) {
window.sessionStorage.setItem(key, JSON.stringify(value))
},
//取出数据
get(key) {
const value = window.sessionStorage.getItem(key)
if (value && value != 'undefined' && value != 'null') {
return JSON.parse(value)
}
return null
},
// 删除数据
remove(key) {
window.sessionStorage.removeItem(key)
}
}

57
vite.config.js

@ -0,0 +1,57 @@
import { defineConfig, loadEnv } from 'vite'
import pkg from './package.json' // 新增包信息导入
import dayjs from 'dayjs' // 新增时间库导入
import { fileURLToPath, URL } from 'url' // 新增路径处理模块
import { wrapperEnv } from './build/utils'
import { createVitePlugins } from './build/vite/plugin'
import { createProxy } from './build/vite/proxy'
import { createBuild } from './build/vite/build'
const { dependencies, devDependencies, name, version } = pkg
// 应用信息
const __APP_INFO__ = {
pkg: { dependencies, devDependencies, name, version },
lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
}
// https://vite.dev/config/
export default defineConfig(({ command, mode }) => {
// console.log('command', command)
const root = process.cwd() // 当前工作目录
const isBuild = command === 'build' // 是否是构建 serve
const env = loadEnv(mode, root) // 加载env环境
// The boolean type read by loadEnv is a string. This function can be converted to boolean type
const viteEnv = wrapperEnv(env)
// console.log('viteEnv', viteEnv)
const { VITE_PUBLIC_PATH, VITE_OUTPUT_DIR } = viteEnv
return {
base: VITE_PUBLIC_PATH,
root,
plugins: createVitePlugins(viteEnv, isBuild),
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
css: {
preprocessorOptions: {
scss: {
charset: false, // 避免出现: build时的 @charset 必须在第一行的警告
additionalData: `
@import "@/styles/mixin.scss";
@import "@/styles/variables.scss";
`
}
}
},
server: {
host: true,
proxy: createProxy()
},
build: createBuild(viteEnv),
define: {
__APP_INFO__: JSON.stringify(__APP_INFO__)
}
}
})
Loading…
Cancel
Save