Compare commits
1 Commits
12257f5769
...
vuetify
Author | SHA1 | Date | |
---|---|---|---|
9ada32765a |
1
.gitattributes
vendored
@ -39,7 +39,6 @@ commit-msg text eol=lf
|
|||||||
*.woff2 binary
|
*.woff2 binary
|
||||||
*.eot binary
|
*.eot binary
|
||||||
*.otf binary
|
*.otf binary
|
||||||
*.spline binary
|
|
||||||
# Add more binary...
|
# Add more binary...
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
### .gitattributes
|
|
||||||
|
|
||||||
如果你先推送了一个.jpg文件,然后再推送包含.gitattributes文件的更新,Git不会自动重新处理之前的.jpg文件的属性。为使.gitattributes中的新规则生效,你可以通过以下步骤重新应用设置:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
1. 删除本地缓存的.jpg文件:git rm --cached <file>.jpg
|
|
||||||
2. 重新添加该文件:git add <file>.jpg
|
|
||||||
3. 再次提交并推送:git commit -m "Apply .gitattributes changes" && git push
|
|
||||||
```
|
|
||||||
|
|
||||||
这样,Git将按照.gitattributes中的新规则处理该文件。
|
|
||||||
|
|
||||||
要验证.gitattributes文件中的二进制配置是否生效,可以使用以下方法:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
1. 推送后验证:先按照之前步骤重新添加并推送.jpg文件。
|
|
||||||
2. 查看差异(diff):执行 git diff,检查文件是否有文本形式的改动。如果是二进制文件,Git不会显示具体内容的差异。
|
|
||||||
3. Git日志验证:执行 git log -p <file>.jpg 查看提交的改动记录,确认文件未受行尾或编码处理的影响。
|
|
||||||
```
|
|
||||||
|
|
||||||
如果以上测试显示该文件未发生不必要的改动,说明.gitattributes配置已生效。
|
|
9
.github/copilot-instructions.md
vendored
@ -1,11 +1,4 @@
|
|||||||
---
|
# Project Conventions and Technical Guidelines
|
||||||
description:
|
|
||||||
globs:
|
|
||||||
alwaysApply: true
|
|
||||||
---
|
|
||||||
# GitHub Copilot Instructions
|
|
||||||
|
|
||||||
本文件定义了项目的代码生成规范,GitHub Copilot 和其他 AI 助手应遵循这些指令。
|
|
||||||
|
|
||||||
This document outlines the core technical choices, coding conventions, and configuration details for this project. Adhering to these guidelines ensures consistency and leverages the project's setup effectively.
|
This document outlines the core technical choices, coding conventions, and configuration details for this project. Adhering to these guidelines ensures consistency and leverages the project's setup effectively.
|
||||||
|
|
||||||
|
3
.github/copilot-instructions_MD
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
```bash
|
||||||
|
ln -s .github/copilot-instructions.md .roorules
|
||||||
|
```
|
2
.github/workflows/lint.yaml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 🛠️ 设置Node环境
|
- name: 🛠️ 设置Node环境
|
||||||
uses: yanhao98/composite-actions/setup-node-environment@b4a2caa64aca72f8aeada59d0df3181a12df8268
|
uses: yanhao98/composite-actions/setup-node-environment@4470aa136359d05ae3b086d37cfaa33305448a5b
|
||||||
- name: 🔍 静态代码分析
|
- name: 🔍 静态代码分析
|
||||||
run: pnpm run lint
|
run: pnpm run lint
|
||||||
- name: 📦 构建项目
|
- name: 📦 构建项目
|
||||||
|
21
.github/workflows/playwright.yaml
vendored
@ -7,13 +7,6 @@ env:
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
run_cleanup:
|
|
||||||
description: '是否运行 Surge 清理 Job'
|
|
||||||
required: false
|
|
||||||
type: boolean
|
|
||||||
default: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
surge:
|
surge:
|
||||||
@ -22,7 +15,7 @@ jobs:
|
|||||||
url: ${{ steps.surge_deploy.outputs.url }}
|
url: ${{ steps.surge_deploy.outputs.url }}
|
||||||
steps:
|
steps:
|
||||||
- name: ⚙️ 设置 Node 环境
|
- name: ⚙️ 设置 Node 环境
|
||||||
uses: yanhao98/composite-actions/setup-node-environment@b4a2caa64aca72f8aeada59d0df3181a12df8268
|
uses: yanhao98/composite-actions/setup-node-environment@4470aa136359d05ae3b086d37cfaa33305448a5b
|
||||||
- name: 🔨 构建项目
|
- name: 🔨 构建项目
|
||||||
run: pnpm run build-only
|
run: pnpm run build-only
|
||||||
env:
|
env:
|
||||||
@ -30,27 +23,21 @@ jobs:
|
|||||||
- name: 🚀 部署到 Surge
|
- name: 🚀 部署到 Surge
|
||||||
id: surge_deploy
|
id: surge_deploy
|
||||||
if: ${{ github.actor != 'nektos/act' }} # https://nektosact.com/usage/index.html#skipping-steps
|
if: ${{ github.actor != 'nektos/act' }} # https://nektosact.com/usage/index.html#skipping-steps
|
||||||
uses: yanhao98/composite-actions/deploy-dist-to-surge@b4a2caa64aca72f8aeada59d0df3181a12df8268
|
uses: yanhao98/composite-actions/deploy-dist-to-surge@4470aa136359d05ae3b086d37cfaa33305448a5b
|
||||||
|
|
||||||
playwright:
|
playwright:
|
||||||
needs: surge
|
needs: surge
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: mcr.microsoft.com/playwright:v1.53.2-noble
|
container: mcr.microsoft.com/playwright:v1.51.1-noble
|
||||||
steps:
|
steps:
|
||||||
- name: ⚙️ 设置 Node 环境
|
- name: ⚙️ 设置 Node 环境
|
||||||
uses: yanhao98/composite-actions/setup-node-environment@b4a2caa64aca72f8aeada59d0df3181a12df8268
|
uses: yanhao98/composite-actions/setup-node-environment@4470aa136359d05ae3b086d37cfaa33305448a5b
|
||||||
# - name: 📥 安装 Playwright 浏览器
|
# - name: 📥 安装 Playwright 浏览器
|
||||||
# run: pnpm exec playwright install --with-deps
|
# run: pnpm exec playwright install --with-deps
|
||||||
- name: ▶️ 运行 Playwright 测试
|
- name: ▶️ 运行 Playwright 测试
|
||||||
run: npx playwright test
|
run: npx playwright test
|
||||||
env:
|
env:
|
||||||
BASE_URL: ${{ needs.surge.outputs.url }}
|
BASE_URL: ${{ needs.surge.outputs.url }}
|
||||||
|
|
||||||
cleanup_surge:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [surge, playwright]
|
|
||||||
if: github.event_name == 'push' || github.event.inputs.run_cleanup == true
|
|
||||||
steps:
|
|
||||||
- name: 🧹 清理 Surge 部署
|
- name: 🧹 清理 Surge 部署
|
||||||
run: npx surge teardown ${{ needs.surge.outputs.url }} --token ${{ env.SURGE_TOKEN}}
|
run: npx surge teardown ${{ needs.surge.outputs.url }} --token ${{ env.SURGE_TOKEN}}
|
||||||
env:
|
env:
|
||||||
|
2
.github/workflows/vercel.yaml
vendored
@ -14,7 +14,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: ⚙️ 设置 Node 环境
|
- name: ⚙️ 设置 Node 环境
|
||||||
uses: yanhao98/composite-actions/setup-node-environment@b4a2caa64aca72f8aeada59d0df3181a12df8268
|
uses: yanhao98/composite-actions/setup-node-environment@4470aa136359d05ae3b086d37cfaa33305448a5b
|
||||||
|
|
||||||
- name: 📥 拉取 Vercel 环境信息
|
- name: 📥 拉取 Vercel 环境信息
|
||||||
run: pnpm dlx vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
|
run: pnpm dlx vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# 此钩子在 pre-commit 钩子成功完成后,用于检查提交消息。
|
# 此钩子在 pre-commit 钩子成功完成后,用于检查提交消息。
|
||||||
echo "📝 [Commit-msg] 正在运行 commit-msg 钩子..."
|
echo "📝 [Commit-msg] 正在运行 commit-msg 钩子..."
|
||||||
echo "当前提交的文件是:$1"
|
# 在这里添加你的 commit message 验证逻辑,例如 commitlint
|
||||||
# npx --no -- commitlint --edit "$1"
|
# npx --no -- commitlint --edit "$1"
|
||||||
pnpm exec commitlint --edit $1
|
|
||||||
echo "✅ [Commit-msg] commit-msg 钩子完成!"
|
echo "✅ [Commit-msg] commit-msg 钩子完成!"
|
||||||
|
2
.npmrc
@ -5,7 +5,7 @@ registry=https://registry.npmjs.org/
|
|||||||
# registry=https://nexus.oo1.dev/repository/npm/
|
# registry=https://nexus.oo1.dev/repository/npm/
|
||||||
|
|
||||||
# https://pnpm.io/zh/npmrc#node-mirrorltreleasedir
|
# https://pnpm.io/zh/npmrc#node-mirrorltreleasedir
|
||||||
use-node-version=22.15.0
|
use-node-version=22.14.0
|
||||||
node-mirror:release=https://npmmirror.com/mirrors/node/ # pnpm config set node-mirror:release=https://npmmirror.com/mirrors/node/
|
node-mirror:release=https://npmmirror.com/mirrors/node/ # pnpm config set node-mirror:release=https://npmmirror.com/mirrors/node/
|
||||||
node-mirror:rc=https://npmmirror.com/mirrors/node-rc/
|
node-mirror:rc=https://npmmirror.com/mirrors/node-rc/
|
||||||
node-mirror:nightly=https://npmmirror.com/mirrors/node-nightly/
|
node-mirror:nightly=https://npmmirror.com/mirrors/node-nightly/
|
||||||
|
3
.vscode/settings.json
vendored
@ -27,7 +27,8 @@
|
|||||||
"source.fixAll.eslint": "never",
|
"source.fixAll.eslint": "never",
|
||||||
"source.fixAll.stylelint": "never",
|
"source.fixAll.stylelint": "never",
|
||||||
"source.fixAll.oxc": "never",
|
"source.fixAll.oxc": "never",
|
||||||
"source.organizeImports": "never"
|
"source.organizeImports": "never",
|
||||||
|
"source.fixAll": "never"
|
||||||
},
|
},
|
||||||
"editor.formatOnSave": false,
|
"editor.formatOnSave": false,
|
||||||
"oxc.enable": true,
|
"oxc.enable": true,
|
||||||
|
30
README.md
@ -15,9 +15,33 @@ pnpm install --registry=https://nexus.oo1.dev/repository/npm
|
|||||||
pnpm run dev
|
pnpm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
### .gitattributes
|
||||||
|
|
||||||
|
如果你先推送了一个.jpg文件,然后再推送包含.gitattributes文件的更新,Git不会自动重新处理之前的.jpg文件的属性。为使.gitattributes中的新规则生效,你可以通过以下步骤重新应用设置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
1. 删除本地缓存的.jpg文件:git rm --cached <file>.jpg
|
||||||
|
2. 重新添加该文件:git add <file>.jpg
|
||||||
|
3. 再次提交并推送:git commit -m "Apply .gitattributes changes" && git push
|
||||||
|
```
|
||||||
|
|
||||||
|
这样,Git将按照.gitattributes中的新规则处理该文件。
|
||||||
|
|
||||||
|
要验证.gitattributes文件中的二进制配置是否生效,可以使用以下方法:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
1. 推送后验证:先按照之前步骤重新添加并推送.jpg文件。
|
||||||
|
2. 查看差异(diff):执行 git diff,检查文件是否有文本形式的改动。如果是二进制文件,Git不会显示具体内容的差异。
|
||||||
|
3. Git日志验证:执行 git log -p <file>.jpg 查看提交的改动记录,确认文件未受行尾或编码处理的影响。
|
||||||
|
```
|
||||||
|
|
||||||
|
如果以上测试显示该文件未发生不必要的改动,说明.gitattributes配置已生效。
|
||||||
|
|
||||||
## Links
|
## Links
|
||||||
|
|
||||||
- https://github.com/hyoban-template/shadcn-vue-unocss-starter
|
- https://github.com/hyoban-template/shadcn-vue-unocss-starter$0
|
||||||
- [Performance API优化页面性能](https://juejin.cn/post/7238779568478552122)
|
- [Performance API优化页面性能](https://juejin.cn/post/7238779568478552122)
|
||||||
- [vitepress-theme-demoblock](https://www.npmjs.com/package/vitepress-theme-demoblock)
|
- [vitepress-theme-demoblock](https://www.npmjs.com/package/vitepress-theme-demoblock)
|
||||||
- [Vite PWA](https://vite-pwa-org-zh.netlify.app/guide/)
|
- [Vite PWA](https://vite-pwa-org-zh.netlify.app/guide/)
|
||||||
@ -29,12 +53,10 @@ pnpm run dev
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
- [如何建立一个最小重现](https://antfu.me/posts/why-reproductions-are-required-zh#如何建立一个最小重现)
|
|
||||||
- https://biomejs.dev/zh-cn/internals/language-support/
|
- https://biomejs.dev/zh-cn/internals/language-support/
|
||||||
- https://github.dev/antfu-collective/vitesse/
|
- https://github.dev/antfu-collective/vitesse/
|
||||||
- [Vue3 入门指南与实战案例](https://vue3.chengpeiquan.com/)
|
- [Vue3 入门指南与实战案例](https://vue3.chengpeiquan.com/)
|
||||||
|
- [如何建立一个最小重现](https://antfu.me/posts/why-reproductions-are-required-zh#如何建立一个最小重现)
|
||||||
|
|
||||||
---
|
---
|
||||||
- [primevue-scopedtokens](https://primevue.org/theming/styled/#scopedtokens)
|
- [primevue-scopedtokens](https://primevue.org/theming/styled/#scopedtokens)
|
||||||
|
|
||||||
+ https://www.npmjs.com/package/npkill
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import type { UserConfig } from '@commitlint/types';
|
|
||||||
|
|
||||||
|
|
||||||
const Configuration: UserConfig = {
|
|
||||||
extends: ['@commitlint/config-conventional'],
|
|
||||||
formatter: '@commitlint/format',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Configuration;
|
|
@ -84,8 +84,6 @@ export default defineConfigWithVueTs(
|
|||||||
'import-x/newline-after-import': 'error',
|
'import-x/newline-after-import': 'error',
|
||||||
'import-x/first': 'error',
|
'import-x/first': 'error',
|
||||||
'import-x/no-named-as-default': 'off',
|
'import-x/no-named-as-default': 'off',
|
||||||
'import-x/no-duplicates': 'off',
|
|
||||||
'import-x/named': 'off',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// endregion <<< eslint-plugin-import-x <<<
|
// endregion <<< eslint-plugin-import-x <<<
|
||||||
@ -101,8 +99,6 @@ export default defineConfigWithVueTs(
|
|||||||
'perfectionist/sort-imports': ['error'],
|
'perfectionist/sort-imports': ['error'],
|
||||||
'perfectionist/sort-modules': 'off',
|
'perfectionist/sort-modules': 'off',
|
||||||
'perfectionist/sort-object-types': 'off',
|
'perfectionist/sort-object-types': 'off',
|
||||||
'perfectionist/sort-enums': 'off',
|
|
||||||
'perfectionist/sort-union-types': 'off',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// endregion <<< eslint-plugin-perfectionist <<<
|
// endregion <<< eslint-plugin-perfectionist <<<
|
||||||
|
142
package.json
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"packageManager": "pnpm@10.13.1",
|
"packageManager": "pnpm@10.8.0",
|
||||||
"name": "vue-ts-example",
|
"name": "vue-ts-example",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
@ -44,123 +44,121 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alova/adapter-axios": "^2.0.16",
|
"@alova/adapter-axios": "^2.0.13",
|
||||||
"@formkit/auto-animate": "^0.8.2",
|
"@formkit/auto-animate": "^0.8.2",
|
||||||
"@intlify/unplugin-vue-i18n": "^6.0.8",
|
"@intlify/unplugin-vue-i18n": "^6.0.6",
|
||||||
"@pinia/colada": "^0.17.1",
|
"@pinia/colada": "^0.14.2",
|
||||||
"@primeuix/themes": "^1.1.2",
|
"@primeuix/themes": "^1.0.3",
|
||||||
"@splinetool/runtime": "^1.10.27",
|
"@splinetool/runtime": "^1.9.82",
|
||||||
"@types/p5": "^1.7.6",
|
"@types/p5": "^1.7.6",
|
||||||
"@types/sortablejs": "^1.15.8",
|
"@types/sortablejs": "^1.15.8",
|
||||||
"@unhead/vue": "^2.0.12",
|
"@unhead/vue": "^2.0.5",
|
||||||
"@vant/use": "^1.6.0",
|
"@vant/use": "^1.6.0",
|
||||||
"@vueuse/core": "^13.5.0",
|
"@vueuse/core": "^13.1.0",
|
||||||
"alova": "^3.3.4",
|
"alova": "^3.2.10",
|
||||||
"ant-design-vue": "~4.2.6",
|
"ant-design-vue": "~4.2.6",
|
||||||
"axios": "^1.10.0",
|
"axios": "^1.8.4",
|
||||||
"cesium": "^1.131.0",
|
"cesium": "^1.128.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"consola": "^3.4.2",
|
"consola": "^3.4.2",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"deep-freeze-es6": "^4.0.1",
|
"deep-freeze-es6": "^4.0.0",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"lucide-vue-next": "^0.525.0",
|
"lucide-vue-next": "^0.487.0",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"p5": "^2.0.3",
|
"p5": "^1.11.3",
|
||||||
"page-stack-vue3": "^2.5.6",
|
"page-stack-vue3": "^2.5.6",
|
||||||
"pinia": "^3.0.3",
|
"pinia": "^3.0.1",
|
||||||
"pinia-plugin-persistedstate": "^4.4.1",
|
"pinia-plugin-persistedstate": "^4.2.0",
|
||||||
"plotly.js-dist-min": "^3.0.1",
|
"plotly.js-dist-min": "^3.0.1",
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primelocale": "^2.1.4",
|
"primelocale": "^2.1.2",
|
||||||
"primevue": "^4.3.5",
|
"primevue": "^4.3.3",
|
||||||
"radash": "^12.1.1",
|
"radash": "^12.1.0",
|
||||||
"radix-vue": "^1.9.17",
|
"radix-vue": "^1.9.17",
|
||||||
"reka-ui": "^2.3.2",
|
"reka-ui": "^2.2.0",
|
||||||
"satellite.js": "^6.0.1",
|
"satellite.js": "^6.0.0",
|
||||||
"sortablejs": "^1.15.6",
|
"sortablejs": "^1.15.6",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.2.0",
|
||||||
"tdesign-icons-vue-next": "^0.3.6",
|
"tdesign-icons-vue-next": "^0.3.5",
|
||||||
"three": "^0.178.0",
|
"three": "^0.175.0",
|
||||||
"ts-enum-util": "^4.1.0",
|
"ts-enum-util": "^4.1.0",
|
||||||
"utils4u": "^4.2.3",
|
"utils4u": "^4.2.3",
|
||||||
"vant": "^4.9.20",
|
"vant": "^4.9.18",
|
||||||
"vue": "^3.5.17",
|
"vue": "^3.5.13",
|
||||||
"vue-data-ui": "^2.15.2",
|
|
||||||
"vue-draggable-plus": "^0.6.0",
|
"vue-draggable-plus": "^0.6.0",
|
||||||
"vue-i18n": "^11.1.9",
|
"vue-i18n": "^11.1.3",
|
||||||
"vue-page-stack": "^3.2.0",
|
"vue-page-stack": "^3.2.0",
|
||||||
"vue-router": "^4.5.1"
|
"vue-router": "^4.5.0",
|
||||||
|
"vuetify": "^3.8.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^19.8.1",
|
"@eslint/compat": "^1.2.8",
|
||||||
"@commitlint/config-conventional": "^19.8.1",
|
"@faker-js/faker": "^9.6.0",
|
||||||
"@eslint/compat": "^1.3.1",
|
"@iconify-json/carbon": "^1.2.8",
|
||||||
"@faker-js/faker": "^9.9.0",
|
|
||||||
"@iconify-json/carbon": "^1.2.10",
|
|
||||||
"@iconify-json/logos": "^1.2.4",
|
"@iconify-json/logos": "^1.2.4",
|
||||||
"@iconify-json/mdi": "^1.2.3",
|
"@iconify-json/mdi": "^1.2.3",
|
||||||
"@iconify/utils": "^2.3.0",
|
"@iconify/utils": "^2.3.0",
|
||||||
"@playwright/test": "^1.53.2",
|
"@playwright/test": "^1.51.1",
|
||||||
"@primevue/auto-import-resolver": "^4.3.5",
|
"@primevue/auto-import-resolver": "^4.3.3",
|
||||||
"@tsconfig/node22": "^22.0.2",
|
"@tsconfig/node22": "^22.0.1",
|
||||||
"@types/archiver": "^6.0.3",
|
"@types/archiver": "^6.0.3",
|
||||||
"@types/mockjs": "^1.0.10",
|
"@types/mockjs": "^1.0.10",
|
||||||
"@types/node": "^22.16.3",
|
"@types/node": "^22.14.0",
|
||||||
"@types/nprogress": "^0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
"@types/plotly.js-dist-min": "^2.3.4",
|
"@types/plotly.js-dist-min": "^2.3.4",
|
||||||
"@types/three": "^0.178.1",
|
"@types/three": "^0.175.0",
|
||||||
"@vant/auto-import-resolver": "^1.3.0",
|
"@vant/auto-import-resolver": "^1.3.0",
|
||||||
"@vitejs/plugin-vue": "^6.0.0",
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
"@vitejs/plugin-vue-jsx": "^5.0.1",
|
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
||||||
"@vitest/eslint-plugin": "^1.3.4",
|
"@vitest/eslint-plugin": "^1.1.40",
|
||||||
"@vue/eslint-config-prettier": "^10.2.0",
|
"@vue/eslint-config-prettier": "^10.2.0",
|
||||||
"@vue/eslint-config-typescript": "^14.6.0",
|
"@vue/eslint-config-typescript": "^14.5.0",
|
||||||
"@vue/test-utils": "^2.4.6",
|
"@vue/test-utils": "^2.4.6",
|
||||||
"@vue/tsconfig": "^0.7.0",
|
"@vue/tsconfig": "^0.7.0",
|
||||||
"archiver": "^7.0.1",
|
"archiver": "^7.0.1",
|
||||||
"depcheck": "^1.4.7",
|
"depcheck": "^1.4.7",
|
||||||
"eruda": "^3.4.3",
|
"eruda": "^3.4.1",
|
||||||
"eslint": "^9.30.1",
|
"eslint": "^9.24.0",
|
||||||
"eslint-plugin-import-x": "^4.16.1",
|
"eslint-plugin-import-x": "^4.10.2",
|
||||||
"eslint-plugin-oxlint": "^1.6.0",
|
"eslint-plugin-oxlint": "^0.16.6",
|
||||||
"eslint-plugin-perfectionist": "^4.15.0",
|
"eslint-plugin-perfectionist": "^4.11.0",
|
||||||
"eslint-plugin-unicorn": "^59.0.1",
|
"eslint-plugin-unicorn": "^58.0.0",
|
||||||
"eslint-plugin-vue": "^10.3.0",
|
"eslint-plugin-vue": "^10.0.0",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"less": "^4.3.0",
|
"less": "^4.3.0",
|
||||||
"lint-staged": "^16.1.2",
|
"lint-staged": "^15.5.0",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
"naive-ui": "^2.42.0",
|
"npm-run-all2": "^7.0.2",
|
||||||
"npm-run-all2": "^8.0.4",
|
"oxlint": "^0.16.6",
|
||||||
"oxlint": "^1.6.0",
|
"prettier": "3.5.3",
|
||||||
"prettier": "3.6.2",
|
"sass-embedded": "^1.86.3",
|
||||||
|
"terser": "^5.39.0",
|
||||||
"typescript": "~5.8.3",
|
"typescript": "~5.8.3",
|
||||||
"unocss": "66.3.3",
|
"unocss": "66.1.0-beta.10",
|
||||||
"unocss-preset-animations": "^1.2.1",
|
"unocss-preset-animations": "^1.1.1",
|
||||||
"unocss-preset-chinese": "^0.3.3",
|
"unocss-preset-chinese": "^0.3.3",
|
||||||
"unocss-preset-shadcn": "^0.5.0",
|
"unocss-preset-shadcn": "^0.5.0",
|
||||||
"unplugin-auto-import": "^19.3.0",
|
"unplugin-auto-import": "^19.1.2",
|
||||||
"unplugin-icons": "^22.1.0",
|
"unplugin-icons": "^22.1.0",
|
||||||
"unplugin-vue-components": "^28.8.0",
|
"unplugin-vue-components": "^28.5.0",
|
||||||
"unplugin-vue-macros": "^2.14.5",
|
"unplugin-vue-macros": "^2.14.5",
|
||||||
"unplugin-vue-markdown": "^29.1.0",
|
"unplugin-vue-markdown": "^28.3.1",
|
||||||
"unplugin-vue-router": "^0.14.0",
|
"unplugin-vue-router": "^0.12.0",
|
||||||
"vfonts": "^0.0.3",
|
"vite": "^6.2.6",
|
||||||
"vite": "^7.0.2",
|
"vite-plugin-checker": "^0.9.1",
|
||||||
"vite-plugin-checker": "^0.10.0",
|
|
||||||
"vite-plugin-fake-server": "^2.2.0",
|
"vite-plugin-fake-server": "^2.2.0",
|
||||||
"vite-plugin-image-tools": "^2.0.2",
|
"vite-plugin-purgecss-updated-v5": "^1.2.4",
|
||||||
"vite-plugin-purgecss-updated-v5": "^1.2.6",
|
"vite-plugin-singlefile": "^2.2.0",
|
||||||
"vite-plugin-singlefile": "^2.3.0",
|
"vite-plugin-static-copy": "^2.3.1",
|
||||||
"vite-plugin-static-copy": "^3.1.0",
|
"vite-plugin-vue-devtools": "^7.7.2",
|
||||||
"vite-plugin-vue-devtools": "^7.7.7",
|
|
||||||
"vite-plugin-vue-layouts": "^0.11.0",
|
"vite-plugin-vue-layouts": "^0.11.0",
|
||||||
"vite-plugin-vue-meta-layouts": "^0.5.1",
|
"vite-plugin-vue-meta-layouts": "^0.5.1",
|
||||||
"vite-plugin-webfont-dl": "^3.10.5",
|
"vite-plugin-vuetify": "^2.1.1",
|
||||||
"vue-component-type-helpers": "^3.0.1",
|
"vite-plugin-webfont-dl": "^3.10.4",
|
||||||
"vue-tsc": "^3.0.1"
|
"vue-component-type-helpers": "^2.2.8",
|
||||||
|
"vue-tsc": "^2.2.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
6904
pnpm-lock.yaml
generated
@ -15,11 +15,9 @@ const themeConfig = computed(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-config-provider preflight-style-disabled>
|
|
||||||
<a-config-provider :theme="themeConfig">
|
<a-config-provider :theme="themeConfig">
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</a-config-provider>
|
</a-config-provider>
|
||||||
</n-config-provider>
|
|
||||||
|
|
||||||
<DynamicDialog /> <ConfirmDialog /> <Toast />
|
<DynamicDialog /> <ConfirmDialog /> <Toast />
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
export enum E_选项卡菜单 {
|
|
||||||
幅度单位列表 = '幅度单位列表',
|
|
||||||
幅度菜单列表 = '幅度菜单列表',
|
|
||||||
跨度菜单列表 = '跨度菜单列表',
|
|
||||||
频率单位列表 = '频率单位列表',
|
|
||||||
频率菜单列表 = '频率菜单列表',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum E_幅度菜单列表的项目 {
|
|
||||||
RefLevel = 'Ref Level',
|
|
||||||
// Attenuation = 'Attenuation', // 如果衰减也需要类似交互,则取消注释
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum E_幅度单位 {
|
|
||||||
dBm = 'dBm',
|
|
||||||
mV = 'mV',
|
|
||||||
uA = 'µA', // 使用 uA 表示微安
|
|
||||||
uV = 'µV', // 使用 uV 表示微伏
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum E_跨度菜单列表的项目 {
|
|
||||||
FullSpan = 'Full Span',
|
|
||||||
LastSpan = 'Last Span',
|
|
||||||
ZeroSpan = 'Zero Span',
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 值是在屏幕上显示的值。 */
|
|
||||||
export enum E_选项卡菜单Freq菜单列表的项目 {
|
|
||||||
CenterFreq = 'Center',
|
|
||||||
StartFreq = 'Start',
|
|
||||||
StopFreq = 'Stop',
|
|
||||||
// CFStep = 'CFStep',
|
|
||||||
// FreqOffset = 'FreqOffset',
|
|
||||||
// SingnalTrack = 'SingnalTrack',
|
|
||||||
// ScaleType = 'ScaleType',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum E_Freq单位 {
|
|
||||||
GHz = 'GHz',
|
|
||||||
Hz = 'Hz',
|
|
||||||
kHz = 'kHz',
|
|
||||||
MHz = 'MHz',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum E_数字键盘按键 {
|
|
||||||
Dot = '.',
|
|
||||||
Num0 = 0,
|
|
||||||
Num1 = 1,
|
|
||||||
Num2 = 2,
|
|
||||||
Num3 = 3,
|
|
||||||
Num4 = 4,
|
|
||||||
Num5 = 5,
|
|
||||||
Num6 = 6,
|
|
||||||
Num7 = 7,
|
|
||||||
Num8 = 8,
|
|
||||||
Num9 = 9,
|
|
||||||
PlusMinus = '+/-',
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
@font-face {
|
|
||||||
font-family: 'Helvetica Custom';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400; /* 400 通常代表 'normal' 或 'regular' */
|
|
||||||
src: url('fonts/Helvetica-Light-05.eot');
|
|
||||||
src:
|
|
||||||
url('fonts/Helvetica-Light-05.eot?#iefix') format('embedded-opentype'),
|
|
||||||
url('fonts/Helvetica-Light-05.woff2') format('woff2'),
|
|
||||||
url('fonts/Helvetica-Light-05.woff') format('woff'),
|
|
||||||
url('fonts/Helvetica-Light-05.ttf') format('truetype'),
|
|
||||||
url('fonts/Helvetica-Light-05.svg#Helvetica') format('svg');
|
|
||||||
font-display: swap; /* 推荐 */
|
|
||||||
}
|
|
@ -1,805 +0,0 @@
|
|||||||
<!-- 频谱仪 -->
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { $enum } from 'ts-enum-util';
|
|
||||||
|
|
||||||
import {
|
|
||||||
E_Freq单位,
|
|
||||||
E_幅度单位,
|
|
||||||
E_幅度菜单列表的项目,
|
|
||||||
E_数字键盘按键,
|
|
||||||
E_跨度菜单列表的项目,
|
|
||||||
E_选项卡菜单,
|
|
||||||
E_选项卡菜单Freq菜单列表的项目,
|
|
||||||
} from './CONST';
|
|
||||||
import 设备照片 from './pin-pu-yi-bg.png';
|
|
||||||
|
|
||||||
const state = reactive({
|
|
||||||
选项卡当前显示: E_选项卡菜单.频率菜单列表,
|
|
||||||
频谱仪状态: {
|
|
||||||
频率输入状态: {
|
|
||||||
选中的频率菜单列表的项目: null as E_选项卡菜单Freq菜单列表的项目 | null,
|
|
||||||
输入的值临时输入字符串: null as null | string, // 用于暂存用户输入
|
|
||||||
},
|
|
||||||
幅度输入状态: {
|
|
||||||
选中的幅度菜单列表的项目: null as E_幅度菜单列表的项目 | null,
|
|
||||||
输入的值临时输入字符串: null as null | string, // 用于暂存用户输入
|
|
||||||
refLevel: {
|
|
||||||
value: 0,
|
|
||||||
unit: E_幅度单位.dBm,
|
|
||||||
},
|
|
||||||
// attenuation: { value: 0, unit: E_幅度单位.dB }, // 如果需要衰减值
|
|
||||||
},
|
|
||||||
center: {
|
|
||||||
value: 0,
|
|
||||||
unit: E_Freq单位.Hz,
|
|
||||||
},
|
|
||||||
start: {
|
|
||||||
value: 0,
|
|
||||||
unit: E_Freq单位.Hz,
|
|
||||||
},
|
|
||||||
stop: {
|
|
||||||
value: 0,
|
|
||||||
unit: E_Freq单位.Hz,
|
|
||||||
},
|
|
||||||
span: {
|
|
||||||
currentSpan: {
|
|
||||||
start: 0,
|
|
||||||
stop: 0,
|
|
||||||
unit: E_Freq单位.Hz,
|
|
||||||
},
|
|
||||||
lastSpan: {
|
|
||||||
start: 0,
|
|
||||||
stop: 0,
|
|
||||||
unit: E_Freq单位.Hz,
|
|
||||||
},
|
|
||||||
fullSpan: {
|
|
||||||
start: 0,
|
|
||||||
stop: 3,
|
|
||||||
unit: E_Freq单位.GHz,
|
|
||||||
},
|
|
||||||
zeroSpan: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const 选项卡标题 = computed(() =>
|
|
||||||
$enum.mapValue(state.选项卡当前显示).with({
|
|
||||||
[E_选项卡菜单.频率菜单列表]: 'Freq/Channel',
|
|
||||||
[E_选项卡菜单.频率单位列表]: '',
|
|
||||||
[E_选项卡菜单.跨度菜单列表]: 'Span',
|
|
||||||
[E_选项卡菜单.幅度菜单列表]: 'Amplitude',
|
|
||||||
[E_选项卡菜单.幅度单位列表]: '',
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
function 执行点击屏幕右边的按钮(按钮序号: number) {
|
|
||||||
console.group('🔘 点击屏幕右边的按钮', {
|
|
||||||
按钮序号,
|
|
||||||
选项卡当前显示: state.选项卡当前显示,
|
|
||||||
});
|
|
||||||
$enum.visitValue(state.选项卡当前显示).with({
|
|
||||||
[E_选项卡菜单.频率菜单列表]: () => {
|
|
||||||
switch (按钮序号) {
|
|
||||||
case 1: {
|
|
||||||
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 = E_选项卡菜单Freq菜单列表的项目.CenterFreq;
|
|
||||||
console.debug('设置 Freq 输入状态为 CenterFreq');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 = E_选项卡菜单Freq菜单列表的项目.StartFreq;
|
|
||||||
console.debug('设置 Freq 输入状态为 StartFreq');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: {
|
|
||||||
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 = E_选项卡菜单Freq菜单列表的项目.StopFreq;
|
|
||||||
console.debug('设置 Freq 输入状态为 StopFreq');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
console.debug('频率菜单列表 - 这个按键还没有实现');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[E_选项卡菜单.频率单位列表]: () => {
|
|
||||||
let selectedUnit: E_Freq单位 | null = null;
|
|
||||||
switch (按钮序号) {
|
|
||||||
case 1: {
|
|
||||||
selectedUnit = E_Freq单位.GHz;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
selectedUnit = E_Freq单位.MHz;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: {
|
|
||||||
selectedUnit = E_Freq单位.kHz;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: {
|
|
||||||
selectedUnit = E_Freq单位.Hz;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
console.warn('无效的频率单位按钮序号:', 按钮序号);
|
|
||||||
console.groupEnd();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const tempInputString = state.频谱仪状态.频率输入状态.输入的值临时输入字符串;
|
|
||||||
const selectedFreqItem = state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目;
|
|
||||||
// 必须有临时输入值和选中的 Freq 项目才能确认
|
|
||||||
if (!tempInputString || !selectedFreqItem) {
|
|
||||||
console.warn('频率输入未完成或未选择项目,无法确认单位。');
|
|
||||||
console.groupEnd();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const inputValue = Number.parseFloat(tempInputString);
|
|
||||||
// 校验解析结果
|
|
||||||
if (Number.isNaN(inputValue)) {
|
|
||||||
console.warn('无法将临时输入解析为有效数字 (频率):', tempInputString);
|
|
||||||
console.groupEnd();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.debug('确认频率单位:', selectedUnit, '值为:', inputValue);
|
|
||||||
switch (selectedFreqItem) {
|
|
||||||
case E_选项卡菜单Freq菜单列表的项目.CenterFreq: {
|
|
||||||
state.频谱仪状态.center.value = inputValue;
|
|
||||||
state.频谱仪状态.center.unit = selectedUnit;
|
|
||||||
console.debug('更新 CenterFreq:', state.频谱仪状态.center);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case E_选项卡菜单Freq菜单列表的项目.StartFreq: {
|
|
||||||
state.频谱仪状态.start.value = inputValue;
|
|
||||||
state.频谱仪状态.start.unit = selectedUnit;
|
|
||||||
console.debug('更新 StartFreq:', state.频谱仪状态.start);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case E_选项卡菜单Freq菜单列表的项目.StopFreq: {
|
|
||||||
state.频谱仪状态.stop.value = inputValue;
|
|
||||||
state.频谱仪状态.stop.unit = selectedUnit;
|
|
||||||
console.debug('更新 StopFreq:', state.频谱仪状态.stop);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 = null;
|
|
||||||
state.频谱仪状态.频率输入状态.输入的值临时输入字符串 = null;
|
|
||||||
state.选项卡当前显示 = E_选项卡菜单.频率菜单列表;
|
|
||||||
console.debug('频率输入状态已重置, 切换回频率菜单列表');
|
|
||||||
},
|
|
||||||
[E_选项卡菜单.跨度菜单列表]: () => {
|
|
||||||
switch (按钮序号) {
|
|
||||||
case 1: {
|
|
||||||
// Full Span
|
|
||||||
state.频谱仪状态.span.lastSpan.start = state.频谱仪状态.start.value;
|
|
||||||
state.频谱仪状态.span.lastSpan.stop = state.频谱仪状态.stop.value;
|
|
||||||
state.频谱仪状态.span.lastSpan.unit = state.频谱仪状态.stop.unit;
|
|
||||||
state.频谱仪状态.start.value = state.频谱仪状态.span.fullSpan.start;
|
|
||||||
state.频谱仪状态.start.unit = state.频谱仪状态.span.fullSpan.unit;
|
|
||||||
state.频谱仪状态.stop.value = state.频谱仪状态.span.fullSpan.stop;
|
|
||||||
state.频谱仪状态.stop.unit = state.频谱仪状态.span.fullSpan.unit;
|
|
||||||
state.频谱仪状态.center.value = (state.频谱仪状态.start.value + state.频谱仪状态.stop.value) / 2;
|
|
||||||
state.频谱仪状态.center.unit = state.频谱仪状态.span.fullSpan.unit;
|
|
||||||
state.频谱仪状态.span.zeroSpan = false;
|
|
||||||
console.debug('设置为 Full Span');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
// Zero Span
|
|
||||||
state.频谱仪状态.span.lastSpan.start = state.频谱仪状态.start.value;
|
|
||||||
state.频谱仪状态.span.lastSpan.stop = state.频谱仪状态.stop.value;
|
|
||||||
state.频谱仪状态.span.lastSpan.unit = state.频谱仪状态.stop.unit;
|
|
||||||
state.频谱仪状态.start.value = state.频谱仪状态.center.value;
|
|
||||||
state.频谱仪状态.start.unit = state.频谱仪状态.center.unit;
|
|
||||||
state.频谱仪状态.stop.value = state.频谱仪状态.center.value;
|
|
||||||
state.频谱仪状态.stop.unit = state.频谱仪状态.center.unit;
|
|
||||||
state.频谱仪状态.span.zeroSpan = true;
|
|
||||||
console.debug('设置为 Zero Span');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: {
|
|
||||||
// Last Span
|
|
||||||
state.频谱仪状态.start.value = state.频谱仪状态.span.lastSpan.start;
|
|
||||||
state.频谱仪状态.start.unit = state.频谱仪状态.span.lastSpan.unit;
|
|
||||||
state.频谱仪状态.stop.value = state.频谱仪状态.span.lastSpan.stop;
|
|
||||||
state.频谱仪状态.stop.unit = state.频谱仪状态.span.lastSpan.unit;
|
|
||||||
state.频谱仪状态.center.value = (state.频谱仪状态.start.value + state.频谱仪状态.stop.value) / 2;
|
|
||||||
state.频谱仪状态.center.unit = state.频谱仪状态.span.lastSpan.unit;
|
|
||||||
state.频谱仪状态.span.zeroSpan = false;
|
|
||||||
console.debug('恢复到 Last Span');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
console.debug('跨度菜单列表 - 这个按键还没有实现');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[E_选项卡菜单.幅度菜单列表]: () => {
|
|
||||||
switch (按钮序号) {
|
|
||||||
case 1: {
|
|
||||||
// Ref Level
|
|
||||||
state.频谱仪状态.幅度输入状态.选中的幅度菜单列表的项目 = E_幅度菜单列表的项目.RefLevel;
|
|
||||||
state.频谱仪状态.幅度输入状态.输入的值临时输入字符串 = null;
|
|
||||||
console.debug('设置 幅度输入状态为 RefLevel');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
// Attenuation
|
|
||||||
console.debug('点击了 幅度菜单列表 - Attenuation (功能待实现)');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
console.debug('幅度菜单列表 - 这个按键还没有实现');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[E_选项卡菜单.幅度单位列表]: () => {
|
|
||||||
let selectedUnit: E_幅度单位 | null = null;
|
|
||||||
switch (按钮序号) {
|
|
||||||
case 1: {
|
|
||||||
selectedUnit = E_幅度单位.dBm;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
selectedUnit = E_幅度单位.mV;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: {
|
|
||||||
selectedUnit = E_幅度单位.uV;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: {
|
|
||||||
selectedUnit = E_幅度单位.uA;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
console.warn('无效的幅度单位按钮序号:', 按钮序号);
|
|
||||||
console.groupEnd();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const tempInputString = state.频谱仪状态.幅度输入状态.输入的值临时输入字符串;
|
|
||||||
const selectedAmpItem = state.频谱仪状态.幅度输入状态.选中的幅度菜单列表的项目;
|
|
||||||
|
|
||||||
if (!tempInputString || !selectedAmpItem) {
|
|
||||||
console.warn('幅度输入未完成或未选择项目,无法确认单位。');
|
|
||||||
console.groupEnd();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const inputValue = Number.parseFloat(tempInputString);
|
|
||||||
if (Number.isNaN(inputValue)) {
|
|
||||||
console.warn('无法将临时输入解析为有效数字 (幅度):', tempInputString);
|
|
||||||
console.groupEnd();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.debug('确认幅度单位:', selectedUnit, '值为:', inputValue);
|
|
||||||
if (selectedAmpItem === E_幅度菜单列表的项目.RefLevel) {
|
|
||||||
state.频谱仪状态.幅度输入状态.refLevel.value = inputValue;
|
|
||||||
state.频谱仪状态.幅度输入状态.refLevel.unit = selectedUnit;
|
|
||||||
console.debug('更新 RefLevel:', state.频谱仪状态.幅度输入状态.refLevel);
|
|
||||||
}
|
|
||||||
state.频谱仪状态.幅度输入状态.选中的幅度菜单列表的项目 = null;
|
|
||||||
state.频谱仪状态.幅度输入状态.输入的值临时输入字符串 = null;
|
|
||||||
state.选项卡当前显示 = E_选项卡菜单.幅度菜单列表;
|
|
||||||
console.debug('幅度输入状态已重置, 切换回幅度菜单列表');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
console.groupEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
function 执行点击数字按钮(按钮值: E_数字键盘按键) {
|
|
||||||
console.group('🔢 点击数字按钮', { 按钮值 });
|
|
||||||
|
|
||||||
const isFreqInputActive = !!state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目;
|
|
||||||
const isAmpInputActive = !!state.频谱仪状态.幅度输入状态.选中的幅度菜单列表的项目;
|
|
||||||
|
|
||||||
if (!isFreqInputActive && !isAmpInputActive) {
|
|
||||||
console.warn('请先选择一个频率或幅度菜单项');
|
|
||||||
console.groupEnd();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let 当前临时输入: string;
|
|
||||||
let 更新临时输入回调: (newVal: null | string) => void;
|
|
||||||
let 后续操作菜单: E_选项卡菜单;
|
|
||||||
|
|
||||||
if (isFreqInputActive) {
|
|
||||||
当前临时输入 = state.频谱仪状态.频率输入状态.输入的值临时输入字符串 ?? '';
|
|
||||||
更新临时输入回调 = (newVal) => {
|
|
||||||
state.频谱仪状态.频率输入状态.输入的值临时输入字符串 = newVal;
|
|
||||||
};
|
|
||||||
后续操作菜单 = E_选项卡菜单.频率单位列表;
|
|
||||||
} else {
|
|
||||||
// isAmpInputActive
|
|
||||||
当前临时输入 = state.频谱仪状态.幅度输入状态.输入的值临时输入字符串 ?? '';
|
|
||||||
更新临时输入回调 = (newVal) => {
|
|
||||||
state.频谱仪状态.幅度输入状态.输入的值临时输入字符串 = newVal;
|
|
||||||
};
|
|
||||||
后续操作菜单 = E_选项卡菜单.幅度单位列表;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (按钮值) {
|
|
||||||
case E_数字键盘按键.Dot: {
|
|
||||||
// 只有在当前临时输入不包含小数点时才允许添加
|
|
||||||
if (当前临时输入.includes('.')) {
|
|
||||||
console.debug('已存在小数点,忽略本次输入');
|
|
||||||
} else {
|
|
||||||
// 如果当前为空,则为 '0.',否则追加 '.'
|
|
||||||
更新临时输入回调(当前临时输入 ? `${当前临时输入}.` : '0.');
|
|
||||||
console.debug(
|
|
||||||
'输入小数点,临时字符串:',
|
|
||||||
isFreqInputActive
|
|
||||||
? state.频谱仪状态.频率输入状态.输入的值临时输入字符串
|
|
||||||
: state.频谱仪状态.幅度输入状态.输入的值临时输入字符串,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case E_数字键盘按键.Num0:
|
|
||||||
case E_数字键盘按键.Num1:
|
|
||||||
case E_数字键盘按键.Num2:
|
|
||||||
case E_数字键盘按键.Num3:
|
|
||||||
case E_数字键盘按键.Num4:
|
|
||||||
case E_数字键盘按键.Num5:
|
|
||||||
case E_数字键盘按键.Num6:
|
|
||||||
case E_数字键盘按键.Num7:
|
|
||||||
case E_数字键盘按键.Num8:
|
|
||||||
case E_数字键盘按键.Num9: {
|
|
||||||
if (当前临时输入 === '0') {
|
|
||||||
更新临时输入回调(String(按钮值));
|
|
||||||
} else if (当前临时输入 === '-0') {
|
|
||||||
更新临时输入回调(`-${String(按钮值)}`);
|
|
||||||
} else {
|
|
||||||
更新临时输入回调(当前临时输入 + String(按钮值));
|
|
||||||
}
|
|
||||||
console.debug(
|
|
||||||
'输入数字,临时字符串:',
|
|
||||||
isFreqInputActive
|
|
||||||
? state.频谱仪状态.频率输入状态.输入的值临时输入字符串
|
|
||||||
: state.频谱仪状态.幅度输入状态.输入的值临时输入字符串,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case E_数字键盘按键.PlusMinus: {
|
|
||||||
if (当前临时输入.startsWith('-')) {
|
|
||||||
更新临时输入回调(当前临时输入.slice(1));
|
|
||||||
} else if (当前临时输入 && 当前临时输入 !== '0' && 当前临时输入 !== '0.') {
|
|
||||||
更新临时输入回调(`-${当前临时输入}`);
|
|
||||||
} else if (当前临时输入 === '' || 当前临时输入 === '0' || 当前临时输入 === '0.') {
|
|
||||||
更新临时输入回调('-');
|
|
||||||
} else {
|
|
||||||
console.debug('无法切换正负号');
|
|
||||||
}
|
|
||||||
console.debug(
|
|
||||||
'切换正负号,临时字符串:',
|
|
||||||
isFreqInputActive
|
|
||||||
? state.频谱仪状态.频率输入状态.输入的值临时输入字符串
|
|
||||||
: state.频谱仪状态.幅度输入状态.输入的值临时输入字符串,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
console.warn('未知的数字键盘按键:', 按钮值);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.选项卡当前显示 = 后续操作菜单;
|
|
||||||
|
|
||||||
console.groupEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
const img_modules = import.meta.glob<{ default: string }>('./imgs/*.png', {
|
|
||||||
eager: true,
|
|
||||||
});
|
|
||||||
const 屏幕照片 = ref(img_modules['./imgs/屏幕_0.png']!.default);
|
|
||||||
watch(
|
|
||||||
() => state.频谱仪状态.center.value,
|
|
||||||
() => {
|
|
||||||
屏幕照片.value = img_modules['./imgs/屏幕_1.png']!.default;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
watch(
|
|
||||||
() => state.频谱仪状态.start.value,
|
|
||||||
() => {
|
|
||||||
屏幕照片.value = img_modules['./imgs/屏幕_2.png']!.default;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
watch(
|
|
||||||
() => state.频谱仪状态.stop.value,
|
|
||||||
() => {
|
|
||||||
屏幕照片.value = img_modules['./imgs/屏幕_3.png']!.default;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
watchEffect(() => {
|
|
||||||
console.debug(`屏幕照片.value :>> `, 屏幕照片.value);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<!-- <pre
|
|
||||||
v-if="$__DEV__"
|
|
||||||
class="fixed bottom-10 right-10 top-10 z-[9999] overflow-auto overflow-y-auto bg-white p-[10px] text-[12px] text-black"
|
|
||||||
>{{ { 选项卡菜单7个: $enum(E_选项卡菜单).getValues(), ...state } }}</pre
|
|
||||||
> -->
|
|
||||||
|
|
||||||
<div class="wrp relative">
|
|
||||||
<img :src="设备照片" alt="频谱仪设备" />
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="absolute left-[640px] top-[174px] flex w-[55px] flex-col gap-y-[4px] overflow-visible text-black"
|
|
||||||
data-box="屏幕右边的按钮"
|
|
||||||
>
|
|
||||||
<!-- 上下还有一个 ESC / RETURN -->
|
|
||||||
<ul class="flex h-[300px] flex-col justify-around gap-y-[4px] overflow-visible" data-box="屏幕右边按钮列表">
|
|
||||||
<template v-for="n in 7" :key="`按钮${n}`">
|
|
||||||
<li
|
|
||||||
class="lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-visible rounded-[2px] text-[12px]"
|
|
||||||
@click="执行点击屏幕右边的按钮(n)"
|
|
||||||
>
|
|
||||||
<button class="ppy-btn !h-full !w-full"></button>
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="absolute left-[195px] top-[140px] h-[350px] w-[430px] bg-black" data-box="屏幕">
|
|
||||||
<img :src="屏幕照片" alt="频谱仪屏幕" class="absolute left-0 top-0 !h-[330px] !w-[340px]" />
|
|
||||||
|
|
||||||
<!-- -->
|
|
||||||
<!-- 屏幕左上角 Ref Level -->
|
|
||||||
<div class="absolute left-[5px] top-[20px] text-left text-[10px] text-white" data-box="屏幕左上角RefLevel">
|
|
||||||
<span>
|
|
||||||
Ref {{ state.频谱仪状态.幅度输入状态.refLevel.value }}
|
|
||||||
{{ state.频谱仪状态.幅度输入状态.refLevel.unit }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="absolute bottom-0 left-0 right-[85px] flex justify-between text-white" data-box="下面左Start 右Stop">
|
|
||||||
<div class="flex-1 text-left">
|
|
||||||
<span>Start </span>
|
|
||||||
<span>{{ state.频谱仪状态.start.value }}</span>
|
|
||||||
<span>{{ state.频谱仪状态.start.unit }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 text-right">
|
|
||||||
<span>Stop </span>
|
|
||||||
<span>{{ state.频谱仪状态.stop.value }}</span>
|
|
||||||
<span>{{ state.频谱仪状态.stop.unit }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="
|
|
||||||
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 ||
|
|
||||||
state.频谱仪状态.幅度输入状态.选中的幅度菜单列表的项目
|
|
||||||
"
|
|
||||||
class="lh-[1.2] absolute left-[40px] top-[140px] flex flex-col gap-y-[0px] bg-gray-500/100 text-white"
|
|
||||||
data-box="正在输入的值"
|
|
||||||
>
|
|
||||||
<!-- 标题:显示当前选中的输入项 -->
|
|
||||||
<div v-if="state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目">
|
|
||||||
{{ state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 }}
|
|
||||||
</div>
|
|
||||||
<div v-else-if="state.频谱仪状态.幅度输入状态.选中的幅度菜单列表的项目">
|
|
||||||
{{ state.频谱仪状态.幅度输入状态.选中的幅度菜单列表的项目 }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 值:优先显示临时输入字符串,如果为空,则显示已确认的值 -->
|
|
||||||
<div>
|
|
||||||
<template
|
|
||||||
v-if="
|
|
||||||
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 &&
|
|
||||||
state.频谱仪状态.频率输入状态.输入的值临时输入字符串 !== null
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ state.频谱仪状态.频率输入状态.输入的值临时输入字符串 }}
|
|
||||||
</template>
|
|
||||||
<template
|
|
||||||
v-else-if="
|
|
||||||
state.频谱仪状态.幅度输入状态.选中的幅度菜单列表的项目 &&
|
|
||||||
state.频谱仪状态.幅度输入状态.输入的值临时输入字符串 !== null
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ state.频谱仪状态.幅度输入状态.输入的值临时输入字符串 }}
|
|
||||||
</template>
|
|
||||||
<!-- 已确认的频率值 -->
|
|
||||||
<template
|
|
||||||
v-else-if="
|
|
||||||
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 === E_选项卡菜单Freq菜单列表的项目.CenterFreq
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ state.频谱仪状态.center.value }}
|
|
||||||
{{ state.频谱仪状态.center.unit }}
|
|
||||||
</template>
|
|
||||||
<template
|
|
||||||
v-else-if="
|
|
||||||
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 === E_选项卡菜单Freq菜单列表的项目.StartFreq
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ state.频谱仪状态.start.value }} {{ state.频谱仪状态.start.unit }}
|
|
||||||
</template>
|
|
||||||
<template
|
|
||||||
v-else-if="
|
|
||||||
state.频谱仪状态.频率输入状态.选中的频率菜单列表的项目 === E_选项卡菜单Freq菜单列表的项目.StopFreq
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ state.频谱仪状态.stop.value }} {{ state.频谱仪状态.stop.unit }}
|
|
||||||
</template>
|
|
||||||
<!-- 已确认的幅度值 -->
|
|
||||||
<template
|
|
||||||
v-else-if="state.频谱仪状态.幅度输入状态.选中的幅度菜单列表的项目 === E_幅度菜单列表的项目.RefLevel"
|
|
||||||
>
|
|
||||||
{{ state.频谱仪状态.幅度输入状态.refLevel.value }}
|
|
||||||
{{ state.频谱仪状态.幅度输入状态.refLevel.unit }}
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
0.000000000
|
|
||||||
<!-- 默认或回退显示 -->
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="absolute bottom-[15px] right-0 top-0 flex w-[80px] flex-col gap-y-[4px] text-black"
|
|
||||||
data-box="屏幕右侧的选项卡"
|
|
||||||
>
|
|
||||||
<div class="menu-item lh-[30px] h-[30px] overflow-hidden bg-[#AFAFAF] text-center" data-box="菜单标题">
|
|
||||||
{{ 选项卡标题 }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul
|
|
||||||
v-if="state.选项卡当前显示 === E_选项卡菜单.频率菜单列表"
|
|
||||||
class="flex h-[300px] flex-col justify-around gap-y-[4px]"
|
|
||||||
data-box="频率菜单列表"
|
|
||||||
>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>Center Freq</span>
|
|
||||||
{{ state.频谱仪状态.center.value }}
|
|
||||||
{{ state.频谱仪状态.center.unit }}
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>Start Freq</span>
|
|
||||||
{{ state.频谱仪状态.start.value }}
|
|
||||||
{{ state.频谱仪状态.start.unit }}
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>Stop Freq</span>
|
|
||||||
{{ state.频谱仪状态.stop.value }}
|
|
||||||
{{ state.频谱仪状态.stop.unit }}
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>#CF Step</span>
|
|
||||||
<span>0.0000 hz</span>
|
|
||||||
<span>X</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>#Freq Offset</span>
|
|
||||||
<span>0.0000 Hz</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>#Singnal Track</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>#Scale Type</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul
|
|
||||||
v-if="state.选项卡当前显示 === E_选项卡菜单.频率单位列表"
|
|
||||||
class="flex flex-1 flex-col justify-around gap-y-[4px]"
|
|
||||||
data-box="FreqChannel单位列表"
|
|
||||||
>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>GHz</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>MHz</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>KHz</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>Hz</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul
|
|
||||||
v-if="state.选项卡当前显示 === E_选项卡菜单.跨度菜单列表"
|
|
||||||
class="flex h-[300px] flex-col justify-around gap-y-[4px]"
|
|
||||||
data-box="跨度菜单列表"
|
|
||||||
>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>{{ E_跨度菜单列表的项目.FullSpan }}</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>{{ E_跨度菜单列表的项目.ZeroSpan }}</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>{{ E_跨度菜单列表的项目.LastSpan }}</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul
|
|
||||||
v-if="state.选项卡当前显示 === E_选项卡菜单.幅度菜单列表"
|
|
||||||
class="flex h-[300px] flex-col justify-around gap-y-[4px]"
|
|
||||||
data-box="幅度菜单列表"
|
|
||||||
>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>Ref Level</span>
|
|
||||||
<span>
|
|
||||||
{{ state.频谱仪状态.幅度输入状态.refLevel.value }}
|
|
||||||
{{ state.频谱仪状态.幅度输入状态.refLevel.unit }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>#Attenuation</span>
|
|
||||||
<!-- <span>TODO</span> -->
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul
|
|
||||||
v-if="state.选项卡当前显示 === E_选项卡菜单.幅度单位列表"
|
|
||||||
class="flex h-[300px] flex-col justify-around gap-y-[4px]"
|
|
||||||
data-box="幅度单位列表"
|
|
||||||
>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>{{ E_幅度单位.dBm }}</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>{{ E_幅度单位.mV }}</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>{{ E_幅度单位.uV }}</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]">
|
|
||||||
<span>{{ E_幅度单位.uA }}</span>
|
|
||||||
</li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
<li class="menu-item lh-[1.2] flex flex-1 flex-col gap-y-[0px] overflow-hidden bg-[#AFAFAF]"></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="ppy-btns absolute left-[768px] top-[120px] h-[415px] !overflow-visible" data-box="机器右边按键">
|
|
||||||
<!-- 左上角. 长的 -->
|
|
||||||
<div class="flex flex-col gap-y-[18px] !overflow-visible">
|
|
||||||
<button class="ppy-btn !w-[62px]" @click="state.选项卡当前显示 = E_选项卡菜单.频率菜单列表">
|
|
||||||
FREQ<br />Channel
|
|
||||||
</button>
|
|
||||||
<button class="ppy-btn !w-[62px]" @click="state.选项卡当前显示 = E_选项卡菜单.跨度菜单列表">
|
|
||||||
SPAN<br />X Scale
|
|
||||||
</button>
|
|
||||||
<button class="ppy-btn !w-[62px]" @click="state.选项卡当前显示 = E_选项卡菜单.幅度菜单列表">
|
|
||||||
AMPLITUDE<br />Y Scale
|
|
||||||
</button>
|
|
||||||
<button class="ppy-btn !w-[62px] opacity-0">#</button>
|
|
||||||
<button class="ppy-btn !w-[62px] opacity-0">#</button>
|
|
||||||
</div>
|
|
||||||
<div class="mt-[20px] grid grid-cols-3 gap-[16.5px] !overflow-visible" data-box="数字键盘区域">
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Num7)">7</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Num8)">8</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Num9)">9</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Num4)">4</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Num5)">5</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Num6)">6</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Num1)">1</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Num2)">2</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Num3)">3</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Num0)">0</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.Dot)">.</button>
|
|
||||||
<button class="ppy-btn" @click="执行点击数字按钮(E_数字键盘按键.PlusMinus)">+/-</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
@import url('./Helvetica.css');
|
|
||||||
|
|
||||||
.wrp {
|
|
||||||
font-family: 'Helvetica Custom';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .wrp * {
|
|
||||||
overflow: hidden;
|
|
||||||
} */
|
|
||||||
|
|
||||||
img[alt='频谱仪设备'] {
|
|
||||||
width: calc(2554px * 0.5);
|
|
||||||
max-width: fit-content;
|
|
||||||
height: calc(1626px * 0.5);
|
|
||||||
max-height: fit-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ppy-btn {
|
|
||||||
display: flex; /* 使用 flex 居中文本 */
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 36px;
|
|
||||||
height: 30px;
|
|
||||||
padding-left: 2px;
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 1.2;
|
|
||||||
color: #333; /* 深灰色文字 */
|
|
||||||
text-align: left;
|
|
||||||
text-decoration: none;
|
|
||||||
background-color: #e0e0e0; /* 按钮浅灰色背景 */
|
|
||||||
border: 1px solid green;
|
|
||||||
border: 1px solid #b0b0b0; /* 添加边框 */
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow:
|
|
||||||
1px 1px 2px rgb(0 0 0 / 20%),
|
|
||||||
/* 轻微外阴影 */ -1px -1px 2px rgb(255 255 255 / 80%); /* 轻微外高光 */
|
|
||||||
|
|
||||||
transition: all 0.1s ease-in-out; /* 平滑过渡效果 */
|
|
||||||
|
|
||||||
/* width: 100%; */
|
|
||||||
|
|
||||||
/* 宽度占满 grid 单元格 */
|
|
||||||
|
|
||||||
/* height: 100%; */
|
|
||||||
|
|
||||||
/* 高度占满 grid 单元格 */
|
|
||||||
|
|
||||||
/* font-size: 20px; */
|
|
||||||
|
|
||||||
/* 调整字体大小 */
|
|
||||||
|
|
||||||
/* font-weight: bold; */
|
|
||||||
|
|
||||||
/* 字体加粗 */
|
|
||||||
|
|
||||||
/* border-radius: 4px; */
|
|
||||||
|
|
||||||
/* 按钮圆角 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.ppy-btn:active {
|
|
||||||
background-color: #d5d5d5;
|
|
||||||
border-color: #a0a0a0;
|
|
||||||
box-shadow:
|
|
||||||
inset 1px 1px 3px rgb(0 0 0 / 30%),
|
|
||||||
inset -1px -1px 3px rgb(255 255 255 / 60%);
|
|
||||||
transform: scale(0.98);
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-item {
|
|
||||||
/* @apply bg-gray-200/50 p-[2px]; */
|
|
||||||
font-size: 12px;
|
|
||||||
|
|
||||||
/* border: 1px solid white; */
|
|
||||||
}
|
|
||||||
|
|
||||||
[alt='频谱仪设备'] {
|
|
||||||
opacity: 1;
|
|
||||||
transition: opacity 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* li,
|
|
||||||
.ppy-btns,
|
|
||||||
[data-box='屏幕'],
|
|
||||||
[data-box='菜单标题'] {
|
|
||||||
box-shadow: 0 0 0 1px rgba(255, 0, 0, 0.5);
|
|
||||||
} */
|
|
||||||
</style>
|
|
Before Width: | Height: | Size: 447 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 705 KiB |
Before Width: | Height: | Size: 810 KiB |
@ -18,32 +18,32 @@ const readyPromise = new Promise<void>((resolve) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const 频谱瀑布图Layout = {
|
const 频谱瀑布图Layout = {
|
||||||
title: { text: '频谱瀑布图' },
|
title: '频谱瀑布图',
|
||||||
xaxis: {
|
xaxis: {
|
||||||
title: { text: '频率 (Hz)' },
|
title: '频率 (Hz)',
|
||||||
// range: [0, 22_050],
|
// range: [0, 22_050],
|
||||||
showgrid: false,
|
showgrid: false,
|
||||||
tickformat: ',d', // 设置为带逗号的整数格式 (推荐,更易读)
|
tickformat: ',d', // 设置为带逗号的整数格式 (推荐,更易读)
|
||||||
},
|
},
|
||||||
yaxis: {
|
yaxis: {
|
||||||
title: { text: '时间步' },
|
title: '时间步',
|
||||||
showgrid: false,
|
showgrid: false,
|
||||||
tickformat: ',d', // 设置为带逗号的整数格式 (推荐,更易读)
|
tickformat: ',d', // 设置为带逗号的整数格式 (推荐,更易读)
|
||||||
},
|
},
|
||||||
margin: { l: 60, r: 40, b: 40, t: 60 },
|
margin: { l: 60, r: 40, b: 40, t: 60 },
|
||||||
} satisfies Partial<import('plotly.js-dist-min').Layout>;
|
};
|
||||||
|
|
||||||
const 频谱图Layout = {
|
const 频谱图Layout = {
|
||||||
title: { text: '频谱图' },
|
title: '频谱图',
|
||||||
xaxis: {
|
xaxis: {
|
||||||
title: { text: '频率 (Hz)' },
|
title: '频率 (Hz)',
|
||||||
// range: [0, 22_050],
|
// range: [0, 22_050],
|
||||||
showgrid: true,
|
showgrid: true,
|
||||||
gridcolor: '#eee',
|
gridcolor: '#eee',
|
||||||
tickformat: ',d', // 设置为带逗号的整数格式 (推荐,更易读)
|
tickformat: ',d', // 设置为带逗号的整数格式 (推荐,更易读)
|
||||||
},
|
},
|
||||||
yaxis: {
|
yaxis: {
|
||||||
title: { text: '幅度 (dB)' },
|
title: '幅度 (dB)',
|
||||||
showgrid: true, // 显示网格线
|
showgrid: true, // 显示网格线
|
||||||
gridcolor: '#eee',
|
gridcolor: '#eee',
|
||||||
tickformat: ',d', // 设置为带逗号的整数格式 (推荐,更易读)
|
tickformat: ',d', // 设置为带逗号的整数格式 (推荐,更易读)
|
||||||
|
@ -1,321 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import type { MenuOption } from 'naive-ui';
|
|
||||||
|
|
||||||
import { createGetRoutes } from '@/plugins/router';
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// 响应式断点检测
|
|
||||||
const isMobile = ref(false);
|
|
||||||
const isTablet = ref(false);
|
|
||||||
|
|
||||||
// 检测屏幕尺寸
|
|
||||||
const updateScreenSize = () => {
|
|
||||||
const width = window.innerWidth;
|
|
||||||
const wasMobile = isMobile.value;
|
|
||||||
|
|
||||||
isMobile.value = width < 768;
|
|
||||||
isTablet.value = width >= 768 && width < 1024;
|
|
||||||
|
|
||||||
// 当从移动端切换到桌面端时,关闭抽屉并重置折叠状态
|
|
||||||
if (wasMobile && !isMobile.value) {
|
|
||||||
drawerVisible.value = false;
|
|
||||||
collapsed.value = false;
|
|
||||||
}
|
|
||||||
// 当从桌面端切换到移动端时,关闭抽屉
|
|
||||||
else if (!wasMobile && isMobile.value) {
|
|
||||||
drawerVisible.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 侧边栏状态管理
|
|
||||||
const collapsed = ref(false);
|
|
||||||
const drawerVisible = ref(false);
|
|
||||||
|
|
||||||
// 初始化屏幕尺寸检测
|
|
||||||
onMounted(() => {
|
|
||||||
updateScreenSize();
|
|
||||||
window.addEventListener('resize', updateScreenSize);
|
|
||||||
|
|
||||||
// 移动端默认收起侧边栏
|
|
||||||
if (isMobile.value) {
|
|
||||||
collapsed.value = true;
|
|
||||||
drawerVisible.value = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
window.removeEventListener('resize', updateScreenSize);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 菜单项类型定义
|
|
||||||
type MenuItemWithRoute = MenuOption & {
|
|
||||||
routeName?: string;
|
|
||||||
parentId?: string;
|
|
||||||
originalPath?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 生成菜单项
|
|
||||||
const menuOptions = computed(() => {
|
|
||||||
let flatArray: MenuItemWithRoute[] = createGetRoutes(router)()
|
|
||||||
.filter((route) => !route.path.includes('/:'))
|
|
||||||
.filter((route) => !route.meta.hidden)
|
|
||||||
.map((route) => ({
|
|
||||||
key: route.path,
|
|
||||||
label: route.meta.title || `${(route.name as string) || route.path}`,
|
|
||||||
routeName: route.name as string,
|
|
||||||
}));
|
|
||||||
|
|
||||||
flatArray = flatArray.map((item) => {
|
|
||||||
const originalPath = item.key as string; // 保存原始路径
|
|
||||||
let id = item.key as string;
|
|
||||||
if (flatArray.some((item) => (item.key as string).startsWith(`${id}/`))) {
|
|
||||||
id = `${id}/index`;
|
|
||||||
}
|
|
||||||
// 去掉最前面的 /
|
|
||||||
id = id.replace(/^\//, '');
|
|
||||||
|
|
||||||
let parentId = id.replace(/\/[^/]+$/, '');
|
|
||||||
if (parentId === id) {
|
|
||||||
parentId = '_ROOT_';
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
key: id,
|
|
||||||
parentId,
|
|
||||||
originalPath, // 保存原始路径用于后续映射
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const groupItems: MenuItemWithRoute[] = [];
|
|
||||||
for (const flatArrayItem of flatArray) {
|
|
||||||
if (!groupItems.some((item) => item.key === flatArrayItem.parentId) && flatArrayItem.parentId !== '_ROOT_') {
|
|
||||||
let groupItemParentId = flatArrayItem.parentId!.replace(/\/[^/]+$/, '');
|
|
||||||
if (groupItemParentId === flatArrayItem.parentId) groupItemParentId = '_ROOT_';
|
|
||||||
groupItems.push({
|
|
||||||
key: flatArrayItem.parentId!,
|
|
||||||
label: `Group ${flatArrayItem.parentId}`,
|
|
||||||
parentId: groupItemParentId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const tree = arrayToTree([...flatArray, ...groupItems], {
|
|
||||||
id: 'key',
|
|
||||||
parentId: 'parentId',
|
|
||||||
rootId: '_ROOT_',
|
|
||||||
});
|
|
||||||
|
|
||||||
// 递归转换树形结构为 naive-ui menu 格式
|
|
||||||
function convertToMenuOptions(tree: MenuItemWithRoute[]): MenuOption[] {
|
|
||||||
return tree.map((item) => {
|
|
||||||
const menuItem: MenuOption = {
|
|
||||||
key: item.key,
|
|
||||||
label: item.label,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (item.children && item.children.length > 0) {
|
|
||||||
menuItem.children = convertToMenuOptions(item.children);
|
|
||||||
} else if (item.routeName) {
|
|
||||||
// 叶子节点,存储路由映射
|
|
||||||
menuRouteMap.set(item.key as string, item.routeName);
|
|
||||||
// 同时存储路径到 key 的映射(用于高亮显示)
|
|
||||||
if (item.originalPath) {
|
|
||||||
pathToKeyMap.set(item.originalPath, item.key as string);
|
|
||||||
}
|
|
||||||
(menuItem as MenuItemWithRoute).routeName = item.routeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return menuItem;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清空之前的映射
|
|
||||||
menuRouteMap.clear();
|
|
||||||
pathToKeyMap.clear();
|
|
||||||
const result = convertToMenuOptions(tree);
|
|
||||||
|
|
||||||
// 菜单生成后,重新设置当前选中的菜单项
|
|
||||||
nextTick(() => {
|
|
||||||
const currentPath = router.currentRoute.value.path;
|
|
||||||
const menuKey = pathToKeyMap.get(currentPath);
|
|
||||||
if (menuKey) {
|
|
||||||
selectedKey.value = menuKey;
|
|
||||||
} else {
|
|
||||||
const pathWithoutSlash = currentPath.replace(/^\//, '');
|
|
||||||
selectedKey.value = pathWithoutSlash;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 当前选中的菜单项
|
|
||||||
const selectedKey = ref<string>();
|
|
||||||
|
|
||||||
// 存储菜单项与路由名称的映射
|
|
||||||
const menuRouteMap = new Map<string, string>();
|
|
||||||
|
|
||||||
// 存储路由路径与菜单 key 的映射(用于高亮显示)
|
|
||||||
const pathToKeyMap = new Map<string, string>();
|
|
||||||
|
|
||||||
// 处理菜单点击
|
|
||||||
const handleMenuSelect = (key: string, item: MenuOption) => {
|
|
||||||
const routeName = menuRouteMap.get(key) || (item as MenuItemWithRoute).routeName;
|
|
||||||
if (routeName) {
|
|
||||||
router.push({ name: routeName as never });
|
|
||||||
|
|
||||||
// 移动端点击菜单项后自动收起侧边栏
|
|
||||||
if (isMobile.value) {
|
|
||||||
drawerVisible.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听路由变化,更新选中的菜单项
|
|
||||||
watch(
|
|
||||||
() => router.currentRoute.value.path,
|
|
||||||
(newPath) => {
|
|
||||||
// 使用路径到 key 的映射来找到对应的菜单项
|
|
||||||
const menuKey = pathToKeyMap.get(newPath);
|
|
||||||
if (menuKey) {
|
|
||||||
selectedKey.value = menuKey;
|
|
||||||
} else {
|
|
||||||
// 如果没有找到精确匹配,尝试去掉前面的 / 再匹配
|
|
||||||
const pathWithoutSlash = newPath.replace(/^\//, '');
|
|
||||||
selectedKey.value = pathWithoutSlash;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
// 切换侧边栏状态
|
|
||||||
const toggleSidebar = () => {
|
|
||||||
if (isMobile.value) {
|
|
||||||
// 移动端使用抽屉模式
|
|
||||||
drawerVisible.value = !drawerVisible.value;
|
|
||||||
} else {
|
|
||||||
// 桌面端使用折叠模式
|
|
||||||
collapsed.value = !collapsed.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-layout :has-sider="!isMobile">
|
|
||||||
<!-- 移动端抽屉 -->
|
|
||||||
<n-drawer
|
|
||||||
v-if="isMobile"
|
|
||||||
v-model:show="drawerVisible"
|
|
||||||
:width="280"
|
|
||||||
placement="left"
|
|
||||||
:trap-focus="false"
|
|
||||||
:block-scroll="false"
|
|
||||||
>
|
|
||||||
<n-drawer-content title="菜单" :native-scrollbar="false">
|
|
||||||
<n-menu :options="menuOptions" :value="selectedKey" @update:value="handleMenuSelect" />
|
|
||||||
</n-drawer-content>
|
|
||||||
</n-drawer>
|
|
||||||
|
|
||||||
<!-- 桌面端侧边栏 -->
|
|
||||||
<n-layout-sider
|
|
||||||
v-if="!isMobile"
|
|
||||||
:collapsed="collapsed"
|
|
||||||
:native-scrollbar="false"
|
|
||||||
bordered
|
|
||||||
collapse-mode="width"
|
|
||||||
:collapsed-width="64"
|
|
||||||
:width="240"
|
|
||||||
show-trigger
|
|
||||||
@collapse="collapsed = true"
|
|
||||||
@expand="collapsed = false"
|
|
||||||
>
|
|
||||||
<n-menu
|
|
||||||
:collapsed="collapsed"
|
|
||||||
:collapsed-width="64"
|
|
||||||
:collapsed-icon-size="22"
|
|
||||||
:options="menuOptions"
|
|
||||||
:value="selectedKey"
|
|
||||||
@update:value="handleMenuSelect"
|
|
||||||
/>
|
|
||||||
</n-layout-sider>
|
|
||||||
|
|
||||||
<n-layout>
|
|
||||||
<n-layout-header
|
|
||||||
bordered
|
|
||||||
:style="{
|
|
||||||
height: '64px',
|
|
||||||
padding: isMobile ? '0 16px' : '0 24px',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<n-button
|
|
||||||
quaternary
|
|
||||||
@click="toggleSidebar"
|
|
||||||
:style="{
|
|
||||||
marginRight: isMobile ? '8px' : '12px',
|
|
||||||
padding: isMobile ? '8px' : '6px',
|
|
||||||
}"
|
|
||||||
:size="isMobile ? 'medium' : 'small'"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<n-icon :size="isMobile ? 20 : 18">
|
|
||||||
<svg viewBox="0 0 24 24">
|
|
||||||
<path
|
|
||||||
v-if="!isMobile && collapsed"
|
|
||||||
fill="currentColor"
|
|
||||||
d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
v-else-if="!isMobile && !collapsed"
|
|
||||||
fill="currentColor"
|
|
||||||
d="M3 18h13v-2H3v2zm0-5h10v-2H3v2zm0-7v2h13V6H3zm18 9.59L17.42 12 21 8.41 19.59 7l-5 5 5 5L21 15.59z"
|
|
||||||
/>
|
|
||||||
<!-- 移动端始终显示菜单图标 -->
|
|
||||||
<path v-else fill="currentColor" d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />
|
|
||||||
</svg>
|
|
||||||
</n-icon>
|
|
||||||
</template>
|
|
||||||
</n-button>
|
|
||||||
<span
|
|
||||||
:style="{
|
|
||||||
fontSize: isMobile ? '16px' : '18px',
|
|
||||||
fontWeight: '500',
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
Vue TS Example
|
|
||||||
</span>
|
|
||||||
</n-layout-header>
|
|
||||||
|
|
||||||
<n-layout-content
|
|
||||||
:content-style="{
|
|
||||||
padding: isMobile ? '16px' : '24px',
|
|
||||||
minHeight: 'calc(100vh - 64px - 72px)', // 减去头部和底部高度
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<router-view />
|
|
||||||
</n-layout-content>
|
|
||||||
|
|
||||||
<n-layout-footer
|
|
||||||
bordered
|
|
||||||
:style="{
|
|
||||||
padding: isMobile ? '16px' : '24px',
|
|
||||||
textAlign: 'center',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
:style="{
|
|
||||||
color: 'var(--n-text-color-disabled)',
|
|
||||||
fontSize: isMobile ? '12px' : '14px',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
© 2025 Vue TS Example. All rights reserved.
|
|
||||||
</span>
|
|
||||||
</n-layout-footer>
|
|
||||||
</n-layout>
|
|
||||||
</n-layout>
|
|
||||||
</template>
|
|
@ -1,12 +1,7 @@
|
|||||||
import './styles';
|
import './styles';
|
||||||
|
|
||||||
import { LogLevels } from 'consola';
|
|
||||||
|
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
import { setupPlugins } from './plugins';
|
import { setupPlugins } from './plugins';
|
||||||
|
|
||||||
const autoInstallModules = import.meta.glob('./plugins/*.ts', { eager: true });
|
const autoInstallModules = import.meta.glob('./plugins/*.ts', { eager: true });
|
||||||
|
|
||||||
setupPlugins(createApp(App), autoInstallModules).mount('#app');
|
setupPlugins(createApp(App), autoInstallModules).mount('#app');
|
||||||
|
|
||||||
consola.level = LogLevels.verbose;
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
# 测试
|
|
||||||
|
|
||||||
这个文件是被 import 的
|
|
@ -1,11 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import MD from './MDPageImportMD.md';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<MD />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
@ -1,13 +0,0 @@
|
|||||||
<!--
|
|
||||||
http://localhost:4730/Page/PinPuYi
|
|
||||||
-->
|
|
||||||
<script setup lang="ts">
|
|
||||||
definePage({ meta: { title: '频谱仪', hidden: !$__DEV__ } });
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<template v-if="true">
|
|
||||||
<PinPuYi />
|
|
||||||
</template>
|
|
||||||
<template v-else> 🤡 </template>
|
|
||||||
</template>
|
|
@ -1,352 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { VueUiXy, type VueUiXyConfig, type VueUiXyDatasetItem } from 'vue-data-ui';
|
|
||||||
import 'vue-data-ui/style.css'; // If you are using multiple components, place styles import in your main
|
|
||||||
|
|
||||||
const config = computed<VueUiXyConfig>(() => {
|
|
||||||
return {
|
|
||||||
theme: undefined,
|
|
||||||
responsive: false,
|
|
||||||
customPalette: [],
|
|
||||||
useCssAnimation: true,
|
|
||||||
downsample: {
|
|
||||||
threshold: 500,
|
|
||||||
},
|
|
||||||
chart: {
|
|
||||||
fontFamily: 'inherit',
|
|
||||||
backgroundColor: '#FFFFFFff',
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
height: 600,
|
|
||||||
width: 1000,
|
|
||||||
zoom: {
|
|
||||||
show: true,
|
|
||||||
color: '#CCCCCCff',
|
|
||||||
highlightColor: '#4A4A4A',
|
|
||||||
fontSize: 14,
|
|
||||||
useResetSlot: false,
|
|
||||||
startIndex: null,
|
|
||||||
endIndex: null,
|
|
||||||
enableRangeHandles: true,
|
|
||||||
enableSelectionDrag: true,
|
|
||||||
minimap: {
|
|
||||||
show: true,
|
|
||||||
smooth: false,
|
|
||||||
selectedColor: '#1F77B4',
|
|
||||||
selectedColorOpacity: 0.2,
|
|
||||||
lineColor: '#1A1A1A',
|
|
||||||
selectionRadius: 2,
|
|
||||||
indicatorColor: '#1A1A1A',
|
|
||||||
verticalHandles: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
padding: {
|
|
||||||
top: 36,
|
|
||||||
right: 24,
|
|
||||||
bottom: 48,
|
|
||||||
left: 48,
|
|
||||||
},
|
|
||||||
highlighter: {
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
opacity: 5,
|
|
||||||
useLine: false,
|
|
||||||
lineDasharray: 2,
|
|
||||||
lineWidth: 1,
|
|
||||||
},
|
|
||||||
highlightArea: {
|
|
||||||
show: false,
|
|
||||||
from: 0,
|
|
||||||
to: 0,
|
|
||||||
color: '#CCCCCCff',
|
|
||||||
opacity: 20,
|
|
||||||
caption: {
|
|
||||||
text: 'Caption',
|
|
||||||
fontSize: 20,
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
bold: false,
|
|
||||||
offsetY: 0,
|
|
||||||
width: 'auto',
|
|
||||||
padding: 3,
|
|
||||||
textAlign: 'center',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
timeTag: {
|
|
||||||
show: false,
|
|
||||||
backgroundColor: '#e1e5e8ff',
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
fontSize: 12,
|
|
||||||
circleMarker: {
|
|
||||||
radius: 3,
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
stroke: '#e1e5e8ff',
|
|
||||||
showVerticalLines: false,
|
|
||||||
showHorizontalLines: false,
|
|
||||||
position: 'middle',
|
|
||||||
frame: {
|
|
||||||
show: false,
|
|
||||||
stroke: '#E1E5E8ff',
|
|
||||||
strokeWidth: 2,
|
|
||||||
strokeLinecap: 'round',
|
|
||||||
strokeLinejoin: 'round',
|
|
||||||
strokeDasharray: 0,
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
show: true,
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
fontSize: 16,
|
|
||||||
axis: {
|
|
||||||
yLabel: '',
|
|
||||||
yLabelOffsetX: 0,
|
|
||||||
xLabel: '',
|
|
||||||
xLabelOffsetY: 14,
|
|
||||||
fontSize: 12,
|
|
||||||
},
|
|
||||||
zeroLine: {
|
|
||||||
show: true,
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
showBaseline: true,
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
showBaseline: true,
|
|
||||||
commonScaleSteps: 10,
|
|
||||||
useIndividualScale: false,
|
|
||||||
stacked: false,
|
|
||||||
gap: 12,
|
|
||||||
labelWidth: 40,
|
|
||||||
formatter: null,
|
|
||||||
scaleMin: null,
|
|
||||||
scaleMax: null,
|
|
||||||
groupColor: '#1A1A1A',
|
|
||||||
scaleLabelOffsetX: 0,
|
|
||||||
scaleValueOffsetX: 0,
|
|
||||||
},
|
|
||||||
xAxisLabels: {
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
show: true,
|
|
||||||
values: [],
|
|
||||||
fontSize: 18,
|
|
||||||
showOnlyFirstAndLast: false,
|
|
||||||
showOnlyAtModulo: false,
|
|
||||||
modulo: 12,
|
|
||||||
yOffset: 8,
|
|
||||||
rotation: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
comments: {
|
|
||||||
show: true,
|
|
||||||
showInTooltip: true,
|
|
||||||
width: 200,
|
|
||||||
offsetX: 0,
|
|
||||||
offsetY: 0,
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
fontSize: 16,
|
|
||||||
prefix: '',
|
|
||||||
suffix: '',
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
show: true,
|
|
||||||
fontSize: 16,
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
text: 'Title',
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
fontSize: 20,
|
|
||||||
bold: true,
|
|
||||||
textAlign: 'center',
|
|
||||||
paddingLeft: 0,
|
|
||||||
paddingRight: 0,
|
|
||||||
subtitle: {
|
|
||||||
color: '#CCCCCCff',
|
|
||||||
text: '',
|
|
||||||
fontSize: 16,
|
|
||||||
bold: false,
|
|
||||||
},
|
|
||||||
show: true,
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
show: true,
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
backgroundColor: '#FFFFFFff',
|
|
||||||
fontSize: 14,
|
|
||||||
customFormat: null,
|
|
||||||
borderRadius: 4,
|
|
||||||
borderColor: '#e1e5e8',
|
|
||||||
borderWidth: 1,
|
|
||||||
backgroundOpacity: 30,
|
|
||||||
position: 'center',
|
|
||||||
offsetY: 24,
|
|
||||||
showTimeLabel: true,
|
|
||||||
showValue: true,
|
|
||||||
showPercentage: false,
|
|
||||||
roundingValue: 0,
|
|
||||||
roundingPercentage: 0,
|
|
||||||
},
|
|
||||||
userOptions: {
|
|
||||||
show: true,
|
|
||||||
showOnChartHover: false,
|
|
||||||
keepStateOnChartLeave: true,
|
|
||||||
position: 'right',
|
|
||||||
buttons: {
|
|
||||||
tooltip: true,
|
|
||||||
pdf: true,
|
|
||||||
csv: true,
|
|
||||||
img: true,
|
|
||||||
table: true,
|
|
||||||
labels: true,
|
|
||||||
fullscreen: true,
|
|
||||||
sort: false,
|
|
||||||
stack: true,
|
|
||||||
animation: false,
|
|
||||||
annotator: true,
|
|
||||||
},
|
|
||||||
buttonTitles: {
|
|
||||||
open: 'Open options',
|
|
||||||
close: 'Close options',
|
|
||||||
tooltip: 'Toggle tooltip',
|
|
||||||
pdf: 'Download PDF',
|
|
||||||
csv: 'Download CSV',
|
|
||||||
img: 'Download PNG',
|
|
||||||
table: 'Toggle table',
|
|
||||||
labels: 'Toggle labels',
|
|
||||||
fullscreen: 'Toggle fullscreen',
|
|
||||||
stack: 'Toggle stack mode',
|
|
||||||
annotator: 'Toggle annotator',
|
|
||||||
},
|
|
||||||
print: {
|
|
||||||
allowTaint: false,
|
|
||||||
backgroundColor: '#FFFFFFff',
|
|
||||||
useCORS: false,
|
|
||||||
onclone: null,
|
|
||||||
scale: 2,
|
|
||||||
logging: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
bar: {
|
|
||||||
borderRadius: 2,
|
|
||||||
useGradient: true,
|
|
||||||
periodGap: 0.1,
|
|
||||||
border: {
|
|
||||||
useSerieColor: false,
|
|
||||||
strokeWidth: 1,
|
|
||||||
stroke: '#FFFFFFff',
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
show: true,
|
|
||||||
offsetY: -8,
|
|
||||||
rounding: 0,
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
formatter: null,
|
|
||||||
},
|
|
||||||
serieName: {
|
|
||||||
show: false,
|
|
||||||
offsetY: -6,
|
|
||||||
useAbbreviation: true,
|
|
||||||
abbreviationSize: 3,
|
|
||||||
useSerieColor: true,
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
bold: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
line: {
|
|
||||||
radius: 6,
|
|
||||||
useGradient: false,
|
|
||||||
strokeWidth: 2,
|
|
||||||
cutNullValues: false,
|
|
||||||
dot: {
|
|
||||||
hideAboveMaxSerieLength: 62,
|
|
||||||
useSerieColor: false,
|
|
||||||
fill: '#FFFFFF',
|
|
||||||
strokeWidth: 2,
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
show: true,
|
|
||||||
offsetY: -16,
|
|
||||||
rounding: 0,
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
formatter: null,
|
|
||||||
},
|
|
||||||
area: {
|
|
||||||
useGradient: true,
|
|
||||||
opacity: 20,
|
|
||||||
},
|
|
||||||
tag: {
|
|
||||||
followValue: true,
|
|
||||||
formatter: null,
|
|
||||||
fontSize: 14,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plot: {
|
|
||||||
radius: 6,
|
|
||||||
useGradient: true,
|
|
||||||
dot: {
|
|
||||||
useSerieColor: true,
|
|
||||||
fill: '#FFFFFF',
|
|
||||||
strokeWidth: 0.5,
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
show: true,
|
|
||||||
offsetY: -8,
|
|
||||||
rounding: 0,
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
formatter: null,
|
|
||||||
},
|
|
||||||
tag: {
|
|
||||||
followValue: true,
|
|
||||||
formatter: null,
|
|
||||||
fontSize: 14,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
table: {
|
|
||||||
responsiveBreakpoint: 400,
|
|
||||||
rounding: 0,
|
|
||||||
sparkline: true,
|
|
||||||
showSum: true,
|
|
||||||
columnNames: {
|
|
||||||
period: 'Period',
|
|
||||||
total: 'Total',
|
|
||||||
},
|
|
||||||
th: {
|
|
||||||
backgroundColor: '#FAFAFAff',
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
outline: '',
|
|
||||||
},
|
|
||||||
td: {
|
|
||||||
backgroundColor: '#FAFAFAff',
|
|
||||||
color: '#1A1A1Aff',
|
|
||||||
outline: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
showTable: false,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const dataset = computed<VueUiXyDatasetItem[]>(() => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
name: 'Serie name',
|
|
||||||
series: [1, 9, 7, 2, 12, 16, 17, 30, 16, 23],
|
|
||||||
color: '#1f77b4',
|
|
||||||
type: 'line',
|
|
||||||
shape: 'circle',
|
|
||||||
useArea: false,
|
|
||||||
useProgression: false,
|
|
||||||
dataLabels: true,
|
|
||||||
smooth: true,
|
|
||||||
dashed: false,
|
|
||||||
useTag: 'none',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<!-- Using a wrapper is optional -->
|
|
||||||
<div :style="{ width: '600px' }">
|
|
||||||
<VueUiXy :config="config" :dataset="dataset" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
@ -27,7 +27,15 @@ import { Input as ShaInput } from '@/shadcn/components/ui/input';
|
|||||||
<ShadcnButton variant="ghost">Ghost</ShadcnButton>
|
<ShadcnButton variant="ghost">Ghost</ShadcnButton>
|
||||||
<ShadcnButton variant="link">Link</ShadcnButton>
|
<ShadcnButton variant="link">Link</ShadcnButton>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="demo-block">
|
||||||
|
<VBtn>VBtn</VBtn>
|
||||||
|
<v-btn variant="outlined"> Button </v-btn>
|
||||||
|
<v-btn variant="tonal"> Button </v-btn>
|
||||||
|
<v-btn variant="text"> Button </v-btn>
|
||||||
|
<v-btn variant="plain"> Button </v-btn>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="demo-block">
|
<div class="demo-block">
|
||||||
<a-input placeholder="Ant Design" />
|
<a-input placeholder="Ant Design" />
|
||||||
<InputText placeholder="Primevue" />
|
<InputText placeholder="Primevue" />
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
<script setup lang="ts"></script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<n-card>
|
|
||||||
<n-divider title-placement="left">
|
|
||||||
<n-text depth="3"> Naive UI Components Divider </n-text>
|
|
||||||
</n-divider>
|
|
||||||
</n-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
@ -28,7 +28,7 @@ defineOptions({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const refresh = () => {
|
const refresh = () => {
|
||||||
state.list.splice(0);
|
state.list.splice(0, state.list.length);
|
||||||
state.page = 0;
|
state.page = 0;
|
||||||
state.complete = false;
|
state.complete = false;
|
||||||
loadMore();
|
loadMore();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { DataLoaderPlugin } from 'unplugin-vue-router/data-loaders';
|
import { DataLoaderPlugin } from 'unplugin-vue-router/data-loaders';
|
||||||
import { setupLayouts } from 'virtual:meta-layouts';
|
import { setupLayouts } from 'virtual:meta-layouts';
|
||||||
// import { createGetRoutes, setupLayouts } from 'virtual:generated-layouts';
|
// import { createGetRoutes, setupLayouts } from 'virtual:generated-layouts';
|
||||||
import { createRouter, createWebHistory } from 'vue-router';
|
import { createRouter, createWebHistory } from 'vue-router/auto';
|
||||||
import { handleHotUpdate, routes } from 'vue-router/auto-routes';
|
import { handleHotUpdate, routes } from 'vue-router/auto-routes';
|
||||||
|
|
||||||
const setupLayoutsResult = setupLayouts(routes);
|
const setupLayoutsResult = setupLayouts(routes);
|
||||||
|
11
src/plugins/vuetify.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { createVuetify } from 'vuetify';
|
||||||
|
import 'vuetify/styles';
|
||||||
|
|
||||||
|
export function install({ app }: { app: import('vue').App<Element> }) {
|
||||||
|
const vuetify = createVuetify({
|
||||||
|
// components,
|
||||||
|
// directives,
|
||||||
|
});
|
||||||
|
|
||||||
|
app.use(vuetify);
|
||||||
|
}
|
@ -13,9 +13,4 @@ import 'primeicons/primeicons.css';
|
|||||||
import './reset/reset-primevue.css';
|
import './reset/reset-primevue.css';
|
||||||
import './reset/reset-antdv.less';
|
import './reset/reset-antdv.less';
|
||||||
|
|
||||||
// 通用字体
|
|
||||||
import 'vfonts/Lato.css';
|
|
||||||
// 等宽字体
|
|
||||||
import 'vfonts/FiraCode.css';
|
|
||||||
//
|
|
||||||
import 'virtual:uno.css';
|
import 'virtual:uno.css';
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
declare global {
|
|
||||||
const $__DEV__: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'vue' {
|
|
||||||
export interface ComponentCustomProperties {
|
|
||||||
$__DEV__: boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {};
|
|
@ -1,4 +1,12 @@
|
|||||||
declare module '*.vue' {
|
declare global {
|
||||||
|
const $__DEV__: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'vue' {
|
||||||
|
export interface ComponentCustomProperties {
|
||||||
|
$__DEV__: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
import type { ComponentOptions } from 'vue';
|
import type { ComponentOptions } from 'vue';
|
||||||
|
|
||||||
const Component: ComponentOptions;
|
const Component: ComponentOptions;
|
||||||
@ -11,3 +19,5 @@ declare module '*.md' {
|
|||||||
const Component: ComponentOptions;
|
const Component: ComponentOptions;
|
||||||
export default Component;
|
export default Component;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export {};
|
4
typed-router.d.ts
vendored
@ -34,12 +34,9 @@ declare module 'vue-router/auto-routes' {
|
|||||||
'PageIframePageSpectrogram': RouteRecordInfo<'PageIframePageSpectrogram', '/Page/iframe-page/Spectrogram', Record<never, never>, Record<never, never>>,
|
'PageIframePageSpectrogram': RouteRecordInfo<'PageIframePageSpectrogram', '/Page/iframe-page/Spectrogram', Record<never, never>, Record<never, never>>,
|
||||||
'PageJSPage': RouteRecordInfo<'PageJSPage', '/Page/JSPage', Record<never, never>, Record<never, never>>,
|
'PageJSPage': RouteRecordInfo<'PageJSPage', '/Page/JSPage', Record<never, never>, Record<never, never>>,
|
||||||
'PageMDPage': RouteRecordInfo<'PageMDPage', '/Page/MDPage', Record<never, never>, Record<never, never>>,
|
'PageMDPage': RouteRecordInfo<'PageMDPage', '/Page/MDPage', Record<never, never>, Record<never, never>>,
|
||||||
'PageMDPageImportMD': RouteRecordInfo<'PageMDPageImportMD', '/Page/MDPageImportMD', Record<never, never>, Record<never, never>>,
|
|
||||||
'PageP5Js': RouteRecordInfo<'PageP5Js', '/Page/p5_js', Record<never, never>, Record<never, never>>,
|
'PageP5Js': RouteRecordInfo<'PageP5Js', '/Page/p5_js', Record<never, never>, Record<never, never>>,
|
||||||
'PagePinPuYi': RouteRecordInfo<'PagePinPuYi', '/Page/PinPuYi', Record<never, never>, Record<never, never>>,
|
|
||||||
'PageStyle': RouteRecordInfo<'PageStyle', '/Page/Style', Record<never, never>, Record<never, never>>,
|
'PageStyle': RouteRecordInfo<'PageStyle', '/Page/Style', Record<never, never>, Record<never, never>>,
|
||||||
'PageViteAssets': RouteRecordInfo<'PageViteAssets', '/Page/vite-assets', Record<never, never>, Record<never, never>>,
|
'PageViteAssets': RouteRecordInfo<'PageViteAssets', '/Page/vite-assets', Record<never, never>, Record<never, never>>,
|
||||||
'PageVueDataUi': RouteRecordInfo<'PageVueDataUi', '/Page/vue-data-ui', Record<never, never>, Record<never, never>>,
|
|
||||||
'PkgsUsageI18n': RouteRecordInfo<'PkgsUsageI18n', '/PkgsUsage/I18n', Record<never, never>, Record<never, never>>,
|
'PkgsUsageI18n': RouteRecordInfo<'PkgsUsageI18n', '/PkgsUsage/I18n', Record<never, never>, Record<never, never>>,
|
||||||
'PkgsUsageTsEnumUtil': RouteRecordInfo<'PkgsUsageTsEnumUtil', '/PkgsUsage/ts-enum-util', Record<never, never>, Record<never, never>>,
|
'PkgsUsageTsEnumUtil': RouteRecordInfo<'PkgsUsageTsEnumUtil', '/PkgsUsage/ts-enum-util', Record<never, never>, Record<never, never>>,
|
||||||
'UIComponentsAntdV': RouteRecordInfo<'UIComponentsAntdV', '/UI-components/AntdV', Record<never, never>, Record<never, never>>,
|
'UIComponentsAntdV': RouteRecordInfo<'UIComponentsAntdV', '/UI-components/AntdV', Record<never, never>, Record<never, never>>,
|
||||||
@ -47,7 +44,6 @@ declare module 'vue-router/auto-routes' {
|
|||||||
'UIComponentsInfiniteLoading': RouteRecordInfo<'UIComponentsInfiniteLoading', '/UI-components/infinite-loading', Record<never, never>, Record<never, never>>,
|
'UIComponentsInfiniteLoading': RouteRecordInfo<'UIComponentsInfiniteLoading', '/UI-components/infinite-loading', Record<never, never>, Record<never, never>>,
|
||||||
'UIComponentsInfiniteLoadingDetail': RouteRecordInfo<'UIComponentsInfiniteLoadingDetail', '/UI-components/infinite-loading/detail', Record<never, never>, Record<never, never>>,
|
'UIComponentsInfiniteLoadingDetail': RouteRecordInfo<'UIComponentsInfiniteLoadingDetail', '/UI-components/infinite-loading/detail', Record<never, never>, Record<never, never>>,
|
||||||
'UIComponentsInspiraUI': RouteRecordInfo<'UIComponentsInspiraUI', '/UI-components/InspiraUI', Record<never, never>, Record<never, never>>,
|
'UIComponentsInspiraUI': RouteRecordInfo<'UIComponentsInspiraUI', '/UI-components/InspiraUI', Record<never, never>, Record<never, never>>,
|
||||||
'UIComponentsNaiveUI': RouteRecordInfo<'UIComponentsNaiveUI', '/UI-components/NaiveUI', Record<never, never>, Record<never, never>>,
|
|
||||||
'UIComponentsPrimeVue': RouteRecordInfo<'UIComponentsPrimeVue', '/UI-components/PrimeVue', Record<never, never>, Record<never, never>>,
|
'UIComponentsPrimeVue': RouteRecordInfo<'UIComponentsPrimeVue', '/UI-components/PrimeVue', Record<never, never>, Record<never, never>>,
|
||||||
'UIComponentsShadcnVue': RouteRecordInfo<'UIComponentsShadcnVue', '/UI-components/ShadcnVue', Record<never, never>, Record<never, never>>,
|
'UIComponentsShadcnVue': RouteRecordInfo<'UIComponentsShadcnVue', '/UI-components/ShadcnVue', Record<never, never>, Record<never, never>>,
|
||||||
'VueMacrosDefineRender': RouteRecordInfo<'VueMacrosDefineRender', '/VueMacros/DefineRender', Record<never, never>, Record<never, never>>,
|
'VueMacrosDefineRender': RouteRecordInfo<'VueMacrosDefineRender', '/VueMacros/DefineRender', Record<never, never>, Record<never, never>>,
|
||||||
|
@ -11,11 +11,11 @@ import Vue from '@vitejs/plugin-vue';
|
|||||||
import VueJsx from '@vitejs/plugin-vue-jsx';
|
import VueJsx from '@vitejs/plugin-vue-jsx';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import UnoCSS from 'unocss/vite';
|
import UnoCSS from 'unocss/vite';
|
||||||
import AutoImport from 'unplugin-auto-import/vite';
|
import UnpluginAutoImport from 'unplugin-auto-import/vite';
|
||||||
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
|
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
|
||||||
import IconsResolver from 'unplugin-icons/resolver';
|
import IconsResolver from 'unplugin-icons/resolver';
|
||||||
import Icons from 'unplugin-icons/vite';
|
import Icons from 'unplugin-icons/vite';
|
||||||
import { AntDesignVueResolver, NaiveUiResolver, TDesignResolver } from 'unplugin-vue-components/resolvers';
|
import { AntDesignVueResolver, TDesignResolver } from 'unplugin-vue-components/resolvers';
|
||||||
import Components from 'unplugin-vue-components/vite';
|
import Components from 'unplugin-vue-components/vite';
|
||||||
import VueMacros from 'unplugin-vue-macros/vite';
|
import VueMacros from 'unplugin-vue-macros/vite';
|
||||||
import Markdown from 'unplugin-vue-markdown/vite';
|
import Markdown from 'unplugin-vue-markdown/vite';
|
||||||
@ -25,12 +25,12 @@ import { createUtils4uAutoImports } from 'utils4u/auto-imports';
|
|||||||
import { type PluginOption } from 'vite';
|
import { type PluginOption } from 'vite';
|
||||||
import { checker } from 'vite-plugin-checker';
|
import { checker } from 'vite-plugin-checker';
|
||||||
import { vitePluginFakeServer } from 'vite-plugin-fake-server';
|
import { vitePluginFakeServer } from 'vite-plugin-fake-server';
|
||||||
import VitePluginImageTools from 'vite-plugin-image-tools';
|
|
||||||
import pluginPurgeCss from 'vite-plugin-purgecss-updated-v5';
|
import pluginPurgeCss from 'vite-plugin-purgecss-updated-v5';
|
||||||
import { viteSingleFile } from 'vite-plugin-singlefile';
|
import { viteSingleFile } from 'vite-plugin-singlefile';
|
||||||
import { viteStaticCopy } from 'vite-plugin-static-copy';
|
import { viteStaticCopy } from 'vite-plugin-static-copy';
|
||||||
import VueDevTools from 'vite-plugin-vue-devtools';
|
import VueDevTools from 'vite-plugin-vue-devtools';
|
||||||
import MetaLayouts from 'vite-plugin-vue-meta-layouts';
|
import MetaLayouts from 'vite-plugin-vue-meta-layouts';
|
||||||
|
import vuetify from 'vite-plugin-vuetify';
|
||||||
import { ViteWebfontDownload } from 'vite-plugin-webfont-dl';
|
import { ViteWebfontDownload } from 'vite-plugin-webfont-dl';
|
||||||
|
|
||||||
import { viteArchiverPlugin } from './vite.config.plugin.archiver';
|
import { viteArchiverPlugin } from './vite.config.plugin.archiver';
|
||||||
@ -66,8 +66,7 @@ export function Plugins() {
|
|||||||
|
|
||||||
// https://github.com/dishait/vite-plugin-vue-meta-layouts
|
// https://github.com/dishait/vite-plugin-vue-meta-layouts
|
||||||
MetaLayouts({
|
MetaLayouts({
|
||||||
// defaultLayout: 'sakai-vue/AppLayout',
|
defaultLayout: 'sakai-vue/AppLayout',
|
||||||
defaultLayout: 'naive-ui/AppLayout',
|
|
||||||
skipTopLevelRouteLayout: false, // 打开修复 https://github.com/JohnCampionJr/vite-plugin-vue-layouts/issues/134,默认为 false 关闭
|
skipTopLevelRouteLayout: false, // 打开修复 https://github.com/JohnCampionJr/vite-plugin-vue-layouts/issues/134,默认为 false 关闭
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@ -80,8 +79,11 @@ export function Plugins() {
|
|||||||
headEnabled: true,
|
headEnabled: true,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// https://github.com/vuetifyjs/vuetify-loader/tree/master/packages/vite-plugin#automatic-imports
|
||||||
|
vuetify({ autoImport: true /* styles: 'none' */ }), // Enabled by default
|
||||||
|
|
||||||
// https://github.com/antfu/unplugin-auto-import
|
// https://github.com/antfu/unplugin-auto-import
|
||||||
AutoImport({
|
UnpluginAutoImport({
|
||||||
dirs: [
|
dirs: [
|
||||||
// 'src/composables',
|
// 'src/composables',
|
||||||
'src/stores',
|
'src/stores',
|
||||||
@ -99,7 +101,6 @@ export function Plugins() {
|
|||||||
{
|
{
|
||||||
'consola/browser': ['consola'],
|
'consola/browser': ['consola'],
|
||||||
'vue-router/auto': ['useLink'],
|
'vue-router/auto': ['useLink'],
|
||||||
'naive-ui': ['useDialog', 'useMessage', 'useNotification', 'useLoadingBar'],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
resolvers: [TDesignResolver({ esm: true, library: 'mobile-vue' }), VantResolver({ importStyle: true })],
|
resolvers: [TDesignResolver({ esm: true, library: 'mobile-vue' }), VantResolver({ importStyle: true })],
|
||||||
@ -126,7 +127,6 @@ export function Plugins() {
|
|||||||
TDesignResolver({ esm: true, library: 'mobile-vue' }),
|
TDesignResolver({ esm: true, library: 'mobile-vue' }),
|
||||||
VantResolver({ importStyle: true }),
|
VantResolver({ importStyle: true }),
|
||||||
PrimeVueResolver(/* { components: { prefix: 'P' } } */),
|
PrimeVueResolver(/* { components: { prefix: 'P' } } */),
|
||||||
NaiveUiResolver(),
|
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@ -194,15 +194,6 @@ export function Plugins() {
|
|||||||
{ dest: cesiumBaseUrl, src: `${cesiumSource}/Widgets` },
|
{ dest: cesiumBaseUrl, src: `${cesiumSource}/Widgets` },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
VitePluginImageTools({
|
|
||||||
quality: 80,
|
|
||||||
enableWebp: true,
|
|
||||||
enableDev: false,
|
|
||||||
enableDevWebp: false,
|
|
||||||
// 排除字体 SVG 文件和可能有问题的 SVG 文件
|
|
||||||
excludes: /fonts\/.*\.svg$|Helvetica.*\.svg$/,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 检查是否在VS Code终端中运行
|
// 检查是否在VS Code终端中运行
|
||||||
|
@ -36,9 +36,6 @@ export default defineConfig(({ command, mode }) => {
|
|||||||
'satellite.js',
|
'satellite.js',
|
||||||
'ts-enum-util',
|
'ts-enum-util',
|
||||||
'unplugin-vue-router',
|
'unplugin-vue-router',
|
||||||
'unplugin-vue-router/runtime',
|
|
||||||
'unplugin-vue-router/data-loaders/basic',
|
|
||||||
'unplugin-vue-router/data-loaders/pinia-colada',
|
|
||||||
],
|
],
|
||||||
exclude: ['quill', 'chart.js/auto'],
|
exclude: ['quill', 'chart.js/auto'],
|
||||||
},
|
},
|
||||||
@ -56,7 +53,7 @@ export default defineConfig(({ command, mode }) => {
|
|||||||
// https://cn.rollupjs.org/configuration-options/#output-assetfilenames
|
// https://cn.rollupjs.org/configuration-options/#output-assetfilenames
|
||||||
// output: env.VITE_SPLIT_CHUNKS === 'true' ? (await import('utils4u/rollup')).createSplitChunkOutput() : undefined,
|
// output: env.VITE_SPLIT_CHUNKS === 'true' ? (await import('utils4u/rollup')).createSplitChunkOutput() : undefined,
|
||||||
output: {
|
output: {
|
||||||
// minifyInternalExports: false,
|
minifyInternalExports: false,
|
||||||
// manualChunks: {
|
// manualChunks: {
|
||||||
// 'vendor/utils4u': ['utils4u', 'utils4u/vue-use', 'utils4u/primevue'],
|
// 'vendor/utils4u': ['utils4u', 'utils4u/vue-use', 'utils4u/primevue'],
|
||||||
// 'vendor/vue': ['vue'],
|
// 'vendor/vue': ['vue'],
|
||||||
@ -70,14 +67,6 @@ export default defineConfig(({ command, mode }) => {
|
|||||||
manualChunks: {
|
manualChunks: {
|
||||||
'vendor/Cesium': ['cesium'],
|
'vendor/Cesium': ['cesium'],
|
||||||
},
|
},
|
||||||
// advancedChunks: {
|
|
||||||
// groups: [
|
|
||||||
// {
|
|
||||||
// name: 'vendor/cesium',
|
|
||||||
// test: 'cesium',
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sourcemap: mode !== 'production' || env.VITE_SOURCE_MAP === 'true',
|
sourcemap: mode !== 'production' || env.VITE_SOURCE_MAP === 'true',
|
||||||
|