Showing
69 changed files
with
2795 additions
and
0 deletions
.env
0 → 100644
.env.development
0 → 100644
.env.production
0 → 100644
.eslintrc-auto-import.json
0 → 100644
| 1 | +{ | ||
| 2 | + "globals": { | ||
| 3 | + "Component": true, | ||
| 4 | + "ComponentPublicInstance": true, | ||
| 5 | + "ComputedRef": true, | ||
| 6 | + "EffectScope": true, | ||
| 7 | + "ExtractDefaultPropTypes": true, | ||
| 8 | + "ExtractPropTypes": true, | ||
| 9 | + "ExtractPublicPropTypes": true, | ||
| 10 | + "InjectionKey": true, | ||
| 11 | + "PropType": true, | ||
| 12 | + "Ref": true, | ||
| 13 | + "VNode": true, | ||
| 14 | + "WritableComputedRef": true, | ||
| 15 | + "computed": true, | ||
| 16 | + "createApp": true, | ||
| 17 | + "customRef": true, | ||
| 18 | + "defineAsyncComponent": true, | ||
| 19 | + "defineComponent": true, | ||
| 20 | + "effectScope": true, | ||
| 21 | + "getCurrentInstance": true, | ||
| 22 | + "getCurrentScope": true, | ||
| 23 | + "h": true, | ||
| 24 | + "inject": true, | ||
| 25 | + "isProxy": true, | ||
| 26 | + "isReactive": true, | ||
| 27 | + "isReadonly": true, | ||
| 28 | + "isRef": true, | ||
| 29 | + "markRaw": true, | ||
| 30 | + "nextTick": true, | ||
| 31 | + "onActivated": true, | ||
| 32 | + "onBeforeMount": true, | ||
| 33 | + "onBeforeRouteLeave": true, | ||
| 34 | + "onBeforeRouteUpdate": true, | ||
| 35 | + "onBeforeUnmount": true, | ||
| 36 | + "onBeforeUpdate": true, | ||
| 37 | + "onDeactivated": true, | ||
| 38 | + "onErrorCaptured": true, | ||
| 39 | + "onMounted": true, | ||
| 40 | + "onRenderTracked": true, | ||
| 41 | + "onRenderTriggered": true, | ||
| 42 | + "onScopeDispose": true, | ||
| 43 | + "onServerPrefetch": true, | ||
| 44 | + "onUnmounted": true, | ||
| 45 | + "onUpdated": true, | ||
| 46 | + "provide": true, | ||
| 47 | + "reactive": true, | ||
| 48 | + "readonly": true, | ||
| 49 | + "ref": true, | ||
| 50 | + "resolveComponent": true, | ||
| 51 | + "shallowReactive": true, | ||
| 52 | + "shallowReadonly": true, | ||
| 53 | + "shallowRef": true, | ||
| 54 | + "toRaw": true, | ||
| 55 | + "toRef": true, | ||
| 56 | + "toRefs": true, | ||
| 57 | + "toValue": true, | ||
| 58 | + "triggerRef": true, | ||
| 59 | + "unref": true, | ||
| 60 | + "useAttrs": true, | ||
| 61 | + "useCssModule": true, | ||
| 62 | + "useCssVars": true, | ||
| 63 | + "useLink": true, | ||
| 64 | + "useRoute": true, | ||
| 65 | + "useRouter": true, | ||
| 66 | + "useSlots": true, | ||
| 67 | + "watch": true, | ||
| 68 | + "watchEffect": true, | ||
| 69 | + "watchPostEffect": true, | ||
| 70 | + "watchSyncEffect": true | ||
| 71 | + } | ||
| 72 | +} |
.gitignore
0 → 100644
build/proxy.js
0 → 100644
counter.js
0 → 100644
index.html
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2022-07-25 11:01:23 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-07-08 17:49:15 | ||
| 5 | + * @FilePath: /my-data-summary/index.html | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<!DOCTYPE html> | ||
| 9 | +<html lang="en"> | ||
| 10 | + <head> | ||
| 11 | + <meta charset="UTF-8" /> | ||
| 12 | + <link rel="icon" type="image/svg+xml" href="http://www.wxgzjs.cn/template/default/static/images/favicon.ico" /> | ||
| 13 | + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
| 14 | + <title>数据汇总</title> | ||
| 15 | + </head> | ||
| 16 | + <body> | ||
| 17 | + <div id="app"></div> | ||
| 18 | + <script type="module" src="/src/main.js"></script> | ||
| 19 | + </body> | ||
| 20 | +</html> |
javascript.svg
0 → 100644
| 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="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path fill="#F7DF1E" d="M0 0h256v256H0V0Z"></path><path d="m67.312 213.932l19.59-11.856c3.78 6.701 7.218 12.371 15.465 12.371c7.905 0 12.89-3.092 12.89-15.12v-81.798h24.057v82.138c0 24.917-14.606 36.259-35.916 36.259c-19.245 0-30.416-9.967-36.087-21.996m85.07-2.576l19.588-11.341c5.157 8.421 11.859 14.607 23.715 14.607c9.969 0 16.325-4.984 16.325-11.858c0-8.248-6.53-11.17-17.528-15.98l-6.013-2.58c-17.357-7.387-28.87-16.667-28.87-36.257c0-18.044 13.747-31.792 35.228-31.792c15.294 0 26.292 5.328 34.196 19.247l-18.732 12.03c-4.125-7.389-8.591-10.31-15.465-10.31c-7.046 0-11.514 4.468-11.514 10.31c0 7.217 4.468 10.14 14.778 14.608l6.014 2.577c20.45 8.765 31.963 17.7 31.963 37.804c0 21.654-17.012 33.51-39.867 33.51c-22.339 0-36.774-10.654-43.819-24.574"></path></svg> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
package-lock.json
0 → 100644
This diff could not be displayed because it is too large.
package.json
0 → 100644
| 1 | +{ | ||
| 2 | + "name": "vue3-vite", | ||
| 3 | + "private": true, | ||
| 4 | + "version": "0.0.0", | ||
| 5 | + "scripts": { | ||
| 6 | + "dev": "vite", | ||
| 7 | + "build": "vite build", | ||
| 8 | + "preview": "vite preview", | ||
| 9 | + "tar": "tar -czvpf dist.tar.gz custom_dashboard", | ||
| 10 | + "build_tar": "npm run build && npm run tar", | ||
| 11 | + "scp-oa": "scp dist.tar.gz itomix@ipadbiz.cn:/opt/oa/f/", | ||
| 12 | + "dec-oa": "ssh itomix@ipadbiz.cn 'cd /opt/oa/f/ && tar -xzvf dist.tar.gz && rm -rf dist.tar.gz'", | ||
| 13 | + "scp-dev": "scp dist.tar.gz itomix@ipadbiz.cn:/opt/space-dev/admin/", | ||
| 14 | + "dec-dev": "ssh itomix@ipadbiz.cn 'cd /opt/space-dev/admin/ && tar -xzvf dist.tar.gz && rm -rf dist.tar.gz'", | ||
| 15 | + "remove_tar": "rm -rf dist.tar.gz", | ||
| 16 | + "oa_upload": "npm run build_tar && npm run scp-oa && npm run dec-oa && npm run remove_tar", | ||
| 17 | + "dev_upload": "npm run build_tar && npm run scp-dev && npm run dec-dev && npm run remove_tar" | ||
| 18 | + }, | ||
| 19 | + "devDependencies": { | ||
| 20 | + "@vitejs/plugin-legacy": "^2.0.0", | ||
| 21 | + "@vitejs/plugin-vue": "^5.0.5", | ||
| 22 | + "code-inspector-plugin": "^0.9.2", | ||
| 23 | + "swiper": "^5.4.5", | ||
| 24 | + "unplugin-auto-import": "^0.17.6", | ||
| 25 | + "unplugin-vue-define-options": "^1.4.5", | ||
| 26 | + "vite": "^3.0.0", | ||
| 27 | + "vite-plugin-dynamic-import": "^1.0.0", | ||
| 28 | + "vite-plugin-style-import": "1.4.1", | ||
| 29 | + "vite-plugin-vue2": "^2.0.2", | ||
| 30 | + "vue-awesome-swiper": "^4.1.1" | ||
| 31 | + }, | ||
| 32 | + "dependencies": { | ||
| 33 | + "@fortawesome/free-brands-svg-icons": "^6.5.2", | ||
| 34 | + "@fortawesome/free-regular-svg-icons": "^6.5.2", | ||
| 35 | + "@fortawesome/free-solid-svg-icons": "^6.5.2", | ||
| 36 | + "@fortawesome/vue-fontawesome": "^2.0.10", | ||
| 37 | + "axios": "^0.27.2", | ||
| 38 | + "dayjs": "^1.11.4", | ||
| 39 | + "echarts": "^5.5.0", | ||
| 40 | + "element-plus": "^2.7.6", | ||
| 41 | + "element-ui": "^2.15.14", | ||
| 42 | + "floating-vue": "^1.0.0-beta.19", | ||
| 43 | + "jquery": "^3.6.0", | ||
| 44 | + "js-cookie": "^3.0.1", | ||
| 45 | + "less": "^4.1.3", | ||
| 46 | + "lodash": "^4.17.21", | ||
| 47 | + "moment": "^2.29.4", | ||
| 48 | + "mui-player": "^1.6.1", | ||
| 49 | + "pinia": "^2.1.7", | ||
| 50 | + "uuid": "^9.0.1", | ||
| 51 | + "vant": "^2.12.48", | ||
| 52 | + "vue": "^3.4.31", | ||
| 53 | + "vue-grid-layout": "^2.4.0", | ||
| 54 | + "vue-router": "^4.4.0", | ||
| 55 | + "vue-template-compiler": "^2.7.16", | ||
| 56 | + "vuex": "3.6.2", | ||
| 57 | + "vxe-table": "^3.7.9", | ||
| 58 | + "xe-utils": "^3.5.22" | ||
| 59 | + } | ||
| 60 | +} |
public/vite.svg
0 → 100644
| 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> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
publish.sh
0 → 100644
| 1 | +#!/usr/bin/env sh | ||
| 2 | +# ----------------------------------------------- | ||
| 3 | +# Filename: publish.sh | ||
| 4 | +# Revision: 1.0 | ||
| 5 | +# Date: 2022年8月05日 | ||
| 6 | +# Author: Hooke | ||
| 7 | +# Description: **** 根据php项目相应特征书写项目发布流程 | ||
| 8 | +# ----------------------------------------------- | ||
| 9 | + | ||
| 10 | +# 当发生错误时中止脚本 | ||
| 11 | +set -e | ||
| 12 | + | ||
| 13 | +# 本地Git服务器目录路径 | ||
| 14 | +path=/Users/huyirui/program/itomix/git/isp/f/guanzong | ||
| 15 | + | ||
| 16 | +# 编译输出文件夹 | ||
| 17 | +output=web | ||
| 18 | + | ||
| 19 | +# 打包 | ||
| 20 | +npm run build | ||
| 21 | + | ||
| 22 | +# 移除Git服务器目录下项目文件夹 | ||
| 23 | +rm -r $path"/${output:?}" | ||
| 24 | + | ||
| 25 | +# 把本地编译输出文件夹添加到服务器目录 | ||
| 26 | +mv "${output:?}/" $path | ||
| 27 | + | ||
| 28 | +# 提交到Git服务器 | ||
| 29 | +cd $path"/${output:?}" | ||
| 30 | +git pull | ||
| 31 | +git add -A | ||
| 32 | +git commit -m '前端网页更新' | ||
| 33 | +git push | ||
| 34 | + | ||
| 35 | +# 更新SSH服务器上文件 | ||
| 36 | +ssh -p 22 itomix@ipadbiz.cn 'cd /opt/voice/f/guanzong/web && git pull' |
src/App.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2022-07-25 11:04:45 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-04-29 10:53:39 | ||
| 5 | + * @FilePath: /custom_dashboard/src/App.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div> | ||
| 10 | + <router-view /> | ||
| 11 | + </div> | ||
| 12 | +</template> | ||
| 13 | + | ||
| 14 | +<script> | ||
| 15 | +import { wxInfo } from '@/utils/tools' | ||
| 16 | +import { Updater } from '@/utils/versionUpdater' | ||
| 17 | + | ||
| 18 | +export default { | ||
| 19 | + components: { }, | ||
| 20 | + mounted () { | ||
| 21 | + // 正式环境 | ||
| 22 | + // TAG:检查是否更新 | ||
| 23 | + if (import.meta.env.PROD) { | ||
| 24 | + const upDater = new Updater({ | ||
| 25 | + time: 30000 | ||
| 26 | + }) | ||
| 27 | + upDater.on('no-update', () => { | ||
| 28 | + // console.log('还没更新') | ||
| 29 | + }) | ||
| 30 | + upDater.on('update', () => { | ||
| 31 | + // console.log('已经更新了,请刷新页面') | ||
| 32 | + this.$confirm('检测到新版本,是否刷新?', '温馨提示', { | ||
| 33 | + confirmButtonText: '确定', | ||
| 34 | + cancelButtonText: '取消', | ||
| 35 | + type: 'warning' | ||
| 36 | + }).then(() => { | ||
| 37 | + window.location.reload(); | ||
| 38 | + }).catch(() => { | ||
| 39 | + }); | ||
| 40 | + }) | ||
| 41 | + } | ||
| 42 | + }, | ||
| 43 | + data () { | ||
| 44 | + return { | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | +} | ||
| 48 | +</script> | ||
| 49 | + | ||
| 50 | + | ||
| 51 | +<style lang="less"> | ||
| 52 | +* { | ||
| 53 | + outline: none; | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +// 隐藏浏览器自带滚动条 | ||
| 57 | +// *::-webkit-scrollbar { | ||
| 58 | +// display: none; | ||
| 59 | +// } | ||
| 60 | +// * { | ||
| 61 | +// scrollbar-width: none; | ||
| 62 | +// } | ||
| 63 | +// * { | ||
| 64 | +// -ms-overflow-style: none; | ||
| 65 | +// } | ||
| 66 | +// | ||
| 67 | + | ||
| 68 | +html, | ||
| 69 | +body { | ||
| 70 | + font-size: 16px; | ||
| 71 | + width: 100%; | ||
| 72 | + height: 100%; | ||
| 73 | + margin: 0; | ||
| 74 | + padding: 0; | ||
| 75 | + p { | ||
| 76 | + margin: 0; | ||
| 77 | + padding: 0; | ||
| 78 | + } | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +.global-center { | ||
| 82 | + position: relative; | ||
| 83 | + top: 50%; | ||
| 84 | + transform: translateY(-50%); | ||
| 85 | +} | ||
| 86 | + | ||
| 87 | +.nav-bar { | ||
| 88 | + background-color: #2B000C; | ||
| 89 | + color: #D4D4D4; | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +</style> |
src/api/common.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-06-17 14:54:29 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-08-18 10:52:55 | ||
| 5 | + * @FilePath: /web/src/api/common.js | ||
| 6 | + * @Description: 公共接口 | ||
| 7 | + */ | ||
| 8 | +import { fn, fetch } from '@/api/fn'; | ||
| 9 | + | ||
| 10 | +const Api = { | ||
| 11 | + NAVI: '/srv/?a=navi_bar', | ||
| 12 | + PUMING_INFO: '/srv/?a=puming_info', | ||
| 13 | + CHANNEL_PAGE: '/srv/?a=channel_page', | ||
| 14 | + CHANNEL_BAR: '/srv/?a=channel_bar', | ||
| 15 | + FAHUI_LIST: '/srv/?a=fahui_list', | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * @description: 导航目录 | ||
| 20 | + * @returns | ||
| 21 | + */ | ||
| 22 | +export const naviAPI = (params) => fn(fetch.get(Api.NAVI, params)); | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * @description: 普明慈善基金会 | ||
| 26 | + * @returns | ||
| 27 | + */ | ||
| 28 | +export const pumingInfoAPI = (params) => fn(fetch.get(Api.PUMING_INFO, params)); | ||
| 29 | + | ||
| 30 | +/** | ||
| 31 | + * @description: 侧边频道页和导航相关信息 | ||
| 32 | + * @returns | ||
| 33 | + */ | ||
| 34 | +export const sideNaviAPI = (params) => fn(fetch.get(Api.CHANNEL_PAGE, params)); | ||
| 35 | + | ||
| 36 | +/** | ||
| 37 | + * @description: 频道介绍和其他相关展示信息 | ||
| 38 | + * @returns | ||
| 39 | + */ | ||
| 40 | +export const channelInfoAPI = (params) => fn(fetch.get(Api.CHANNEL_BAR, params)); | ||
| 41 | + | ||
| 42 | +/** | ||
| 43 | + * @description: 法会活动 | ||
| 44 | + * @returns | ||
| 45 | + */ | ||
| 46 | +export const fahuiListAPI = (params) => fn(fetch.get(Api.FAHUI_LIST, params)); |
src/api/fn.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-05-18 22:56:08 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-07-28 17:46:42 | ||
| 5 | + * @FilePath: /web/src/api/fn.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +import axios from '@/utils/axios'; | ||
| 9 | +import { Message } from 'element-ui'; | ||
| 10 | +import qs from 'Qs' | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 网络请求功能函数 | ||
| 14 | + * @param {*} api 请求axios接口 | ||
| 15 | + * @returns 请求成功后,获取数据 | ||
| 16 | + */ | ||
| 17 | +export const fn = (api) => { | ||
| 18 | + return api | ||
| 19 | + .then(res => { | ||
| 20 | + if (res.data.code === 1) { | ||
| 21 | + return res.data || true; | ||
| 22 | + } else { | ||
| 23 | + console.warn(res); | ||
| 24 | + if (!res.data.show) return false; | ||
| 25 | + Message({ | ||
| 26 | + message: res.data.msg, | ||
| 27 | + type: 'warning' | ||
| 28 | + }); | ||
| 29 | + return false; | ||
| 30 | + } | ||
| 31 | + }) | ||
| 32 | + .catch(err => { | ||
| 33 | + console.error(err); | ||
| 34 | + return false; | ||
| 35 | + }) | ||
| 36 | + .finally(() => { // 最终执行 | ||
| 37 | + }) | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +/** | ||
| 41 | + * 统一 GET/POST 不同传参形式 | ||
| 42 | + */ | ||
| 43 | +export const fetch = { | ||
| 44 | + get: function (api, params) { | ||
| 45 | + return axios.get(api, { params }) | ||
| 46 | + }, | ||
| 47 | + post: function (api, params) { | ||
| 48 | + return axios.post(api, params) | ||
| 49 | + }, | ||
| 50 | + stringifyPost: function (api, params) { | ||
| 51 | + return axios.post(api, qs.stringify(params)) | ||
| 52 | + }, | ||
| 53 | + basePost: function (url, data, config) { | ||
| 54 | + return axios.post(url, data, config) | ||
| 55 | + } | ||
| 56 | +} |
src/api/index.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-06-17 14:54:29 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-04-03 14:09:34 | ||
| 5 | + * @FilePath: /custom_dashboard/src/api/index.js | ||
| 6 | + * @Description: 首页接口 | ||
| 7 | + */ | ||
| 8 | +import { fn, fetch } from '@/api/fn'; | ||
| 9 | + | ||
| 10 | +const Api = { | ||
| 11 | + CHART_SQL_LIST: '/admin/?a=chart_sql_list', | ||
| 12 | + SAVE_CHART_SQL: '/admin/?a=save_chart_sql', | ||
| 13 | + DEL_CHART_SQL: '/admin/?a=del_chart_sql', | ||
| 14 | + CHART_SQL_SETTING_LIST: '/admin/?a=chart_sql_setting_list', | ||
| 15 | + SAVE_CHART_SQL_SETTING: '/admin/?a=save_chart_sql_setting', | ||
| 16 | + CHART_SQL_BOARD_LIST: '/admin/?a=chart_sql_board_list', | ||
| 17 | + SAVE_CHART_SQL_BOARD: '/admin/?a=save_chart_sql_board', | ||
| 18 | + DEL_CHART_SQL_BOARD: '/admin/?a=del_chart_sql_board', | ||
| 19 | + DEL_CHART_SQL_SETTING: '/admin/?a=del_chart_sql_setting', | ||
| 20 | + SAVE_CHART_SQL_LOCATION: '/admin/?a=save_chart_sql_location', | ||
| 21 | + CHART_DATA_MIX_LINE_BAR: '/admin/?a=chart_data_mix_line_bar', | ||
| 22 | + SHOW_CHART_SQL: '/admin/?a=show_chart_sql', | ||
| 23 | + DUPLICATE_CHART_SQL: '/admin/?a=duplicate_chart_sql', | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +/** | ||
| 27 | + * @description: sql数据源列表 | ||
| 28 | + */ | ||
| 29 | +export const chartSqlListAPI = (params) => fn(fetch.get(Api.CHART_SQL_LIST, params)); | ||
| 30 | + | ||
| 31 | +/** | ||
| 32 | + * @description: 保存sql数据源 | ||
| 33 | + * @param {*} id sql数据源id。为空表示新增,否则是更新。 | ||
| 34 | + * @param {*} name sql数据源名称 | ||
| 35 | + * @param {*} chart_mode 图表类型 | ||
| 36 | + * @param {*} sql_stat sql语句 | ||
| 37 | + * @param {*} sql_col sql语句输出的字段 | ||
| 38 | + * @param {*} sql_parm sql语句的执行参数 | ||
| 39 | + * @param {*} status 状态 | ||
| 40 | + * @param {*} note sql数据源的描述 | ||
| 41 | + */ | ||
| 42 | +export const saveChartSqlAPI = (params) => fn(fetch.post(Api.SAVE_CHART_SQL, params)) | ||
| 43 | + | ||
| 44 | +/** | ||
| 45 | + * @description: 删除sql数据源 | ||
| 46 | + * @param {*} id sql数据源id | ||
| 47 | + */ | ||
| 48 | +export const delChartSqlAPI = (params) => fn(fetch.post(Api.DEL_CHART_SQL, params)) | ||
| 49 | + | ||
| 50 | +/** | ||
| 51 | + * @description: sql版图表列表 | ||
| 52 | + * @param {*} name 图表名称,模糊查询 | ||
| 53 | + * @param {*} chart_mode 图表类型,json数组,可以查询多个类型 | ||
| 54 | + * @param {*} status 状态,json数组,可以查询多个状态 | ||
| 55 | + * @param {*} row_num 每页行数,默认20 | ||
| 56 | + * @param {*} page 当前页数,默认1,从1开始,1表示第一页,2表示第二页,依次类推; | ||
| 57 | + */ | ||
| 58 | +export const chartSqlSettingListAPI = (params) => fn(fetch.get(Api.CHART_SQL_SETTING_LIST, params)) | ||
| 59 | + | ||
| 60 | +/** | ||
| 61 | + * @description: 仪表盘内保存sql版图表 | ||
| 62 | + * @param {*} | ||
| 63 | + */ | ||
| 64 | +export const saveChartSqlSettingAPI = (params) => fn(fetch.post(Api.SAVE_CHART_SQL_SETTING, params)) | ||
| 65 | + | ||
| 66 | +/** | ||
| 67 | + * @description: sql版仪表盘列表 | ||
| 68 | + */ | ||
| 69 | +export const chartSqlBoardListAPI = (params) => fn(fetch.get(Api.CHART_SQL_BOARD_LIST, params)); | ||
| 70 | + | ||
| 71 | +/** | ||
| 72 | + * @description: 保存sql版仪表盘 | ||
| 73 | + * @param {*} id sql版仪表盘id。为空表示新增,否则是更新。 | ||
| 74 | + * @param {*} name sql版仪表盘名称 | ||
| 75 | + * @param {*} note sql版仪表盘的描述 | ||
| 76 | + */ | ||
| 77 | +export const saveChartSqlBoardAPI = (params) => fn(fetch.post(Api.SAVE_CHART_SQL_BOARD, params)) | ||
| 78 | + | ||
| 79 | +/** | ||
| 80 | + * @description: 删除sql版仪表盘 | ||
| 81 | + * @param {*} id sql版仪表盘id。 | ||
| 82 | + */ | ||
| 83 | +export const delChartSqlBoardAPI = (params) => fn(fetch.post(Api.DEL_CHART_SQL_BOARD, params)) | ||
| 84 | + | ||
| 85 | +/** | ||
| 86 | + * @description: 仪表盘内删除sql版图表 | ||
| 87 | + * @param {*} id sql版仪表盘id。 | ||
| 88 | + */ | ||
| 89 | +export const delChartSqlSettingAPI = (params) => fn(fetch.post(Api.DEL_CHART_SQL_SETTING, params)) | ||
| 90 | + | ||
| 91 | +/** | ||
| 92 | + * @description: 仪表盘内保存sql版图表位置 | ||
| 93 | + * @param {*} board_id 仪表盘id | ||
| 94 | + * @param {*} location 仪表盘内所有图表的位置,json数组格式 | ||
| 95 | + */ | ||
| 96 | +export const saveChartSqlLocationAPI = (params) => fn(fetch.post(Api.SAVE_CHART_SQL_LOCATION, params)) | ||
| 97 | + | ||
| 98 | +/** | ||
| 99 | + * @description: 双轴图的展示数据 | ||
| 100 | + * @param {*} data 左右轴的图表数据 | ||
| 101 | + */ | ||
| 102 | +export const chartDataMixLineBarAPI = (params) => fn(fetch.get(Api.CHART_DATA_MIX_LINE_BAR, params)) | ||
| 103 | + | ||
| 104 | +/** | ||
| 105 | + * @description: 展示一个sql版图表 | ||
| 106 | + * @param {*} | ||
| 107 | + */ | ||
| 108 | +export const showChartSqlAPI = (params) => fn(fetch.get(Api.SHOW_CHART_SQL, params)) | ||
| 109 | + | ||
| 110 | +/** | ||
| 111 | + * @description: 复制sql数据源 | ||
| 112 | + * @param {*} sql_id sql数据源id | ||
| 113 | + */ | ||
| 114 | +export const duplicateChartSqlAPI = (params) => fn(fetch.get(Api.DUPLICATE_CHART_SQL, params)) |
src/api/temple.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-06-17 14:54:29 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-08-04 14:49:05 | ||
| 5 | + * @FilePath: /web/src/api/temple.js | ||
| 6 | + * @Description: 走进寺庙接口 | ||
| 7 | + */ | ||
| 8 | +import { fn, fetch } from '@/api/fn'; | ||
| 9 | + | ||
| 10 | +const Api = { | ||
| 11 | + TEMPLE_INFO: '/srv/?a=temple_info', | ||
| 12 | +} | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * @description: 走进寺庙 | ||
| 16 | + * @returns | ||
| 17 | + */ | ||
| 18 | +export const templeInfoAPI = (params) => fn(fetch.get(Api.TEMPLE_INFO, params)); |
src/assets/images/chart/area-basic.png
0 → 100644
8.96 KB
src/assets/images/chart/bar-race.png
0 → 100644
5.32 KB
src/assets/images/chart/bar-simple.png
0 → 100644
6.97 KB
src/assets/images/chart/dynamic-data.png
0 → 100644
16.7 KB
src/assets/images/chart/funnel.png
0 → 100644
7.86 KB
src/assets/images/chart/line-simple.png
0 → 100644
7.07 KB
src/assets/images/chart/pie-simple.png
0 → 100644
10.3 KB
src/assets/images/chart/radar.png
0 → 100644
24.3 KB
src/assets/styles/base.less
0 → 100644
| 1 | +/* ============ 颜色 ============ */ | ||
| 2 | + | ||
| 3 | +// 文字颜色 | ||
| 4 | +@text-color: #333333; | ||
| 5 | +// Hover颜色 | ||
| 6 | +@hover-color: #2B000C; | ||
| 7 | +// Hover颜色 | ||
| 8 | +@hover-main-color: #F3BB66; | ||
| 9 | +// 次要颜色 | ||
| 10 | +@sub-color: #2B000C; | ||
| 11 | +// 文字附件颜色 | ||
| 12 | +@affix-color: #999999; | ||
| 13 | + | ||
| 14 | +.multi-ellipsis--l1 { | ||
| 15 | + display: -webkit-box; | ||
| 16 | + overflow: hidden; | ||
| 17 | + text-overflow: ellipsis; | ||
| 18 | + -webkit-line-clamp: 1; | ||
| 19 | + -webkit-box-orient: vertical; | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +.multi-ellipsis--l2 { | ||
| 23 | + display: -webkit-box; | ||
| 24 | + overflow: hidden; | ||
| 25 | + text-overflow: ellipsis; | ||
| 26 | + -webkit-line-clamp: 2; | ||
| 27 | + -webkit-box-orient: vertical; | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +.multi-ellipsis--l3 { | ||
| 31 | + display: -webkit-box; | ||
| 32 | + overflow: hidden; | ||
| 33 | + text-overflow: ellipsis; | ||
| 34 | + -webkit-line-clamp: 3; | ||
| 35 | + -webkit-box-orient: vertical; | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +.multi-ellipsis--l4 { | ||
| 39 | + display: -webkit-box; | ||
| 40 | + overflow: hidden; | ||
| 41 | + text-overflow: ellipsis; | ||
| 42 | + -webkit-line-clamp: 4; | ||
| 43 | + -webkit-box-orient: vertical; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +.multi-ellipsis--l5 { | ||
| 47 | + display: -webkit-box; | ||
| 48 | + overflow: hidden; | ||
| 49 | + text-overflow: ellipsis; | ||
| 50 | + -webkit-line-clamp: 5; | ||
| 51 | + -webkit-box-orient: vertical; | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +.multi-ellipsis--l6 { | ||
| 55 | + display: -webkit-box; | ||
| 56 | + overflow: hidden; | ||
| 57 | + text-overflow: ellipsis; | ||
| 58 | + -webkit-line-clamp: 6; | ||
| 59 | + -webkit-box-orient: vertical; | ||
| 60 | +} |
src/auto-imports.d.ts
0 → 100644
| 1 | +/* eslint-disable */ | ||
| 2 | +/* prettier-ignore */ | ||
| 3 | +// @ts-nocheck | ||
| 4 | +// noinspection JSUnusedGlobalSymbols | ||
| 5 | +// Generated by unplugin-auto-import | ||
| 6 | +export {} | ||
| 7 | +declare global { | ||
| 8 | + const EffectScope: typeof import('vue')['EffectScope'] | ||
| 9 | + const computed: typeof import('vue')['computed'] | ||
| 10 | + const createApp: typeof import('vue')['createApp'] | ||
| 11 | + const customRef: typeof import('vue')['customRef'] | ||
| 12 | + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] | ||
| 13 | + const defineComponent: typeof import('vue')['defineComponent'] | ||
| 14 | + const effectScope: typeof import('vue')['effectScope'] | ||
| 15 | + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] | ||
| 16 | + const getCurrentScope: typeof import('vue')['getCurrentScope'] | ||
| 17 | + const h: typeof import('vue')['h'] | ||
| 18 | + const inject: typeof import('vue')['inject'] | ||
| 19 | + const isProxy: typeof import('vue')['isProxy'] | ||
| 20 | + const isReactive: typeof import('vue')['isReactive'] | ||
| 21 | + const isReadonly: typeof import('vue')['isReadonly'] | ||
| 22 | + const isRef: typeof import('vue')['isRef'] | ||
| 23 | + const markRaw: typeof import('vue')['markRaw'] | ||
| 24 | + const nextTick: typeof import('vue')['nextTick'] | ||
| 25 | + const onActivated: typeof import('vue')['onActivated'] | ||
| 26 | + const onBeforeMount: typeof import('vue')['onBeforeMount'] | ||
| 27 | + const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] | ||
| 28 | + const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] | ||
| 29 | + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] | ||
| 30 | + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] | ||
| 31 | + const onDeactivated: typeof import('vue')['onDeactivated'] | ||
| 32 | + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] | ||
| 33 | + const onMounted: typeof import('vue')['onMounted'] | ||
| 34 | + const onRenderTracked: typeof import('vue')['onRenderTracked'] | ||
| 35 | + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] | ||
| 36 | + const onScopeDispose: typeof import('vue')['onScopeDispose'] | ||
| 37 | + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] | ||
| 38 | + const onUnmounted: typeof import('vue')['onUnmounted'] | ||
| 39 | + const onUpdated: typeof import('vue')['onUpdated'] | ||
| 40 | + const provide: typeof import('vue')['provide'] | ||
| 41 | + const reactive: typeof import('vue')['reactive'] | ||
| 42 | + const readonly: typeof import('vue')['readonly'] | ||
| 43 | + const ref: typeof import('vue')['ref'] | ||
| 44 | + const resolveComponent: typeof import('vue')['resolveComponent'] | ||
| 45 | + const shallowReactive: typeof import('vue')['shallowReactive'] | ||
| 46 | + const shallowReadonly: typeof import('vue')['shallowReadonly'] | ||
| 47 | + const shallowRef: typeof import('vue')['shallowRef'] | ||
| 48 | + const toRaw: typeof import('vue')['toRaw'] | ||
| 49 | + const toRef: typeof import('vue')['toRef'] | ||
| 50 | + const toRefs: typeof import('vue')['toRefs'] | ||
| 51 | + const toValue: typeof import('vue')['toValue'] | ||
| 52 | + const triggerRef: typeof import('vue')['triggerRef'] | ||
| 53 | + const unref: typeof import('vue')['unref'] | ||
| 54 | + const useAttrs: typeof import('vue')['useAttrs'] | ||
| 55 | + const useCssModule: typeof import('vue')['useCssModule'] | ||
| 56 | + const useCssVars: typeof import('vue')['useCssVars'] | ||
| 57 | + const useLink: typeof import('vue-router')['useLink'] | ||
| 58 | + const useRoute: typeof import('vue-router')['useRoute'] | ||
| 59 | + const useRouter: typeof import('vue-router')['useRouter'] | ||
| 60 | + const useSlots: typeof import('vue')['useSlots'] | ||
| 61 | + const watch: typeof import('vue')['watch'] | ||
| 62 | + const watchEffect: typeof import('vue')['watchEffect'] | ||
| 63 | + const watchPostEffect: typeof import('vue')['watchPostEffect'] | ||
| 64 | + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] | ||
| 65 | +} | ||
| 66 | +// for type re-export | ||
| 67 | +declare global { | ||
| 68 | + // @ts-ignore | ||
| 69 | + export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' | ||
| 70 | + import('vue') | ||
| 71 | +} |
src/common/mixin.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-07-26 09:49:54 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-03-25 17:56:01 | ||
| 5 | + * @FilePath: /custom_dashboard/src/common/mixin.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | + | ||
| 9 | +export default { | ||
| 10 | + // 初始化设置 | ||
| 11 | + init: { | ||
| 12 | + mounted () { | ||
| 13 | + document.title = this.$route.meta.title; | ||
| 14 | + }, | ||
| 15 | + methods: { | ||
| 16 | + }, | ||
| 17 | + }, | ||
| 18 | +}; |
src/components/DataSource.vue
0 → 100644
This diff is collapsed. Click to expand it.
src/components/DynamicChart.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2024-03-01 09:40:27 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-03-30 06:14:10 | ||
| 5 | + * @FilePath: /custom_dashboard/src/components/DynamicChart.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div :ref="chartRef" class="dynamic-chart" :style="{ width: width, height: wrapper_height, marginTop: titleHeight + 'px'}"></div> | ||
| 10 | +</template> | ||
| 11 | + | ||
| 12 | +<script> | ||
| 13 | +import * as echarts from 'echarts/core'; | ||
| 14 | +// 引入柱状图图表,图表后缀都为 Chart | ||
| 15 | +import { BarChart, PieChart, LineChart, RadarChart, FunnelChart } from 'echarts/charts'; | ||
| 16 | +// 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component | ||
| 17 | +import { | ||
| 18 | + TitleComponent, | ||
| 19 | + TooltipComponent, | ||
| 20 | + LegendComponent, | ||
| 21 | + GridComponent, | ||
| 22 | + DatasetComponent, | ||
| 23 | + TransformComponent | ||
| 24 | +} from 'echarts/components'; | ||
| 25 | +// 标签自动布局、全局过渡动画等特性 | ||
| 26 | +import { LabelLayout, UniversalTransition } from 'echarts/features'; | ||
| 27 | +// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步 | ||
| 28 | +import { CanvasRenderer } from 'echarts/renderers'; | ||
| 29 | + | ||
| 30 | +// 注册必须的组件 | ||
| 31 | +echarts.use([ | ||
| 32 | + TitleComponent, | ||
| 33 | + TooltipComponent, | ||
| 34 | + LegendComponent, | ||
| 35 | + GridComponent, | ||
| 36 | + DatasetComponent, | ||
| 37 | + TransformComponent, | ||
| 38 | + BarChart, | ||
| 39 | + PieChart, | ||
| 40 | + LineChart, | ||
| 41 | + RadarChart, | ||
| 42 | + FunnelChart, | ||
| 43 | + LabelLayout, | ||
| 44 | + UniversalTransition, | ||
| 45 | + CanvasRenderer | ||
| 46 | +]); | ||
| 47 | + | ||
| 48 | +export default { | ||
| 49 | + name: 'DynamicChart', | ||
| 50 | + props: ['chartOptions', 'chartData', 'width', 'height', 'titleHeight'], | ||
| 51 | + data() { | ||
| 52 | + return { | ||
| 53 | + chartRef: 'chartContainer', | ||
| 54 | + chartInstance: null, | ||
| 55 | + wrapper_height: '', | ||
| 56 | + }; | ||
| 57 | + }, | ||
| 58 | + watch: { | ||
| 59 | + height (val) { | ||
| 60 | + if (val) { | ||
| 61 | + this.wrapper_height = val; | ||
| 62 | + } | ||
| 63 | + } | ||
| 64 | + }, | ||
| 65 | + mounted() { | ||
| 66 | + this.wrapper_height = this.height; | ||
| 67 | + setTimeout(() => { | ||
| 68 | + this.initChart(); | ||
| 69 | + }, 200); | ||
| 70 | + }, | ||
| 71 | + beforeDestroy() { | ||
| 72 | + this.destroyChart(); | ||
| 73 | + }, | ||
| 74 | + methods: { | ||
| 75 | + initChart() { | ||
| 76 | + const chartContainer = this.$refs.chartContainer; | ||
| 77 | + if (chartContainer) { | ||
| 78 | + this.chartInstance = echarts.init(chartContainer); | ||
| 79 | + this.chartInstance.setOption(this.chartOptions); | ||
| 80 | + } | ||
| 81 | + }, | ||
| 82 | + destroyChart() { | ||
| 83 | + if (this.chartInstance) { | ||
| 84 | + this.chartInstance.dispose(); | ||
| 85 | + this.chartInstance = null; | ||
| 86 | + } | ||
| 87 | + }, | ||
| 88 | + updateChart() { | ||
| 89 | + this.chartInstance.setOption(this.chartOptions); | ||
| 90 | + }, | ||
| 91 | + } | ||
| 92 | +}; | ||
| 93 | +</script> | ||
| 94 | + | ||
| 95 | +<style scoped> | ||
| 96 | +.dynamic-chart { | ||
| 97 | + padding: 10px; | ||
| 98 | +} | ||
| 99 | +</style> |
src/components/FilterInput.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2024-03-21 09:36:01 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-03-21 14:20:43 | ||
| 5 | + * @FilePath: /custom_dashboard/src/components/filterInput.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div :class="['edit-tag-wrapper', hoverInFilter ? 'hover' : '']"> | ||
| 10 | + <p style="margin-bottom: 10px">过滤:</p> | ||
| 11 | + <div id="filter" style="flex: 1; height: 100%; display: flex"> | ||
| 12 | + <!-- <el-tag | ||
| 13 | + :key="index" | ||
| 14 | + v-for="(item, index) in filter_list" | ||
| 15 | + closable | ||
| 16 | + effect="plain" | ||
| 17 | + type="success" | ||
| 18 | + :disable-transitions="false" | ||
| 19 | + @close="handleFilterClose(item, index)"> | ||
| 20 | + {{ item.name }}<span style="font-size: 0.7rem;"> ( 求和 )</span> | ||
| 21 | + </el-tag> --> | ||
| 22 | + <div | ||
| 23 | + :key="index" | ||
| 24 | + v-for="(item, index) in filter_list" | ||
| 25 | + class="filter-wrapper" | ||
| 26 | + > | ||
| 27 | + <VDropdown placement="bottom"> | ||
| 28 | + <span class="filter-item"> | ||
| 29 | + <i class="el-icon-arrow-down el-icon--right"></i> <span | ||
| 30 | + style="font-size: 0.8rem" | ||
| 31 | + >{{ item.name }}</span | ||
| 32 | + > | ||
| 33 | + </span> | ||
| 34 | + | ||
| 35 | + <template #popper> | ||
| 36 | + <!-- <VMenu v-for="n in 5" :key="n" placement="right-start" instant-move> | ||
| 37 | + <div style="padding: 0.5rem">修改显示名</div> | ||
| 38 | + | ||
| 39 | + <template #popper> | ||
| 40 | + <VMenu v-for="n in 5" :key="n" placement="right-start" instant-move> | ||
| 41 | + <div class="rounded hover:bg-green-100 px-4 py-2">Option {{ n }}</div> | ||
| 42 | + </VMenu> | ||
| 43 | + </template> | ||
| 44 | + </VMenu> --> | ||
| 45 | + <div style="padding: 0.5rem;"> | ||
| 46 | + <div class="filter-handle-item">修改筛选条件</div> | ||
| 47 | + <div class="filter-handle-item">删除筛选条件</div> | ||
| 48 | + </div> | ||
| 49 | + </template> | ||
| 50 | + </VDropdown> | ||
| 51 | + </div> | ||
| 52 | + </div> | ||
| 53 | + | ||
| 54 | + <el-dialog | ||
| 55 | + title="设置过滤条件" | ||
| 56 | + :visible.sync="dialogVisible" | ||
| 57 | + width="30%" | ||
| 58 | + :append-to-body="true" | ||
| 59 | + :before-close="handleClose"> | ||
| 60 | + <div> | ||
| 61 | + <el-row :gutter="5"> | ||
| 62 | + <el-col :span="16"> | ||
| 63 | + <el-input v-model="field_input" :disabled="true"> | ||
| 64 | + </el-input> | ||
| 65 | + </el-col> | ||
| 66 | + <el-col :span="8"> | ||
| 67 | + <el-select v-model="op_value" placeholder="请选择"> | ||
| 68 | + <el-option | ||
| 69 | + v-for="item in options" | ||
| 70 | + :key="item.value" | ||
| 71 | + :label="item.label" | ||
| 72 | + :value="item.value"> | ||
| 73 | + </el-option> | ||
| 74 | + </el-select> | ||
| 75 | + </el-col> | ||
| 76 | + </el-row> | ||
| 77 | + <el-row style="margin-top: 0.5rem;"> | ||
| 78 | + <el-col :span="24"> | ||
| 79 | + <el-input placeholder="请输入内容" v-model="filter_input"> | ||
| 80 | + </el-input> | ||
| 81 | + </el-col> | ||
| 82 | + </el-row> | ||
| 83 | + </div> | ||
| 84 | + <span slot="footer" class="dialog-footer"> | ||
| 85 | + <el-button @click="dialogVisible = false">取 消</el-button> | ||
| 86 | + <el-button type="primary" @click="dialogVisible = false">确 定</el-button> | ||
| 87 | + </span> | ||
| 88 | + </el-dialog> | ||
| 89 | + </div> | ||
| 90 | +</template> | ||
| 91 | + | ||
| 92 | +<script> | ||
| 93 | +import mixin from "common/mixin"; | ||
| 94 | + | ||
| 95 | +const TEXT_OPTIONS = [{ | ||
| 96 | + value: '1', | ||
| 97 | + label: '等于' | ||
| 98 | +}, { | ||
| 99 | + value: '2', | ||
| 100 | + label: '不等于' | ||
| 101 | +}, { | ||
| 102 | + value: '3', | ||
| 103 | + label: '等于任意一个' | ||
| 104 | +}, { | ||
| 105 | + value: '4', | ||
| 106 | + label: '不等于任意一个' | ||
| 107 | +}, { | ||
| 108 | + value: '5', | ||
| 109 | + label: '包含' | ||
| 110 | +}, { | ||
| 111 | + value: '6', | ||
| 112 | + label: '不包含' | ||
| 113 | +}, { | ||
| 114 | + value: '7', | ||
| 115 | + label: '为空' | ||
| 116 | +}, { | ||
| 117 | + value: '8', | ||
| 118 | + label: '不为空' | ||
| 119 | +}]; | ||
| 120 | + | ||
| 121 | +const DATE_OPTIONS = [{ | ||
| 122 | + value: '1', | ||
| 123 | + label: '等于' | ||
| 124 | +}, { | ||
| 125 | + value: '2', | ||
| 126 | + label: '不等于' | ||
| 127 | +}, { | ||
| 128 | + value: '3', | ||
| 129 | + label: '大于等于' | ||
| 130 | +}, { | ||
| 131 | + value: '4', | ||
| 132 | + label: '小于等于' | ||
| 133 | +}, { | ||
| 134 | + value: '5', | ||
| 135 | + label: '选择范围' | ||
| 136 | +}, { | ||
| 137 | + value: '6', | ||
| 138 | + label: '动态筛选' | ||
| 139 | +}, { | ||
| 140 | + value: '7', | ||
| 141 | + label: '为空' | ||
| 142 | +}, { | ||
| 143 | + value: '8', | ||
| 144 | + label: '不为空' | ||
| 145 | +}]; | ||
| 146 | + | ||
| 147 | +const NUM_OPTIONS = [{ | ||
| 148 | + value: '1', | ||
| 149 | + label: '等于' | ||
| 150 | +}, { | ||
| 151 | + value: '2', | ||
| 152 | + label: '不等于' | ||
| 153 | +}, { | ||
| 154 | + value: '3', | ||
| 155 | + label: '大于' | ||
| 156 | +}, { | ||
| 157 | + value: '4', | ||
| 158 | + label: '大于等于' | ||
| 159 | +}, { | ||
| 160 | + value: '5', | ||
| 161 | + label: '小于' | ||
| 162 | +}, { | ||
| 163 | + value: '6', | ||
| 164 | + label: '小于等于' | ||
| 165 | +}, { | ||
| 166 | + value: '7', | ||
| 167 | + label: '选择范围' | ||
| 168 | +}, { | ||
| 169 | + value: '8', | ||
| 170 | + label: '为空' | ||
| 171 | +}, { | ||
| 172 | + value: '9', | ||
| 173 | + label: '不为空' | ||
| 174 | +}]; | ||
| 175 | + | ||
| 176 | +export default { | ||
| 177 | + mixins: [mixin.init], | ||
| 178 | + props: { | ||
| 179 | + hover: { | ||
| 180 | + type: Boolean, | ||
| 181 | + default: false, | ||
| 182 | + }, | ||
| 183 | + list: { | ||
| 184 | + type: Array, | ||
| 185 | + default: () => { | ||
| 186 | + return []; | ||
| 187 | + }, | ||
| 188 | + }, | ||
| 189 | + filterItem: { | ||
| 190 | + type: Object, | ||
| 191 | + default: () => { | ||
| 192 | + return {}; | ||
| 193 | + } | ||
| 194 | + } | ||
| 195 | + }, | ||
| 196 | + watch: { | ||
| 197 | + hover(v) { | ||
| 198 | + this.hoverInFilter = v; | ||
| 199 | + }, | ||
| 200 | + list(v) { | ||
| 201 | + this.filter_list = v; | ||
| 202 | + }, | ||
| 203 | + filterItem(v) { | ||
| 204 | + if (v) { | ||
| 205 | + this.dialogVisible = true; | ||
| 206 | + } | ||
| 207 | + } | ||
| 208 | + }, | ||
| 209 | + data() { | ||
| 210 | + return { | ||
| 211 | + filter_list: [], | ||
| 212 | + hoverInFilter: false, | ||
| 213 | + dialogVisible: false, | ||
| 214 | + options: [], | ||
| 215 | + op_value: '1', | ||
| 216 | + field_input: '测试字段', | ||
| 217 | + filter_input: '', | ||
| 218 | + }; | ||
| 219 | + }, | ||
| 220 | + mounted() { | ||
| 221 | + this.options = TEXT_OPTIONS; | ||
| 222 | + }, | ||
| 223 | + methods: { | ||
| 224 | + handleFilterClose() { | ||
| 225 | + // this.filter_list.splice(index, 1); | ||
| 226 | + }, | ||
| 227 | + handleClose(done) { | ||
| 228 | + this.$confirm('确认关闭?') | ||
| 229 | + .then(_ => { | ||
| 230 | + done(); | ||
| 231 | + }) | ||
| 232 | + .catch(_ => {}); | ||
| 233 | + }, | ||
| 234 | + }, | ||
| 235 | +}; | ||
| 236 | +</script> | ||
| 237 | + | ||
| 238 | +<style lang="less" scoped> | ||
| 239 | +.edit-tag-wrapper { | ||
| 240 | + border: 1px dashed #d7d9dc; | ||
| 241 | + border-radius: 3px; | ||
| 242 | + padding: 10px; | ||
| 243 | + padding-bottom: 0; | ||
| 244 | + height: auto; | ||
| 245 | + min-height: 42px; | ||
| 246 | + background: #fff; | ||
| 247 | + display: flex; | ||
| 248 | + align-items: center; | ||
| 249 | + margin-bottom: 10px; | ||
| 250 | + // width: 100%; | ||
| 251 | + &.hover { | ||
| 252 | + border: 1px dashed green; | ||
| 253 | + background: rgb(208 249 208 / 34%); | ||
| 254 | + } | ||
| 255 | + | ||
| 256 | + .filter-wrapper { | ||
| 257 | + margin-right: 10px; | ||
| 258 | + margin-bottom: 10px; | ||
| 259 | + .filter-item { | ||
| 260 | + background-color: #fff; | ||
| 261 | + border-color: #d9ecff; | ||
| 262 | + height: 32px; | ||
| 263 | + padding: 7px 10px 10px 0; | ||
| 264 | + line-height: 1; | ||
| 265 | + color: #409eff; | ||
| 266 | + border-width: 1px; | ||
| 267 | + border-style: solid; | ||
| 268 | + border-radius: 4px; | ||
| 269 | + box-sizing: border-box; | ||
| 270 | + white-space: nowrap; | ||
| 271 | + display: inline-block; | ||
| 272 | + cursor: pointer; | ||
| 273 | + } | ||
| 274 | + } | ||
| 275 | +} | ||
| 276 | + | ||
| 277 | +.filter-handle-item { | ||
| 278 | + padding: 0.5rem 1rem; | ||
| 279 | + &:hover { | ||
| 280 | + background-color: #f5f5f5; | ||
| 281 | + cursor: pointer; | ||
| 282 | + } | ||
| 283 | +} | ||
| 284 | +</style> |
src/components/GeoChart.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2024-05-17 16:31:55 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-05-17 17:33:08 | ||
| 5 | + * @FilePath: /custom_dashboard/src/components/GeoChart.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div :ref="chartRef" id="chart-container" style="width: 100%; height: 800px;"></div> | ||
| 10 | +</template> | ||
| 11 | + | ||
| 12 | +<script> | ||
| 13 | +import mixin from 'common/mixin'; | ||
| 14 | +import $ from 'jquery'; | ||
| 15 | +import * as echarts from 'echarts/core'; | ||
| 16 | +// 引入柱状图图表,图表后缀都为 Chart | ||
| 17 | +import { BarChart, PieChart, LineChart, RadarChart, FunnelChart, LinesChart } from 'echarts/charts'; | ||
| 18 | +// 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component | ||
| 19 | +import { | ||
| 20 | + TitleComponent, | ||
| 21 | + TooltipComponent, | ||
| 22 | + LegendComponent, | ||
| 23 | + GridComponent, | ||
| 24 | + DatasetComponent, | ||
| 25 | + TransformComponent, | ||
| 26 | + GeoComponent | ||
| 27 | +} from 'echarts/components'; | ||
| 28 | +// 标签自动布局、全局过渡动画等特性 | ||
| 29 | +import { LabelLayout, UniversalTransition } from 'echarts/features'; | ||
| 30 | +// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步 | ||
| 31 | +import { CanvasRenderer, SVGRenderer } from 'echarts/renderers'; | ||
| 32 | + | ||
| 33 | +// 注册必须的组件 | ||
| 34 | +echarts.use([ | ||
| 35 | + TitleComponent, | ||
| 36 | + TooltipComponent, | ||
| 37 | + LegendComponent, | ||
| 38 | + GridComponent, | ||
| 39 | + DatasetComponent, | ||
| 40 | + TransformComponent, | ||
| 41 | + BarChart, | ||
| 42 | + PieChart, | ||
| 43 | + LineChart, | ||
| 44 | + RadarChart, | ||
| 45 | + FunnelChart, | ||
| 46 | + LabelLayout, | ||
| 47 | + UniversalTransition, | ||
| 48 | + CanvasRenderer, | ||
| 49 | + SVGRenderer, | ||
| 50 | + GeoComponent, | ||
| 51 | + LinesChart | ||
| 52 | +]); | ||
| 53 | + | ||
| 54 | +export default { | ||
| 55 | + mixins: [mixin.init], | ||
| 56 | + data () { | ||
| 57 | + return { | ||
| 58 | + chartRef: 'chartContainer', | ||
| 59 | + chartInstance: null, | ||
| 60 | + chartOptions: { | ||
| 61 | + title: { | ||
| 62 | + text: 'Visit Route', | ||
| 63 | + left: 'center', | ||
| 64 | + bottom: 10 | ||
| 65 | + }, | ||
| 66 | + tooltip: {}, | ||
| 67 | + geo: { | ||
| 68 | + map: 'MacOdrum-LV5-floorplan-web', | ||
| 69 | + roam: true, | ||
| 70 | + emphasis: { | ||
| 71 | + itemStyle: { | ||
| 72 | + color: undefined | ||
| 73 | + }, | ||
| 74 | + label: { | ||
| 75 | + show: false | ||
| 76 | + } | ||
| 77 | + } | ||
| 78 | + }, | ||
| 79 | + series: [ | ||
| 80 | + { | ||
| 81 | + name: 'Route', | ||
| 82 | + type: 'lines', | ||
| 83 | + coordinateSystem: 'geo', | ||
| 84 | + geoIndex: 0, | ||
| 85 | + emphasis: { | ||
| 86 | + label: { | ||
| 87 | + show: false | ||
| 88 | + } | ||
| 89 | + }, | ||
| 90 | + polyline: true, | ||
| 91 | + lineStyle: { | ||
| 92 | + color: '#c46e54', | ||
| 93 | + width: 5, | ||
| 94 | + opacity: 1, | ||
| 95 | + type: 'dotted' | ||
| 96 | + }, | ||
| 97 | + effect: { | ||
| 98 | + show: true, | ||
| 99 | + period: 8, | ||
| 100 | + color: '#a10000', | ||
| 101 | + constantSpeed: 80, | ||
| 102 | + trailLength: 0, | ||
| 103 | + symbolSize: [20, 12], | ||
| 104 | + symbol: | ||
| 105 | + 'path://M35.5 40.5c0-22.16 17.84-40 40-40s40 17.84 40 40c0 1.6939-.1042 3.3626-.3067 5H35.8067c-.2025-1.6374-.3067-3.3061-.3067-5zm90.9621-2.6663c-.62-1.4856-.9621-3.1182-.9621-4.8337 0-6.925 5.575-12.5 12.5-12.5s12.5 5.575 12.5 12.5a12.685 12.685 0 0 1-.1529 1.9691l.9537.5506-15.6454 27.0986-.1554-.0897V65.5h-28.7285c-7.318 9.1548-18.587 15-31.2715 15s-23.9535-5.8452-31.2715-15H15.5v-2.8059l-.0937.0437-8.8727-19.0274C2.912 41.5258.5 37.5549.5 33c0-6.925 5.575-12.5 12.5-12.5S25.5 26.075 25.5 33c0 .9035-.0949 1.784-.2753 2.6321L29.8262 45.5h92.2098z' | ||
| 106 | + }, | ||
| 107 | + data: [ | ||
| 108 | + { | ||
| 109 | + coords: [ | ||
| 110 | + [110.6189462165178, 456.64349563895087], | ||
| 111 | + [124.10988522879458, 450.8570048730469], | ||
| 112 | + [123.9272226116071, 389.9520693708147], | ||
| 113 | + [61.58708083147317, 386.87942320312504], | ||
| 114 | + [61.58708083147317, 72.8954315876116], | ||
| 115 | + [258.29514854771196, 72.8954315876116], | ||
| 116 | + [260.75457021484374, 336.8559607533482], | ||
| 117 | + [280.5277985253906, 410.2406672084263], | ||
| 118 | + [275.948185765904, 528.0254369698661], | ||
| 119 | + [111.06907909458701, 552.795792593471], | ||
| 120 | + [118.87138231445309, 701.365737015904], | ||
| 121 | + [221.36468155133926, 758.7870354617745], | ||
| 122 | + [307.86195445452006, 742.164737297712], | ||
| 123 | + [366.8489324762834, 560.9895157073103], | ||
| 124 | + [492.8750778390066, 560.9895157073103], | ||
| 125 | + [492.8750778390066, 827.9639780566406], | ||
| 126 | + [294.9255269587053, 827.9639780566406], | ||
| 127 | + [282.79803391043527, 868.2476088113839] | ||
| 128 | + ] | ||
| 129 | + } | ||
| 130 | + ] | ||
| 131 | + } | ||
| 132 | + ] | ||
| 133 | + } | ||
| 134 | + } | ||
| 135 | + }, | ||
| 136 | + mounted () { | ||
| 137 | + setTimeout(() => { | ||
| 138 | + this.initChart(); | ||
| 139 | + }, 500); | ||
| 140 | + }, | ||
| 141 | + methods: { | ||
| 142 | + initChart() { | ||
| 143 | + var dom = document.getElementById('chart-container'); | ||
| 144 | + this.chartInstance = echarts.init(dom, null, { | ||
| 145 | + renderer: 'svg', | ||
| 146 | + useDirtyRect: false | ||
| 147 | + }); | ||
| 148 | + $.get('https://cdn.ipadbiz.cn/tmp/MacOdrum-LV5-floorplan-web.svg', (svg) => { | ||
| 149 | + echarts.registerMap('MacOdrum-LV5-floorplan-web', { svg: svg }); | ||
| 150 | + this.chartInstance.setOption(this.chartOptions); | ||
| 151 | + this.chartInstance.on('click', { geoIndex: 0, name: 'seminar_room' }, function (params) { | ||
| 152 | + console.log(params); | ||
| 153 | + }); | ||
| 154 | + }) | ||
| 155 | + }, | ||
| 156 | + destroyChart() { | ||
| 157 | + if (this.chartInstance) { | ||
| 158 | + this.chartInstance.dispose(); | ||
| 159 | + this.chartInstance = null; | ||
| 160 | + } | ||
| 161 | + }, | ||
| 162 | + updateChart() { | ||
| 163 | + this.chartInstance.setOption(this.chartOptions); | ||
| 164 | + }, | ||
| 165 | + } | ||
| 166 | +} | ||
| 167 | +</script> | ||
| 168 | + | ||
| 169 | +<style lang="less" scoped> | ||
| 170 | + | ||
| 171 | +</style> |
This diff could not be displayed because it is too large.
src/components/ksia-ext-plan-min.svg
0 → 100644
This diff could not be displayed because it is too large.
src/main.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-07-25 11:01:23 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-07-08 17:48:53 | ||
| 5 | + * @FilePath: /my-data-summary/src/main.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +import { createApp } from 'vue' | ||
| 9 | +import ElementPlus from 'element-plus' | ||
| 10 | +import 'element-plus/dist/index.css' | ||
| 11 | +import App from './App.vue' | ||
| 12 | +import router from './router'; | ||
| 13 | +import axios from '@/utils/axios'; | ||
| 14 | + | ||
| 15 | +import { createPinia } from 'pinia'; | ||
| 16 | +// router.afterEach((to, from, next) => { | ||
| 17 | +// // window.scrollTo(0, 0); | ||
| 18 | +// }) | ||
| 19 | + | ||
| 20 | +const pinia = createPinia(); | ||
| 21 | +const app = createApp(App); | ||
| 22 | + | ||
| 23 | +app.config.globalProperties.$http = axios; // 关键语句 | ||
| 24 | + | ||
| 25 | +app.use(router).use(ElementPlus).use(pinia).mount('#app'); |
src/mock/detail.js
0 → 100644
This diff is collapsed. Click to expand it.
src/mock/nav.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-07-18 12:57:31 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-07-21 17:03:02 | ||
| 5 | + * @FilePath: /front/src/mock/nav.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +const data = [{ | ||
| 9 | + title: '首页', | ||
| 10 | + link: '/', | ||
| 11 | + sub: [] | ||
| 12 | +}, { | ||
| 13 | + title: '走进寺院', | ||
| 14 | + link: '/temple', | ||
| 15 | + sub: [] | ||
| 16 | +}, { | ||
| 17 | + title: '寺院新闻', | ||
| 18 | + link: '', | ||
| 19 | + sub: [{ | ||
| 20 | + id: 'xxx', | ||
| 21 | + title: '公告', | ||
| 22 | + link: '/column' | ||
| 23 | + }, { | ||
| 24 | + title: '招聘', | ||
| 25 | + link: '' | ||
| 26 | + }, { | ||
| 27 | + title: '新闻', | ||
| 28 | + link: '' | ||
| 29 | + }] | ||
| 30 | +}, { | ||
| 31 | + title: '智慧课堂', | ||
| 32 | + link: '', | ||
| 33 | + sub: [{ | ||
| 34 | + title: '活动与咨询', | ||
| 35 | + link: '' | ||
| 36 | + }, { | ||
| 37 | + title: '福田功德', | ||
| 38 | + link: '' | ||
| 39 | + }, { | ||
| 40 | + title: '广结善缘', | ||
| 41 | + link: '' | ||
| 42 | + }] | ||
| 43 | +}, { | ||
| 44 | + title: '弘法利生', | ||
| 45 | + link: '', | ||
| 46 | + sub: [{ | ||
| 47 | + title: '法务活动', | ||
| 48 | + link: '' | ||
| 49 | + }, { | ||
| 50 | + title: '本源法师开示', | ||
| 51 | + link: '' | ||
| 52 | + }, { | ||
| 53 | + title: '短期出家', | ||
| 54 | + link: '' | ||
| 55 | + }, { | ||
| 56 | + title: '闻思修慧', | ||
| 57 | + link: '' | ||
| 58 | + }, { | ||
| 59 | + title: '素食护生', | ||
| 60 | + link: '' | ||
| 61 | + }, { | ||
| 62 | + title: '妙智学堂', | ||
| 63 | + link: '' | ||
| 64 | + }] | ||
| 65 | +}, { | ||
| 66 | + title: '义工之家', | ||
| 67 | + link: '', | ||
| 68 | + sub: [{ | ||
| 69 | + title: '义工之家', | ||
| 70 | + link: '' | ||
| 71 | + }] | ||
| 72 | +}, { | ||
| 73 | + title: '普明慈善基金会', | ||
| 74 | + link: '/foundation', | ||
| 75 | + sub: [] | ||
| 76 | +}, { | ||
| 77 | + title: '生命关怀', | ||
| 78 | + link: '', | ||
| 79 | + sub: [{ | ||
| 80 | + title: '生命关怀', | ||
| 81 | + link: '' | ||
| 82 | + }] | ||
| 83 | +}] | ||
| 84 | + | ||
| 85 | +export default data |
src/mock/routes.js
0 → 100644
| 1 | +const routes = [{ | ||
| 2 | + path: '/image', | ||
| 3 | + redirect: '', | ||
| 4 | + name: 'html转图片', | ||
| 5 | + component: 'html2canvas', | ||
| 6 | + keepAlive: '', | ||
| 7 | + meta: { | ||
| 8 | + title: 'html转图片', | ||
| 9 | + name: '' | ||
| 10 | + }, | ||
| 11 | + children: [{ | ||
| 12 | + path: 'children', | ||
| 13 | + redirect: '', | ||
| 14 | + name: 'html转图片', | ||
| 15 | + component: 'children-test', | ||
| 16 | + keepAlive: '', | ||
| 17 | + meta: { | ||
| 18 | + title: 'html转图片', | ||
| 19 | + name: '' | ||
| 20 | + } | ||
| 21 | + }] | ||
| 22 | +}] | ||
| 23 | +// const routes = [] | ||
| 24 | + | ||
| 25 | +export default routes |
src/mock/swipe.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-07-18 15:05:39 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-07-22 14:34:25 | ||
| 5 | + * @FilePath: /front/src/mock/swipe.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +const data = [{ | ||
| 9 | + id: '1', | ||
| 10 | + src: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | ||
| 11 | + title: '文章1', | ||
| 12 | + link: '/detail' | ||
| 13 | +}, { | ||
| 14 | + id: '2', | ||
| 15 | + src: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | ||
| 16 | + title: '文章2', | ||
| 17 | + link: '/detail' | ||
| 18 | +}, { | ||
| 19 | + id: '3', | ||
| 20 | + src: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg', | ||
| 21 | + title: '文章3', | ||
| 22 | + link: '/detail' | ||
| 23 | +}] | ||
| 24 | +export default data |
src/mock/video_list.js
0 → 100644
This diff is collapsed. Click to expand it.
src/mock/video_list1.js
0 → 100644
This diff is collapsed. Click to expand it.
src/route.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-07-18 10:22:22 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-07-08 17:22:58 | ||
| 5 | + * @FilePath: /custom_dashboard/src/route.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +export default [{ | ||
| 9 | + path: '/', | ||
| 10 | + component: () => import('@/views/index.vue'), | ||
| 11 | + meta: { | ||
| 12 | + title: '首页', | ||
| 13 | + } | ||
| 14 | +}]; |
src/router.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-05-26 13:57:28 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-06-29 21:36:59 | ||
| 5 | + * @FilePath: /tswj/src/router.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +import { createRouter, createWebHashHistory } from 'vue-router'; | ||
| 9 | +import RootRoute from './route.js'; | ||
| 10 | +import asyncRoutesArr from "./mock/routes" | ||
| 11 | +import generateRoutes from './utils/generateRoute' | ||
| 12 | + | ||
| 13 | +// TAG: 路由配置表 | ||
| 14 | +/** | ||
| 15 | + * 把项目独有的路由配置到相应的路径,默认路由文件只放公用部分 | ||
| 16 | + * 但是 vue 文件内容还是要事先准备好 | ||
| 17 | + */ | ||
| 18 | +const modules = import.meta.globEager('@/router/routes/modules/**/*.js'); // Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块 | ||
| 19 | +const routeModuleList = []; | ||
| 20 | + | ||
| 21 | +Object.keys(modules).forEach((key) => { | ||
| 22 | + const mod = modules[key].default || {}; | ||
| 23 | + const modList = Array.isArray(mod) ? [...mod] : [mod]; | ||
| 24 | + routeModuleList.push(...modList); | ||
| 25 | +}); | ||
| 26 | + | ||
| 27 | +// 创建路由实例并传递 `routes` 配置 | ||
| 28 | +const router = createRouter({ | ||
| 29 | + history: createWebHashHistory('/index.html'), | ||
| 30 | + routes: [...RootRoute, ...routeModuleList] | ||
| 31 | +}); | ||
| 32 | + | ||
| 33 | +// TAG: 动态生成路由 | ||
| 34 | +/** | ||
| 35 | + * generateRoute 负责把后台返回数据拼接成项目需要的路由结构,动态添加到路由表里面 | ||
| 36 | + */ | ||
| 37 | +router.beforeEach((to, from, next) => { | ||
| 38 | + // 使用404为中转页面,避免动态路由没有渲染出来,控制台报警告问题 | ||
| 39 | + if (to.path == '/404' && to.redirectedFrom != undefined) { | ||
| 40 | + // 模拟异步操作 | ||
| 41 | + setTimeout(() => { | ||
| 42 | + if (!asyncRoutesArr.length) return; // 没有动态路由避免报错 | ||
| 43 | + const arr = generateRoutes(asyncRoutesArr); // 在路由守卫处生成,避免有子路由时刷新白屏问题。 | ||
| 44 | + arr.forEach(item => { | ||
| 45 | + router.addRoute(item) // 新增路由 | ||
| 46 | + }) | ||
| 47 | + // 重写被404覆盖路由信息 | ||
| 48 | + next({ ...to.redirectedFrom, replace: true }); | ||
| 49 | + }, 1000); | ||
| 50 | + } else { | ||
| 51 | + next() | ||
| 52 | + } | ||
| 53 | +}) | ||
| 54 | + | ||
| 55 | +router.afterEach(() => { | ||
| 56 | + // console.warn(to); | ||
| 57 | + // console.warn(wx); | ||
| 58 | + // share(to) | ||
| 59 | +}) | ||
| 60 | + | ||
| 61 | +export default router; |
src/router/routes/modules/auth/index.js
0 → 100644
src/router/routes/modules/common/index.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-06-15 17:09:03 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-07-18 10:54:32 | ||
| 5 | + * @FilePath: /front/src/router/routes/modules/common/index.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +const index = [{ // 配置404为动态路由中转页面 | ||
| 9 | + path: '/:pathMatch(.*)*', | ||
| 10 | + redirect: '/404' | ||
| 11 | +}, { | ||
| 12 | + path: '/404', | ||
| 13 | + name: '404', | ||
| 14 | + component: () => import('@/views/404.vue'), | ||
| 15 | + meta: { | ||
| 16 | + icon: '', | ||
| 17 | + title: '404', | ||
| 18 | + }, | ||
| 19 | + children: [], | ||
| 20 | +}]; | ||
| 21 | + | ||
| 22 | +export default index; |
src/store/index.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-04-18 15:59:42 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2023-03-03 10:10:27 | ||
| 5 | + * @FilePath: /data-table/src/store/index.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +import { defineStore } from 'pinia'; | ||
| 9 | +// import { testStore } from './test'; // 另一个store | ||
| 10 | +import _ from 'lodash'; | ||
| 11 | +import { useRouter } from 'vue-router' | ||
| 12 | + | ||
| 13 | +export const mainStore = defineStore('main', { | ||
| 14 | + state: () => { | ||
| 15 | + return { | ||
| 16 | + msg: 'Hello world', | ||
| 17 | + count: 0, | ||
| 18 | + auth: false, | ||
| 19 | + comment_num: 0, | ||
| 20 | + video_detail: {}, | ||
| 21 | + scrollTop: 0, | ||
| 22 | + scrollTopCollection: 0, | ||
| 23 | + scrollTopLike: 0, | ||
| 24 | + scrollTopPerson: 0, | ||
| 25 | + keepPages: ['default'], // 很坑爹,空值全部都缓存 | ||
| 26 | + fieldName: '', | ||
| 27 | + formInfo: {}, // 表单字段信息 | ||
| 28 | + formSetting: {}, // 表单数据收集设置 | ||
| 29 | + successInfo: {}, // 表单提交返回值 | ||
| 30 | + }; | ||
| 31 | + }, | ||
| 32 | + getters: { | ||
| 33 | + getKeepPages () { | ||
| 34 | + return this.keepPages | ||
| 35 | + }, | ||
| 36 | + // getTestStoreList () { | ||
| 37 | + // return testStore().list // 返回另一个store的值 | ||
| 38 | + // } | ||
| 39 | + }, | ||
| 40 | + actions: { | ||
| 41 | + changeState (state) { | ||
| 42 | + this.auth = state; | ||
| 43 | + }, | ||
| 44 | + changeCommentNum (num) { | ||
| 45 | + this.comment_num = num; | ||
| 46 | + }, | ||
| 47 | + changeVideoDetail (v) { | ||
| 48 | + this.video_detail = v; | ||
| 49 | + }, | ||
| 50 | + changeScrollTop (v) { | ||
| 51 | + this.scrollTop = v; | ||
| 52 | + }, | ||
| 53 | + changeScrollTopCollection (v) { | ||
| 54 | + this.scrollTopCollection = v; | ||
| 55 | + }, | ||
| 56 | + changeScrollTopLike (v) { | ||
| 57 | + this.scrollTopLike = v; | ||
| 58 | + }, | ||
| 59 | + changeScrollTopPerson (v) { | ||
| 60 | + this.scrollTopPerson = v; | ||
| 61 | + }, | ||
| 62 | + changeKeepPages () { // 清空所有缓存,用一个不存在的值覆盖 | ||
| 63 | + this.keepPages = ['default']; | ||
| 64 | + }, | ||
| 65 | + keepThisPage () { // 新增缓存页 | ||
| 66 | + const $router = useRouter(); | ||
| 67 | + const page = $router.currentRoute.value.meta.name; | ||
| 68 | + this.keepPages.push(page); | ||
| 69 | + }, | ||
| 70 | + removeThisPage () { // 删除缓存页 | ||
| 71 | + const $router = useRouter(); | ||
| 72 | + const page = $router.currentRoute.value.meta.name; | ||
| 73 | + _.remove(this.keepPages, item => item === page) | ||
| 74 | + }, | ||
| 75 | + changeFieldName (v) { | ||
| 76 | + this.fieldName = v; | ||
| 77 | + }, | ||
| 78 | + changeFormInfo (v) { | ||
| 79 | + this.formInfo = v; | ||
| 80 | + }, | ||
| 81 | + changeFormSetting (v) { | ||
| 82 | + this.formSetting = v; | ||
| 83 | + }, | ||
| 84 | + changeSuccessInfo (v) { | ||
| 85 | + this.successInfo = v; | ||
| 86 | + }, | ||
| 87 | + }, | ||
| 88 | +}); |
File moved
src/utils/MonitorKeyboard.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-06-20 01:22:50 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-06-20 01:23:18 | ||
| 5 | + * @FilePath: /tswj/src/composables/useMonitorKeyboard.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +/** | ||
| 9 | + * @class 监听虚拟键盘 | ||
| 10 | + * @classdesc 监听虚拟键盘弹出隐藏 | ||
| 11 | + * @public onEnd 结束监听虚拟键盘 | ||
| 12 | + * @public onShow 传递一个回调 监听虚拟键盘弹出 | ||
| 13 | + * @public onHidden 传递一个回调 监听虚拟键盘隐藏 | ||
| 14 | + */ | ||
| 15 | +class MonitorKeyboard { | ||
| 16 | + constructor() { | ||
| 17 | + this.type = this.IsIA(); | ||
| 18 | + this.originalHeight = window.innerHeight; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * @function IsIA 获取设备类型 | ||
| 23 | + * @param 1 Android 2 iOS | ||
| 24 | + */ | ||
| 25 | + IsIA = () => { | ||
| 26 | + const userAgent = typeof window === 'object' ? window.navigator.userAgent : ''; | ||
| 27 | + if (/android/i.test(userAgent)) { | ||
| 28 | + return 1; | ||
| 29 | + } else if (/iPhone|iPod|iPad/i.test(userAgent)) { | ||
| 30 | + return 2; | ||
| 31 | + } | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + // Android系统 | ||
| 35 | + onResize = () => { | ||
| 36 | + //键盘弹起与隐藏都会引起窗口的高度发生变化 | ||
| 37 | + const resizeHeight = window.innerHeight; | ||
| 38 | + | ||
| 39 | + if (this.originalHeight - resizeHeight > 50) { | ||
| 40 | + this.show('Android系统: 软键盘弹出'); | ||
| 41 | + } else { | ||
| 42 | + this.hidden('Android系统: 软键盘收起'); | ||
| 43 | + } | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + // iOS获取焦点 | ||
| 47 | + onFocusin = () => { | ||
| 48 | + this.show('iOS系统:软键盘弹出'); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + // iOS失去焦点 | ||
| 52 | + onFocusout = () => { | ||
| 53 | + this.hidden('iOS系统:软键盘收起'); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * @function onStart 开始监听虚拟键盘 | ||
| 58 | + */ | ||
| 59 | + onStart = () => { | ||
| 60 | + if (this.type == 1) { | ||
| 61 | + // 获取窗口的高度 | ||
| 62 | + window.addEventListener('resize', this.onResize); | ||
| 63 | + } | ||
| 64 | + if (this.type == 2) { | ||
| 65 | + // iOS系统 | ||
| 66 | + window.addEventListener('focusin', this.onFocusin); | ||
| 67 | + window.addEventListener('focusout', this.onFocusout); | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * @function onEnd 结束监听虚拟键盘 | ||
| 73 | + */ | ||
| 74 | + onEnd = () => { | ||
| 75 | + if (this.type == 1) { | ||
| 76 | + //获取窗口的高度 | ||
| 77 | + window.removeEventListener('resize', this.onResize); | ||
| 78 | + } | ||
| 79 | + if (this.type == 2) { | ||
| 80 | + window.removeEventListener('focusin', this.onFocusin); | ||
| 81 | + window.removeEventListener('focusout', this.onFocusout); | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + /** | ||
| 86 | + * @function onShow 传递一个回调函数 | ||
| 87 | + * @param 虚拟键盘弹出时触发 | ||
| 88 | + */ | ||
| 89 | + onShow = (fn) => { | ||
| 90 | + this.show = fn; | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + /** | ||
| 94 | + * @function onHidden 传递一个回调函数 | ||
| 95 | + * @param 虚拟键盘隐藏时触发 | ||
| 96 | + */ | ||
| 97 | + onHidden = (fn) => { | ||
| 98 | + this.hidden = fn; | ||
| 99 | + } | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +export default MonitorKeyboard |
src/utils/axios.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Author: hookehuyr hookehuyr@gmail.com | ||
| 3 | + * @Date: 2022-05-28 10:17:40 | ||
| 4 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 5 | + * @LastEditTime: 2022-12-01 16:33:51 | ||
| 6 | + * @FilePath: /data-table/src/utils/axios.js | ||
| 7 | + * @Description: | ||
| 8 | + */ | ||
| 9 | +import axios from 'axios'; | ||
| 10 | +import router from '@/router'; | ||
| 11 | +import qs from 'Qs' | ||
| 12 | +import { strExist } from '@/utils/tools' | ||
| 13 | +// import { parseQueryString } from '@/utils/tools' | ||
| 14 | + | ||
| 15 | +axios.defaults.params = { | ||
| 16 | + f: 'custom_form', | ||
| 17 | +}; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * @description 请求拦截器 | ||
| 21 | + */ | ||
| 22 | +axios.interceptors.request.use( | ||
| 23 | + config => { | ||
| 24 | + // const url_params = parseQueryString(location.href); | ||
| 25 | + // GET请求默认打上时间戳,避免从缓存中拿数据。 | ||
| 26 | + const timestamp = config.method === 'get' ? (new Date()).valueOf() : ''; | ||
| 27 | + /** | ||
| 28 | + * POST PHP需要修改数据格式 | ||
| 29 | + * 序列化POST请求时需要屏蔽上传相关接口,上传相关接口序列化后报错 | ||
| 30 | + */ | ||
| 31 | + // config.data = config.method === 'post' && !strExist(['a=upload', 'upload.qiniup.com'], config.url) ? qs.stringify(config.data) : config.data; | ||
| 32 | + // 绑定默认请求头 | ||
| 33 | + config.params = { ...config.params, timestamp } | ||
| 34 | + return config; | ||
| 35 | + }, | ||
| 36 | + error => { | ||
| 37 | + // 请求错误处理 | ||
| 38 | + return Promise.reject(error); | ||
| 39 | + }); | ||
| 40 | + | ||
| 41 | +/** | ||
| 42 | + * @description 响应拦截器 | ||
| 43 | + */ | ||
| 44 | +axios.interceptors.response.use( | ||
| 45 | + response => { | ||
| 46 | + return response; | ||
| 47 | + }, | ||
| 48 | + error => { | ||
| 49 | + return Promise.reject(error); | ||
| 50 | + }); | ||
| 51 | + | ||
| 52 | +export default axios; |
src/utils/fp3.js
0 → 100644
This diff is collapsed. Click to expand it.
src/utils/generateIcons.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-07-18 10:22:22 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-08-22 18:23:07 | ||
| 5 | + * @FilePath: /front/src/utils/generateIcons.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +import icon_nav from '@images/icon/nav.png' | ||
| 9 | +import icon_gz from '@images/icon/icon_gz.png' | ||
| 10 | + | ||
| 11 | +export { | ||
| 12 | + icon_nav, | ||
| 13 | + icon_gz, | ||
| 14 | +} |
src/utils/generateModules.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Author: hookehuyr hookehuyr@gmail.com | ||
| 3 | + * @Date: 2022-05-17 11:17:58 | ||
| 4 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 5 | + * @LastEditTime: 2022-07-18 10:42:12 | ||
| 6 | + * @FilePath: /front/src/utils/generateModules.js | ||
| 7 | + * @Description: | ||
| 8 | + */ | ||
| 9 | +import MuiVideo from '@/components/MuiVideo/index.vue' | ||
| 10 | + | ||
| 11 | +export { | ||
| 12 | + MuiVideo, | ||
| 13 | +} |
src/utils/generatePackage.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-05-17 11:26:03 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-08-05 15:18:06 | ||
| 5 | + * @FilePath: /front/src/utils/generatePackage.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +import Cookies from 'js-cookie' | ||
| 9 | +import $ from 'jquery' | ||
| 10 | +import _ from 'lodash' | ||
| 11 | +import dayjs from 'dayjs' | ||
| 12 | +import axios from '@/utils/axios'; | ||
| 13 | +import { storeToRefs } from 'pinia' | ||
| 14 | +import { mainStore } from '@/store' | ||
| 15 | +import { Toast, Dialog } from 'vant'; | ||
| 16 | +import { wxInfo, hasEllipsis } from '@/utils/tools'; | ||
| 17 | +import { useTitle } from '@vueuse/core' | ||
| 18 | + | ||
| 19 | +export { | ||
| 20 | + Cookies, | ||
| 21 | + $, | ||
| 22 | + _, | ||
| 23 | + axios, | ||
| 24 | + storeToRefs, | ||
| 25 | + mainStore, | ||
| 26 | + Toast, | ||
| 27 | + Dialog, | ||
| 28 | + wxInfo, | ||
| 29 | + hasEllipsis, | ||
| 30 | + useTitle, | ||
| 31 | + dayjs | ||
| 32 | +} |
src/utils/generateRoute.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-05-16 17:21:45 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-06-29 17:00:15 | ||
| 5 | + * @FilePath: /tswj/src/utils/generateRoute.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 根据后台返回的路径,生成页面的组件模版 | ||
| 11 | + * @param {*} component | ||
| 12 | + * @returns 模版地址 | ||
| 13 | + */ | ||
| 14 | +function loadView(component) { | ||
| 15 | + return () => import(`../views/${component}.vue`) | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * 生成路由结构 | ||
| 20 | + * @param {*} routes | ||
| 21 | + */ | ||
| 22 | +const generateRoutes = (routes) => { | ||
| 23 | + const arr = [] | ||
| 24 | + routes.forEach(route => { | ||
| 25 | + const router = {} | ||
| 26 | + const { | ||
| 27 | + path, | ||
| 28 | + redirect, | ||
| 29 | + name, | ||
| 30 | + component, | ||
| 31 | + keepAlive, | ||
| 32 | + meta, | ||
| 33 | + children | ||
| 34 | + } = route | ||
| 35 | + | ||
| 36 | + router.path = path | ||
| 37 | + redirect && (router.redirect = redirect) | ||
| 38 | + name && (router.name = name) | ||
| 39 | + router.component = loadView(component) | ||
| 40 | + keepAlive && (router.keepAlive = keepAlive) | ||
| 41 | + meta && (router.meta = meta) | ||
| 42 | + router.children = !Array.isArray(children) || generateRoutes(children); | ||
| 43 | + arr.push(router) | ||
| 44 | + }) | ||
| 45 | + return arr | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +export default generateRoutes; |
src/utils/qetag.js
0 → 100644
| 1 | +import sha1 from "js-sha1"; | ||
| 2 | + | ||
| 3 | +function getEtag(buffer, callback) { | ||
| 4 | + // sha1算法 | ||
| 5 | + var shA1 = sha1.digest; | ||
| 6 | + | ||
| 7 | + // 以4M为单位分割 | ||
| 8 | + var blockSize = 4 * 1024 * 1024; | ||
| 9 | + var sha1String = []; | ||
| 10 | + var prefix = 0x16; | ||
| 11 | + var blockCount = 0; | ||
| 12 | + | ||
| 13 | + var bufferSize = buffer.size || buffer.length || buffer.byteLength; | ||
| 14 | + blockCount = Math.ceil(bufferSize / blockSize); | ||
| 15 | + | ||
| 16 | + for (var i = 0; i < blockCount; i++) { | ||
| 17 | + sha1String.push(shA1(buffer.slice(i * blockSize, (i + 1) * blockSize))); | ||
| 18 | + } | ||
| 19 | + function concatArr2Uint8(s) {//Array 2 Uint8Array | ||
| 20 | + var tmp = []; | ||
| 21 | + for (var i of s) tmp = tmp.concat(i); | ||
| 22 | + return new Uint8Array(tmp); | ||
| 23 | + } | ||
| 24 | + function Uint8ToBase64(u8Arr, urisafe) {//Uint8Array 2 Base64 | ||
| 25 | + var CHUNK_SIZE = 0x8000; //arbitrary number | ||
| 26 | + var index = 0; | ||
| 27 | + var length = u8Arr.length; | ||
| 28 | + var result = ''; | ||
| 29 | + var slice; | ||
| 30 | + while (index < length) { | ||
| 31 | + slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length)); | ||
| 32 | + result += String.fromCharCode.apply(null, slice); | ||
| 33 | + index += CHUNK_SIZE; | ||
| 34 | + } | ||
| 35 | + return urisafe ? btoa(result).replace(/\//g, '_').replace(/\+/g, '-') : btoa(result); | ||
| 36 | + } | ||
| 37 | + function calcEtag() { | ||
| 38 | + if (!sha1String.length) return 'Fto5o-5ea0sNMlW_75VgGJCv2AcJ'; | ||
| 39 | + var sha1Buffer = concatArr2Uint8(sha1String); | ||
| 40 | + // 如果大于4M,则对各个块的sha1结果再次sha1 | ||
| 41 | + if (blockCount > 1) { | ||
| 42 | + prefix = 0x96; | ||
| 43 | + sha1Buffer = shA1(sha1Buffer.buffer); | ||
| 44 | + } else { | ||
| 45 | + sha1Buffer = Array.apply([], sha1Buffer); | ||
| 46 | + } | ||
| 47 | + sha1Buffer = concatArr2Uint8([[prefix], sha1Buffer]); | ||
| 48 | + return Uint8ToBase64(sha1Buffer, true); | ||
| 49 | + } | ||
| 50 | + return (calcEtag()); | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +export { getEtag } |
src/utils/sha1.js
0 → 100644
This diff is collapsed. Click to expand it.
src/utils/tools.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2022-04-18 15:59:42 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2023-02-24 16:13:06 | ||
| 5 | + * @FilePath: /data-table/src/utils/tools.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +import dayjs from 'dayjs'; | ||
| 9 | + | ||
| 10 | +// 格式化时间 | ||
| 11 | +const formatDate = (date) => { | ||
| 12 | + return dayjs(date).format('YYYY-MM-DD HH:mm'); | ||
| 13 | +}; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * @description 判断浏览器属于平台 | ||
| 17 | + * @returns | ||
| 18 | + */ | ||
| 19 | +const wxInfo = () => { | ||
| 20 | + let u = navigator.userAgent; | ||
| 21 | + let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //android终端或者uc浏览器 | ||
| 22 | + let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端 | ||
| 23 | + let isMobile = u.indexOf('Android') > -1 || u.indexOf('iPhone') > -1 || u.indexOf('iPad') > -1; // 移动端平台 | ||
| 24 | + let isIpad = u.indexOf('iPad') > -1; // iPad平台 | ||
| 25 | + let uAgent = navigator.userAgent.toLowerCase(); | ||
| 26 | + let isWeiXin = (uAgent.match(/MicroMessenger/i) == 'micromessenger') ? true : false; | ||
| 27 | + let isPC = (uAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|micromessenger)/i)) ? false : true; | ||
| 28 | + return { | ||
| 29 | + isAndroid, | ||
| 30 | + isiOS, | ||
| 31 | + isWeiXin, | ||
| 32 | + isMobile, | ||
| 33 | + isIpad, | ||
| 34 | + isPC | ||
| 35 | + }; | ||
| 36 | +}; | ||
| 37 | + | ||
| 38 | +/** | ||
| 39 | + * @description 判断多行省略文本 | ||
| 40 | + * @param {*} id 目标dom标签 | ||
| 41 | + * @returns | ||
| 42 | + */ | ||
| 43 | +const hasEllipsis = (id) => { | ||
| 44 | + let oDiv = document.getElementById(id); | ||
| 45 | + let flag = false; | ||
| 46 | + if (oDiv.scrollHeight > oDiv.clientHeight) { | ||
| 47 | + flag = true | ||
| 48 | + } | ||
| 49 | + return flag | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +/** | ||
| 53 | + * @description 解析URL参数 | ||
| 54 | + * @param {*} url | ||
| 55 | + * @returns | ||
| 56 | + */ | ||
| 57 | +const parseQueryString = url => { | ||
| 58 | + var json = {}; | ||
| 59 | + var arr = url.indexOf('?') >= 0 ? url.substr(url.indexOf('?') + 1).split('&') : []; | ||
| 60 | + arr.forEach(item => { | ||
| 61 | + var tmp = item.split('='); | ||
| 62 | + json[tmp[0]] = decodeURIComponent(tmp[1]); | ||
| 63 | + }); | ||
| 64 | + return json; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +/** | ||
| 68 | + * 字符串包含字符数组中字符的状态 | ||
| 69 | + * @param {*} array 字符数组 | ||
| 70 | + * @param {*} str 字符串 | ||
| 71 | + * @returns 包含状态 | ||
| 72 | + */ | ||
| 73 | +const strExist = (array, str) => { | ||
| 74 | + const exist = array.filter(arr => { | ||
| 75 | + if (str.indexOf(arr) >= 0) return str; | ||
| 76 | + }) | ||
| 77 | + return exist.length > 0 | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +/** | ||
| 81 | + * 自定义替换参数 | ||
| 82 | + * @param {*} url | ||
| 83 | + * @param {*} arg | ||
| 84 | + * @param {*} arg_val | ||
| 85 | + * @returns | ||
| 86 | + */ | ||
| 87 | +const changeURLArg = (url, arg, arg_val) => { | ||
| 88 | + var pattern = arg + '=([^&]*)'; | ||
| 89 | + var replaceText = arg + '=' + arg_val; | ||
| 90 | + if (url.match(pattern)) { | ||
| 91 | + var tmp = '/(' + arg + '=)([^&]*)/gi'; | ||
| 92 | + tmp = url.replace(eval(tmp), replaceText); | ||
| 93 | + return tmp; | ||
| 94 | + } else { | ||
| 95 | + if (url.match('[\?]')) { | ||
| 96 | + return url + '&' + replaceText; | ||
| 97 | + } else { | ||
| 98 | + return url + '?' + replaceText; | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | + return url + '\n' + arg + '\n' + arg_val; | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +// 获取参数key/value值对 | ||
| 105 | +const getUrlParams = (url) => { | ||
| 106 | + // 没有参数处理 | ||
| 107 | + if (url.split('?').length === 1) return false; | ||
| 108 | + let arr = url.split('?'); | ||
| 109 | + let res = arr[1].split('&'); | ||
| 110 | + let items = {}; | ||
| 111 | + for (let i = 0; i < res.length; i++) { | ||
| 112 | + let [key, value] = res[i].split('='); | ||
| 113 | + items[key] = value; | ||
| 114 | + } | ||
| 115 | + return items | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +// 格式化URL参数为字符串 | ||
| 119 | +const stringifyQuery = (params) => { | ||
| 120 | + const queryString = []; | ||
| 121 | + Object.keys(params || {}).forEach((k) => { | ||
| 122 | + queryString.push(k + '=' + params[k]); | ||
| 123 | + }); | ||
| 124 | + | ||
| 125 | + return '?' + queryString.join('&'); | ||
| 126 | +}; | ||
| 127 | + | ||
| 128 | +export { | ||
| 129 | + formatDate, | ||
| 130 | + wxInfo, | ||
| 131 | + hasEllipsis, | ||
| 132 | + parseQueryString, | ||
| 133 | + strExist, | ||
| 134 | + changeURLArg, | ||
| 135 | + getUrlParams, | ||
| 136 | + stringifyQuery, | ||
| 137 | +}; |
src/utils/vconsole.js
0 → 100644
src/utils/versionUpdater.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2024-02-06 11:38:13 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-02-06 13:04:25 | ||
| 5 | + * @FilePath: /xysBooking/src/utils/versionUpdater.js | ||
| 6 | + * @Description: | ||
| 7 | + */ | ||
| 8 | +/* eslint-disable */ | ||
| 9 | +/** | ||
| 10 | + * @description: 版本更新检查 | ||
| 11 | + * @param {*} time 阈值 | ||
| 12 | + * @return {*} | ||
| 13 | + */ | ||
| 14 | +export class Updater { | ||
| 15 | + constructor(options = {}) { | ||
| 16 | + this.oldScript = []; | ||
| 17 | + this.newScript = []; | ||
| 18 | + this.dispatch = {}; | ||
| 19 | + this.init(); //初始化 | ||
| 20 | + this.timing(options.time); //轮询 | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + async init() { | ||
| 24 | + const html = await this.getHtml(); | ||
| 25 | + this.oldScript = this.parserScript(html); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + async getHtml() { | ||
| 29 | + // TAG: html的位置需要动态修改 | ||
| 30 | + const html = await fetch(import.meta.env.VITE_BASE).then((res) => res.text()); //读取index html | ||
| 31 | + return html; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + parserScript(html) { | ||
| 35 | + const reg = new RegExp(/<script(?:\s+[^>]*)?>(.*?)<\/script\s*>/gi); //script正则 | ||
| 36 | + return html.match(reg); //匹配script标签 | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + //发布订阅通知 | ||
| 40 | + on(key, fn) { | ||
| 41 | + (this.dispatch[key] || (this.dispatch[key] = [])).push(fn); | ||
| 42 | + return this; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + compare(oldArr, newArr) { | ||
| 46 | + const base = oldArr.length; | ||
| 47 | + // 去重 | ||
| 48 | + const arr = Array.from(new Set(oldArr.concat(newArr))); | ||
| 49 | + //如果新旧length 一样无更新 | ||
| 50 | + if (arr.length === base) { | ||
| 51 | + this.dispatch['no-update'].forEach((fn) => { | ||
| 52 | + fn(); | ||
| 53 | + }); | ||
| 54 | + } else { | ||
| 55 | + //否则通知更新 | ||
| 56 | + this.dispatch['update'].forEach((fn) => { | ||
| 57 | + fn(); | ||
| 58 | + }); | ||
| 59 | + } | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + timing(time = 10000) { | ||
| 63 | + //轮询 | ||
| 64 | + setInterval(async () => { | ||
| 65 | + const newHtml = await this.getHtml(); | ||
| 66 | + this.newScript = this.parserScript(newHtml); | ||
| 67 | + this.compare(this.oldScript, this.newScript); | ||
| 68 | + }, time); | ||
| 69 | + } | ||
| 70 | +} |
src/views/404.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2022-06-29 18:18:02 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-07-08 17:25:42 | ||
| 5 | + * @FilePath: /custom_dashboard/src/views/404.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="">404</div> | ||
| 10 | +</template> | ||
| 11 | + | ||
| 12 | +<script setup> | ||
| 13 | +import { ref } from 'vue' | ||
| 14 | +import { useRoute, useRouter } from 'vue-router' | ||
| 15 | + | ||
| 16 | +</script> | ||
| 17 | + | ||
| 18 | +<style lang="less" scoped> | ||
| 19 | + | ||
| 20 | +</style> |
src/views/auth.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2022-08-29 13:55:31 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2022-12-06 20:56:54 | ||
| 5 | + * @FilePath: /data-table/src/views/auth.vue | ||
| 6 | + * @Description: 授权模块 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div /> | ||
| 10 | +</template> | ||
| 11 | + | ||
| 12 | +<script setup> | ||
| 13 | +import { onMounted } from 'vue' | ||
| 14 | +import { useRoute } from 'vue-router' | ||
| 15 | + | ||
| 16 | +const $route = useRoute(); | ||
| 17 | + | ||
| 18 | +onMounted(() => { | ||
| 19 | + // php需要先跳转链接获取openid | ||
| 20 | + /** | ||
| 21 | + * encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。 | ||
| 22 | + * 该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。 | ||
| 23 | + * 其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。 | ||
| 24 | + */ | ||
| 25 | + let raw_url = encodeURIComponent(location.origin + location.pathname + $route.query.href); // 未授权的地址 | ||
| 26 | + // TAG: 开发环境测试数据 | ||
| 27 | + const short_url = `/srv/?f=custom_form&a=openid&res=${raw_url}&form_code=${$route.query.code}`; | ||
| 28 | + location.href = import.meta.env.DEV | ||
| 29 | + ? `${short_url}&openid=${import.meta.env.VITE_OPENID}` | ||
| 30 | + : `${short_url}`; | ||
| 31 | +}) | ||
| 32 | +</script> |
src/views/index.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2024-07-08 17:06:30 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-07-08 17:37:15 | ||
| 5 | + * @FilePath: /custom_dashboard/src/views/index.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="mb-4"> | ||
| 10 | + <el-button>Default</el-button> | ||
| 11 | + <el-button type="primary">Primary</el-button> | ||
| 12 | + <el-button type="success">Success</el-button> | ||
| 13 | + <el-button type="info">Info</el-button> | ||
| 14 | + <el-button type="warning">Warning</el-button> | ||
| 15 | + <el-button type="danger">Danger</el-button> | ||
| 16 | + </div> | ||
| 17 | +</template> | ||
| 18 | + | ||
| 19 | +<script setup> | ||
| 20 | +import { ref, onMounted } from 'vue' | ||
| 21 | +import { useRoute, useRouter } from 'vue-router' | ||
| 22 | + | ||
| 23 | +onMounted(() => { | ||
| 24 | + console.warn('onMounted'); | ||
| 25 | +}) | ||
| 26 | + | ||
| 27 | +</script> | ||
| 28 | + | ||
| 29 | +<style lang="less" scoped> | ||
| 30 | + | ||
| 31 | +</style> |
src/views/test.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2024-04-02 17:03:26 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-05-17 16:37:21 | ||
| 5 | + * @FilePath: /custom_dashboard/src/views/test.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div style=""> | ||
| 10 | + <!--<svg width="500" height="500" viewBox="0 0 900 900"> | ||
| 11 | + <!~~ 定义裁剪路径 ~~> | ||
| 12 | + <defs> | ||
| 13 | + <clipPath id="clippath"> | ||
| 14 | + <!~~ 使用有效的路径来定义裁剪形状 ~~> | ||
| 15 | + <path d="M0 0 L300 0 L300 110 A40 40 180 0 1 300 190 L300 300 L190 300 A40 40 180 0 0 110 300 L0 300 Z" /> | ||
| 16 | + </clipPath> | ||
| 17 | + </defs> | ||
| 18 | + | ||
| 19 | + <!~~ 应用遮罩和裁剪路径到图像 ~~> | ||
| 20 | + <image width="900" height="900" :href="imageSrc" style="clip-path: url(#clippath); filter: grayscale(100%);" mask="url(#mask)" /> | ||
| 21 | + </svg>--> | ||
| 22 | + <!--<div style="width: 100%; height: 100%;" class="boxer" > | ||
| 23 | + <!~~ <div style="width: 100%; height: 100%;" > ~~> | ||
| 24 | + <svg width="100%" height="100%" viewBox="0 0 100 100"> | ||
| 25 | + <!~~ 图像 ~~> | ||
| 26 | + <!~~ <image style="width: 100%; height: 100%;" :href="imageSrc" /> ~~> | ||
| 27 | + | ||
| 28 | + <!~~ 第一个格子的遮罩层 ~~> | ||
| 29 | + <polygon points="0,0 20,0 20,20 0,20" fill="black" opacity="0.5" /> | ||
| 30 | + | ||
| 31 | + <!~~ 第二个格子的遮罩层 ~~> | ||
| 32 | + <polygon points="10,10 30,10 30,30 10,30 10,20 20,20 20,10 10,10" fill="black" opacity="0.5" /> | ||
| 33 | + </svg> | ||
| 34 | + </div>--> | ||
| 35 | + | ||
| 36 | + <!-- <button @click="changeColor">改变颜色</button> --> | ||
| 37 | + | ||
| 38 | + <!-- <div class="container-t"> --> | ||
| 39 | + <!-- <div class="shape shape-t"> | ||
| 40 | + Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corrupti recusandae fugiat dicta ipsam ex non sunt maiores, nisi animi repellendus fugit facilis. Vitae pariatur cupiditate totam laboriosam optio! Qui, enim. | ||
| 41 | + </div> --> | ||
| 42 | + <!-- <div class="shape shape1"></div> | ||
| 43 | + <div class="shape shape2"></div> | ||
| 44 | + <div class="shape shape3"></div> | ||
| 45 | + <div class="shape shape4"></div> --> | ||
| 46 | + <!-- </div> --> | ||
| 47 | + <!-- <div class="container"> | ||
| 48 | + <img src="https://cdn.ipadbiz.cn/tmp/fx_park/s1.png" class="img"> | ||
| 49 | + </div> | ||
| 50 | + <div class="container"> | ||
| 51 | + <img src="https://cdn.ipadbiz.cn/tmp/fx_park/s2.png" class="img"> | ||
| 52 | + </div> | ||
| 53 | + <div class="container"> | ||
| 54 | + <img src="https://cdn.ipadbiz.cn/tmp/fx_park/s3.png" class="img"> | ||
| 55 | + </div> | ||
| 56 | + <div class="container"> | ||
| 57 | + <img src="https://cdn.ipadbiz.cn/tmp/fx_park/s4.png" class="img"> | ||
| 58 | + </div> | ||
| 59 | + <div class="container"> | ||
| 60 | + <img src="https://cdn.ipadbiz.cn/tmp/fx_park/s5.png" class="img"> | ||
| 61 | + </div> | ||
| 62 | + <div class="container"> | ||
| 63 | + <img src="https://cdn.ipadbiz.cn/tmp/fx_park/s6.png" class="img"> | ||
| 64 | + </div> --> | ||
| 65 | + <geo-chart></geo-chart> | ||
| 66 | + | ||
| 67 | + </div> | ||
| 68 | +</template> | ||
| 69 | + | ||
| 70 | +<script> | ||
| 71 | +import mixin from 'common/mixin'; | ||
| 72 | +import GeoChart from '@/components/GeoChart.vue'; | ||
| 73 | +/* | ||
| 74 | +如果希望 <polygon> 的位置和形状能够相对于图片保持不变, | ||
| 75 | +可以考虑使用 viewBox 和 viewBox 中的坐标系来定义 <polygon> 的顶点坐标。 | ||
| 76 | +这样,无论图片大小如何改变,<polygon> 的位置和形状都会相对于图片保持不变。 | ||
| 77 | +使用 viewBox 和 viewBox 中的坐标系来定义 <polygon> 的顶点坐标: | ||
| 78 | +*/ | ||
| 79 | + | ||
| 80 | +export default { | ||
| 81 | + components: { | ||
| 82 | + GeoChart | ||
| 83 | + }, | ||
| 84 | + mixins: [mixin.init], | ||
| 85 | + data () { | ||
| 86 | + return { | ||
| 87 | + imageSrc: 'https://picsum.photos/500/500', | ||
| 88 | + svg_color: 'black', | ||
| 89 | + } | ||
| 90 | + }, | ||
| 91 | + mounted () { | ||
| 92 | + }, | ||
| 93 | + methods: { | ||
| 94 | + changeColor () { | ||
| 95 | + this.svg_color = this.svg_color === 'black' ? 'white' : 'black'; | ||
| 96 | + } | ||
| 97 | + } | ||
| 98 | +} | ||
| 99 | +</script> | ||
| 100 | + | ||
| 101 | +<style lang="less" scoped> | ||
| 102 | +.boxer { | ||
| 103 | + background-image: url('https://picsum.photos/375/729'); | ||
| 104 | + background-repeat: no-repeat; | ||
| 105 | + background-size: cover; | ||
| 106 | + background-position: center; | ||
| 107 | +} | ||
| 108 | + | ||
| 109 | +.container-t { | ||
| 110 | + width: 100%; | ||
| 111 | + height: 100vh; | ||
| 112 | + background-image: url('https://picsum.photos/375/729'); | ||
| 113 | + background-size: cover; | ||
| 114 | + position: relative; | ||
| 115 | + overflow: hidden; /* 确保超出容器部分被隐藏 */ | ||
| 116 | +} | ||
| 117 | +.container { | ||
| 118 | + width: 100%; | ||
| 119 | + height: 100%; | ||
| 120 | + background-size: contain; | ||
| 121 | + position: absolute; | ||
| 122 | + z-index: 1; | ||
| 123 | + top: 0; | ||
| 124 | + left: 0; | ||
| 125 | + background-repeat: no-repeat; | ||
| 126 | +} | ||
| 127 | +.container1 { | ||
| 128 | + width: 100%; | ||
| 129 | + height: 100%; | ||
| 130 | + background-size: contain; | ||
| 131 | + position: absolute; | ||
| 132 | + z-index: 1; | ||
| 133 | + top: 0; | ||
| 134 | + left: 0; | ||
| 135 | + background-repeat: no-repeat; | ||
| 136 | +} | ||
| 137 | +.container2 { | ||
| 138 | + width: 100%; | ||
| 139 | + height: 100%; | ||
| 140 | + background-size: contain; | ||
| 141 | + position: absolute; | ||
| 142 | + z-index: 10; | ||
| 143 | + top: 0; | ||
| 144 | + right: 0; | ||
| 145 | + background-repeat: no-repeat; | ||
| 146 | +} | ||
| 147 | +.container3 { | ||
| 148 | + width: 100%; | ||
| 149 | + height: 100%; | ||
| 150 | + // background-image: url('https://cdn.ipadbiz.cn/tmp/fx_park/s3.png'); | ||
| 151 | + background-size: contain; | ||
| 152 | + position: absolute; | ||
| 153 | + // overflow: hidden; /* 确保超出容器部分被隐藏 */ | ||
| 154 | + z-index: 10; | ||
| 155 | + top: 0; | ||
| 156 | + right: 0; | ||
| 157 | + background-repeat: no-repeat; | ||
| 158 | +} | ||
| 159 | +.container4 { | ||
| 160 | + width: 100%; | ||
| 161 | + height: 100%; | ||
| 162 | + // background-image: url('https://cdn.ipadbiz.cn/tmp/fx_park/s4.png'); | ||
| 163 | + background-size: contain; | ||
| 164 | + position: absolute; | ||
| 165 | + // overflow: hidden; /* 确保超出容器部分被隐藏 */ | ||
| 166 | + z-index: 10; | ||
| 167 | + top: 0; | ||
| 168 | + right: 0; | ||
| 169 | + background-repeat: no-repeat; | ||
| 170 | +} | ||
| 171 | +.container5 { | ||
| 172 | + width: 100%; | ||
| 173 | + height: 100%; | ||
| 174 | + // background-image: url('https://cdn.ipadbiz.cn/tmp/fx_park/s5.png'); | ||
| 175 | + background-size: contain; | ||
| 176 | + position: absolute; | ||
| 177 | + // overflow: hidden; /* 确保超出容器部分被隐藏 */ | ||
| 178 | + z-index: 10; | ||
| 179 | + top: 0; | ||
| 180 | + right: 0; | ||
| 181 | + background-repeat: no-repeat; | ||
| 182 | + background-position: left; | ||
| 183 | +} | ||
| 184 | +.container6 { | ||
| 185 | + width: 100%; | ||
| 186 | + height: 100%; | ||
| 187 | + // background-image: url('https://cdn.ipadbiz.cn/tmp/fx_park/s6.png'); | ||
| 188 | + background-size: contain; | ||
| 189 | + position: absolute; | ||
| 190 | + // overflow: hidden; /* 确保超出容器部分被隐藏 */ | ||
| 191 | + z-index: 10; | ||
| 192 | + bottom: 0; | ||
| 193 | + right: 0; | ||
| 194 | + background-repeat: no-repeat; | ||
| 195 | + background-position: right; | ||
| 196 | +} | ||
| 197 | + | ||
| 198 | +.img { | ||
| 199 | + position: absolute; top: 0; left: 0; width: 100%; object-fit: cover; | ||
| 200 | +} | ||
| 201 | + | ||
| 202 | +.mask { | ||
| 203 | + mask: linear-gradient(to right, transparent, rgb(0, 0, 0)); | ||
| 204 | +} | ||
| 205 | + | ||
| 206 | +.shape { | ||
| 207 | + position: absolute; | ||
| 208 | +} | ||
| 209 | + | ||
| 210 | +.shape-t { | ||
| 211 | + clip-path: polygon(52% 6.67%, 77.67% 10.67%, 90% 28.33%, 94% 54.67%, 86.33% 91%, 51.67% 94%, 22.67% 88.67%, 16.67% 64%, 13.33% 32.33%, 26% 11%); | ||
| 212 | + width: 100%; | ||
| 213 | + height: 100%; | ||
| 214 | + top: 0; | ||
| 215 | + left: 0; | ||
| 216 | + background-color: rgba(119, 119, 119, 0.5); | ||
| 217 | + border: 1px solid rgba(119, 119, 119, 0.5); | ||
| 218 | +} | ||
| 219 | + | ||
| 220 | +.shape1 { | ||
| 221 | + clip-path: polygon(50% 0%, 74% 31%, 54% 82%, 33% 100%, 0 100%, 0% 60%, 0 0); | ||
| 222 | + width: 100%; | ||
| 223 | + height: 100%; | ||
| 224 | + top: 0; | ||
| 225 | + left: 0; | ||
| 226 | + background-color: rgba(119, 119, 119, 0.5); | ||
| 227 | + border: 1px solid rgba(119, 119, 119, 0.5); | ||
| 228 | +} | ||
| 229 | + | ||
| 230 | +.shape2 { | ||
| 231 | + clip-path: polygon(50% 0%, 74% 31%, 54% 82%, 33% 100%, 100% 100%, 100% 54%, 100% 0); | ||
| 232 | + width: 100%; | ||
| 233 | + height: 100%; | ||
| 234 | + top: 0; | ||
| 235 | + right: 0; | ||
| 236 | + background-color: rgba(20, 120, 119, 0.5); | ||
| 237 | +} | ||
| 238 | +</style> |
style.css
0 → 100644
| 1 | +:root { | ||
| 2 | + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; | ||
| 3 | + font-size: 16px; | ||
| 4 | + line-height: 24px; | ||
| 5 | + font-weight: 400; | ||
| 6 | + | ||
| 7 | + color-scheme: light dark; | ||
| 8 | + color: rgba(255, 255, 255, 0.87); | ||
| 9 | + background-color: #242424; | ||
| 10 | + | ||
| 11 | + font-synthesis: none; | ||
| 12 | + text-rendering: optimizeLegibility; | ||
| 13 | + -webkit-font-smoothing: antialiased; | ||
| 14 | + -moz-osx-font-smoothing: grayscale; | ||
| 15 | + -webkit-text-size-adjust: 100%; | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +a { | ||
| 19 | + font-weight: 500; | ||
| 20 | + color: #646cff; | ||
| 21 | + text-decoration: inherit; | ||
| 22 | +} | ||
| 23 | +a:hover { | ||
| 24 | + color: #535bf2; | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +body { | ||
| 28 | + margin: 0; | ||
| 29 | + display: flex; | ||
| 30 | + place-items: center; | ||
| 31 | + min-width: 320px; | ||
| 32 | + min-height: 100vh; | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +h1 { | ||
| 36 | + font-size: 3.2em; | ||
| 37 | + line-height: 1.1; | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +#app { | ||
| 41 | + max-width: 1280px; | ||
| 42 | + margin: 0 auto; | ||
| 43 | + padding: 2rem; | ||
| 44 | + text-align: center; | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +.logo { | ||
| 48 | + height: 6em; | ||
| 49 | + padding: 1.5em; | ||
| 50 | + will-change: filter; | ||
| 51 | +} | ||
| 52 | +.logo:hover { | ||
| 53 | + filter: drop-shadow(0 0 2em #646cffaa); | ||
| 54 | +} | ||
| 55 | +.logo.vanilla:hover { | ||
| 56 | + filter: drop-shadow(0 0 2em #f7df1eaa); | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | +.card { | ||
| 60 | + padding: 2em; | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +.read-the-docs { | ||
| 64 | + color: #888; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +button { | ||
| 68 | + border-radius: 8px; | ||
| 69 | + border: 1px solid transparent; | ||
| 70 | + padding: 0.6em 1.2em; | ||
| 71 | + font-size: 1em; | ||
| 72 | + font-weight: 500; | ||
| 73 | + font-family: inherit; | ||
| 74 | + background-color: #1a1a1a; | ||
| 75 | + cursor: pointer; | ||
| 76 | + transition: border-color 0.25s; | ||
| 77 | +} | ||
| 78 | +button:hover { | ||
| 79 | + border-color: #646cff; | ||
| 80 | +} | ||
| 81 | +button:focus, | ||
| 82 | +button:focus-visible { | ||
| 83 | + outline: 4px auto -webkit-focus-ring-color; | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +@media (prefers-color-scheme: light) { | ||
| 87 | + :root { | ||
| 88 | + color: #213547; | ||
| 89 | + background-color: #ffffff; | ||
| 90 | + } | ||
| 91 | + a:hover { | ||
| 92 | + color: #747bff; | ||
| 93 | + } | ||
| 94 | + button { | ||
| 95 | + background-color: #f9f9f9; | ||
| 96 | + } | ||
| 97 | +} |
tsconfig.json
0 → 100644
| 1 | +{ | ||
| 2 | + "compilerOptions": { | ||
| 3 | + /* 基本选项 */ | ||
| 4 | + "target": "esnext", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT' | ||
| 5 | + "module": "CommonJS", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015' | ||
| 6 | + "lib": [ // 指定要包含在编译中的库文件 | ||
| 7 | + "esnext", | ||
| 8 | + "dom", | ||
| 9 | + "dom.iterable", | ||
| 10 | + "scripthost" | ||
| 11 | + ], | ||
| 12 | + "allowJs": true, // 允许编译 javascript 文件 | ||
| 13 | + // "checkJs": true, // 报告 javascript 文件中的错误 | ||
| 14 | + "jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react' | ||
| 15 | + // "declaration": true, // 生成相应的 '.d.ts' 文件 | ||
| 16 | + // "sourceMap": true, // 生成相应的 '.map' 文件 | ||
| 17 | + // "outFile": "./", // 将输出文件合并为一个文件 | ||
| 18 | + "outDir": "./", // 指定输出目录 | ||
| 19 | + // "rootDir": "./", // 用来控制输出目录结构 --outDir. | ||
| 20 | + "removeComments": true, // 删除编译后的所有的注释 | ||
| 21 | + // "noEmit": true, // 不生成输出文件 | ||
| 22 | + "importHelpers": true, // 从 tslib 导入辅助工具函数 | ||
| 23 | + "isolatedModules": false, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似) | ||
| 24 | + | ||
| 25 | + /* 严格的类型检查选项 */ | ||
| 26 | + "strict": true, // 启用所有严格类型检查选项 | ||
| 27 | + // "noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错 | ||
| 28 | + // "strictNullChecks": true, // 启用严格的 null 检查 | ||
| 29 | + // "noImplicitThis": true, // 当 this 表达式值为 any 类型的时候,生成一个错误 | ||
| 30 | + // "alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict' | ||
| 31 | + | ||
| 32 | + /* 额外的检查 */ | ||
| 33 | + "noUnusedLocals": true, // 有未使用的变量时,抛出错误 | ||
| 34 | + "noUnusedParameters": true, // 有未使用的参数时,抛出错误 | ||
| 35 | + "noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误 | ||
| 36 | + "noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿) | ||
| 37 | + | ||
| 38 | + /* 模块解析选项 */ | ||
| 39 | + "moduleResolution": "node", // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6) | ||
| 40 | + "baseUrl": ".", // 用于解析非相对模块名称的基目录 | ||
| 41 | + "paths": { // 模块名到基于 baseUrl 的路径映射的列表 | ||
| 42 | + "@/*": [ | ||
| 43 | + "src/*" | ||
| 44 | + ] | ||
| 45 | + }, | ||
| 46 | + // "rootDirs": [], // 根文件夹列表,其组合内容表示项目运行时的结构内容 | ||
| 47 | + // "typeRoots": [], // 包含类型声明的文件列表 | ||
| 48 | + "types": [ // 需要包含的类型声明文件名列表 | ||
| 49 | + // "webpack-env", | ||
| 50 | + "vite/client", | ||
| 51 | + "lodash", | ||
| 52 | + "moment", | ||
| 53 | + "node", | ||
| 54 | + "jquery", | ||
| 55 | + "element-plus/global" | ||
| 56 | + ], | ||
| 57 | + "allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。 | ||
| 58 | + | ||
| 59 | + /* Source Map Options */ | ||
| 60 | + // "sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置 | ||
| 61 | + // "mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置 | ||
| 62 | + // "inlineSourceMap": true, // 生成单个 sourcemaps 文件,而不是将 sourcemaps 生成不同的文件 | ||
| 63 | + // "inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性 | ||
| 64 | + | ||
| 65 | + /* 其他选项 */ | ||
| 66 | + "experimentalDecorators": true, // 启用装饰器 | ||
| 67 | + // "emitDecoratorMetadata": true, // 为装饰器提供元数据的支持 | ||
| 68 | + | ||
| 69 | + "esModuleInterop": true, // 可以在es6中导入commonjs | ||
| 70 | + }, | ||
| 71 | + "include": [ | ||
| 72 | + "src/**/*" | ||
| 73 | + ], | ||
| 74 | + "exclude": [ | ||
| 75 | + "node_modules", | ||
| 76 | + "dist" | ||
| 77 | + ], | ||
| 78 | + "vueCompilerOptions": { | ||
| 79 | + "target": 2, | ||
| 80 | + "experimentalSuppressInvalidJsxElementTypeErrors": true | ||
| 81 | + } | ||
| 82 | +} |
vite.config.js
0 → 100644
| 1 | +import vue from '@vitejs/plugin-vue'; | ||
| 2 | +import dynamicImport from 'vite-plugin-dynamic-import'; | ||
| 3 | +// import legacy from '@vitejs/plugin-legacy'; | ||
| 4 | +// import styleImport, { VantResolve } from 'vite-plugin-style-import'; | ||
| 5 | +import { defineConfig, loadEnv } from 'vite'; | ||
| 6 | +import { createProxy } from './build/proxy' | ||
| 7 | +// import { codeInspectorPlugin } from 'code-inspector-plugin'; | ||
| 8 | +import DefineOptions from 'unplugin-vue-define-options/vite'; | ||
| 9 | +import AutoImport from 'unplugin-auto-import/vite'; | ||
| 10 | + | ||
| 11 | +var path = require('path'); | ||
| 12 | +// const { createVuePlugin } = require('vite-plugin-vue2') | ||
| 13 | + | ||
| 14 | +export default ({ command, mode }) => { | ||
| 15 | + const root = process.cwd(); | ||
| 16 | + | ||
| 17 | + const viteEnv = loadEnv(mode, root); | ||
| 18 | + // let isProd = (command === 'serve'); // 情景配置是否为开发模式 serve 或 build | ||
| 19 | + | ||
| 20 | + return defineConfig({ | ||
| 21 | + // root: '', | ||
| 22 | + // root: './src/packages', // 多页面应用配置入口根目录 | ||
| 23 | + base: viteEnv.VITE_BASE, // 开发或生产环境服务的公共基础路径。 | ||
| 24 | + // base: isProd ? '/' : '/f/voice/', // 开发或生产环境服务的公共基础路径。 | ||
| 25 | + // mode: '', // 在配置中指明将会把 serve 和 build 时的模式 都 覆盖掉。也可以通过命令行 --mode 选项来重写。 | ||
| 26 | + // define: '', // 定义全局常量替换方式。其中每项在开发环境下会被定义在全局,而在构建时被静态替换。 | ||
| 27 | + plugins: [ // 将要用到的插件数组。Falsy 虚值的插件将被忽略,插件数组将被扁平化(flatten)。查看 插件 API 获取 Vite 插件的更多细节。 | ||
| 28 | + // createVuePlugin(), | ||
| 29 | + vue(), | ||
| 30 | + // styleImport({ | ||
| 31 | + // resolves: [VantResolve()], | ||
| 32 | + // libs: [ | ||
| 33 | + // { | ||
| 34 | + // libraryName: 'vant', | ||
| 35 | + // esModule: true, | ||
| 36 | + // resolveStyle: name => `../es/${name}/style` | ||
| 37 | + // } | ||
| 38 | + // ] | ||
| 39 | + // }), // 按需引入 vant 位置报错问题 | ||
| 40 | + dynamicImport(), // 增强 Vite 内置的 dynamic import, 支持在 import() 中使用别名 | ||
| 41 | + // legacy({ | ||
| 42 | + // targets: ['defaults', 'not IE 11'] | ||
| 43 | + // }), // Vite 的默认旧版浏览器支持时提供此插件本机ESM的支持。 | ||
| 44 | + // codeInspectorPlugin({ | ||
| 45 | + // bundler: 'vite', | ||
| 46 | + // }), // 点击页面上的元素,能够自动打开你的代码编辑器并将光标定位到元素对应的代码位置。 | ||
| 47 | + DefineOptions(), // TAG: 插件来对组件名进行注册的, 解决setup没法写name的问题 | ||
| 48 | + AutoImport({ // API 自动导入 | ||
| 49 | + // 可以自定义文件生成的位置,默认是根目录下,使用ts的建议放src目录下 | ||
| 50 | + dts: 'src/auto-imports.d.ts', | ||
| 51 | + imports: ['vue', 'vue-router'], | ||
| 52 | + // 解决eslint报错问题 | ||
| 53 | + eslintrc: { | ||
| 54 | + enabled: true | ||
| 55 | + } | ||
| 56 | + }), | ||
| 57 | + ], | ||
| 58 | + publicDir: 'public', // 作为静态资源服务的文件夹。这个目录中的文件会在开发中被服务于 /,在开发模式时,会被拷贝到 outDir 的根目录,并没有转换,永远只是复制到这里。该值可以是文件系统的绝对路径,也可以是相对于项目的根目录路径。 | ||
| 59 | + // cacheDir: '', // 存储缓存文件的目录。此目录下会存储预打包的依赖项或 vite 生成的某些缓存文件,使用缓存可以提高性能。如需重新生成缓存文件,你可以使用 --force 命令行选项或手动删除目录。此选项的值可以是文件的绝对路径,也可以是以项目根目录为基准的相对路径。 | ||
| 60 | + resolve: { | ||
| 61 | + alias: { // 将会被传递到 @rollup/plugin-alias 作为 entries 的选项。也可以是一个对象,或一个 { find, replacement } 的数组. 当使用文件系统路径的别名时,请始终使用绝对路径。相对路径的别名值会被原封不动地使用,因此无法被正常解析。 更高级的自定义解析方法可以通过 插件 实现。 | ||
| 62 | + "@": path.resolve(__dirname, "src"), | ||
| 63 | + "@components": path.resolve(__dirname, "src/components"), | ||
| 64 | + "@utils": path.resolve(__dirname, "src/utils"), | ||
| 65 | + "@images": path.resolve(__dirname, "src/assets/images"), | ||
| 66 | + "@css": path.resolve(__dirname, "src/assets/css"), | ||
| 67 | + "@mock": path.resolve(__dirname, "src/assets/mock"), | ||
| 68 | + "common": path.resolve(__dirname, "src/common"), | ||
| 69 | + "@api": path.resolve(__dirname, "src/api"), | ||
| 70 | + }, | ||
| 71 | + // dedupe: [''], // 如果你在你的应用程序中有相同依赖的副本(比如 monorepos),使用这个选项来强制 Vite 总是将列出的依赖关系解析到相同的副本(从项目根目录)。 | ||
| 72 | + // conditions: [''], // 在解析包的 情景导出 时允许的附加条件。 | ||
| 73 | + // mainFields: [''], // package.json 中,在解析包的入口点时尝试的字段列表。注意,这比从 exports 字段解析的情景导出优先级低:如果一个入口点从 exports 成功解析,主字段将被忽略。 | ||
| 74 | + extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'], // 导入时想要省略的扩展名列表。注意,不 建议忽略自定义导入类型的扩展名(例如:.vue),因为它会干扰 IDE 和类型支持。 | ||
| 75 | + }, | ||
| 76 | + css: { | ||
| 77 | + modules: '', // 配置 CSS modules 的行为。选项将被传递给 postcss-modules。 | ||
| 78 | + postcss: { // 内联的 PostCSS 配置(格式同 postcss.config.js),或者一个(默认基于项目根目录的)自定义的 PostCSS 配置路径。其路径搜索是通过 postcss-load-config 实现的。 注意,如果提供了该内联配置,Vite 将不会搜索其他 PostCSS 配置源。 | ||
| 79 | + plugins: [] | ||
| 80 | + }, | ||
| 81 | + preprocessorOptions: { | ||
| 82 | + less: { | ||
| 83 | + javascriptEnabled: true, | ||
| 84 | + additionalData: `@import "${path.resolve(__dirname, 'src/assets/styles/base.less')}";` | ||
| 85 | + } | ||
| 86 | + } // 指定传递给 CSS 预处理器的选项。 | ||
| 87 | + }, | ||
| 88 | + // json: { | ||
| 89 | + // namedExports: true, // 是否支持从 .json 文件中进行按名导入。 | ||
| 90 | + // stringify: false, // 若设置为 true,导入的 JSON 会被转换为 export default JSON.parse("...") 会比转译成对象字面量性能更好,尤其是当 JSON 文件较大的时候。 开启此项,则会禁用按名导入。 | ||
| 91 | + // }, | ||
| 92 | + // esbuild: false, // | ||
| 93 | + // assetsInclude: '', // 指定其他文件类型作为静态资源处理 | ||
| 94 | + logLevel: 'info', // 调整控制台输出的级别,默认为 'info'。 | ||
| 95 | + // clearScreen: true, // 设为 false 可以避免 Vite 清屏而错过在终端中打印某些关键信息。命令行模式下请通过 --clearScreen false 设置。 | ||
| 96 | + server: { | ||
| 97 | + host: '0.0.0.0', | ||
| 98 | + port: viteEnv.VITE_PORT, // 本地服务端口 | ||
| 99 | + // strictPort: true, // 设为true时若端口已被占用则会直接退出, 而不是尝试下一个可用端口 | ||
| 100 | + // https: '', | ||
| 101 | + // open: false, // 在服务器启动时自动在浏览器中打开应用程序. 当此值为字符串时, 会被当作URL的路径名. | ||
| 102 | + // proxy: { // 代理 | ||
| 103 | + // '/srv/': { | ||
| 104 | + // // target: 'http://voice.onwall.cn', | ||
| 105 | + // target: viteEnv.VITE_PROXY_TARGET, | ||
| 106 | + // changeOrigin: true, | ||
| 107 | + // // rewrite: (path) => path.replace(/^\/api/, '') | ||
| 108 | + // }, | ||
| 109 | + // }, | ||
| 110 | + proxy: createProxy(viteEnv.VITE_PROXY_PREFIX, viteEnv.VITE_PROXY_TARGET), | ||
| 111 | + // cors: '', // 为开发服务器配置 CORS。默认启用并允许任何源,传递一个 选项对象 来调整行为或设为 false 表示禁用。 | ||
| 112 | + // force: '', // 设置为 true 强制使依赖预构建。 | ||
| 113 | + // hmr: '', // 禁用或配置 HMR 连接(用于 HMR websocket 必须使用不同的 http 服务器地址的情况)。 设置 server.hmr.overlay 为 false 可以禁用服务器错误遮罩层。 | ||
| 114 | + // watch: '', // 传递给 chokidar 的文件系统监视器选项。 | ||
| 115 | + }, | ||
| 116 | + build: { | ||
| 117 | + // outDir: 'voice', // 指定输出路径(相对于项目根目录). | ||
| 118 | + outDir: viteEnv.VITE_OUTDIR, // 指定输出路径(相对于项目根目录). | ||
| 119 | + assetsDir: 'static', | ||
| 120 | + rollupOptions: { | ||
| 121 | + output: { | ||
| 122 | + chunkFileNames: 'static/js/[name]-[hash].js', | ||
| 123 | + entryFileNames: 'static/js/[name]-[hash].js', | ||
| 124 | + assetFileNames: 'static/[ext]/[name]-[hash].[ext]', | ||
| 125 | + }, | ||
| 126 | + input: { // 多页面应用模式, 打包时配置,运行配置要处理root | ||
| 127 | + main: path.resolve(__dirname, 'index.html'), | ||
| 128 | + // mono1: path.resolve(__dirname, 'src/packages/mono1/index.html'), | ||
| 129 | + // mono2: path.resolve(__dirname, 'src/packages/mono2/index.html'), | ||
| 130 | + } | ||
| 131 | + }, | ||
| 132 | + }, | ||
| 133 | + optimizeDeps: { | ||
| 134 | + // entries: '', | ||
| 135 | + // exclude: [], | ||
| 136 | + include: ['jquery', 'lodash', 'moment', 'axios', 'vue-router'], // 默认情况下,不在 node_modules 中的,链接的包不会被预构建。使用此选项可强制预构建链接的包。 | ||
| 137 | + // keepNames: false, // 打包器有时需要重命名符号以避免冲突。 设置此项为 true 可以在函数和类上保留 name 属性。 若想获取更多详情,请参阅 keepNames | ||
| 138 | + } | ||
| 139 | + }); | ||
| 140 | +}; |
yarn-error.log
0 → 100644
This diff is collapsed. Click to expand it.
yarn.lock
0 → 100644
This diff could not be displayed because it is too large.
-
Please register or login to post a comment