create-bubbles 0.1.22 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/index.mjs +5 -0
  2. package/package.json +1 -1
  3. package/template-vp-monorepo-react-nestjs/.vscode/settings.json +3 -2
  4. package/template-vp-monorepo-react-nestjs/apps/server/src/database/schema.ts +63 -4
  5. package/template-vp-monorepo-react-nestjs/vite.config.ts +2 -1
  6. package/template-vp-vue-eslint-vapor/.env +6 -0
  7. package/template-vp-vue-eslint-vapor/.env.development +2 -0
  8. package/template-vp-vue-eslint-vapor/.env.production +2 -0
  9. package/template-vp-vue-eslint-vapor/.vite-hooks/commit-msg +1 -0
  10. package/template-vp-vue-eslint-vapor/.vite-hooks/pre-commit +1 -0
  11. package/template-vp-vue-eslint-vapor/.vscode/extensions.json +3 -0
  12. package/template-vp-vue-eslint-vapor/AGENTS.md +16 -0
  13. package/template-vp-vue-eslint-vapor/README.md +93 -0
  14. package/template-vp-vue-eslint-vapor/commitlint.config.js +1 -0
  15. package/template-vp-vue-eslint-vapor/eslint.config.js +13 -0
  16. package/template-vp-vue-eslint-vapor/index.html +13 -0
  17. package/template-vp-vue-eslint-vapor/package.json +64 -0
  18. package/template-vp-vue-eslint-vapor/pnpm-workspace.yaml +2 -0
  19. package/template-vp-vue-eslint-vapor/public/vite.svg +1 -0
  20. package/template-vp-vue-eslint-vapor/src/App.vue +7 -0
  21. package/template-vp-vue-eslint-vapor/src/api/index.ts +12 -0
  22. package/template-vp-vue-eslint-vapor/src/assets/icon/home.svg +3 -0
  23. package/template-vp-vue-eslint-vapor/src/assets/icon/logo.svg +1 -0
  24. package/template-vp-vue-eslint-vapor/src/assets/image/.gitkeep +0 -0
  25. package/template-vp-vue-eslint-vapor/src/components/Icon/svg-icon.vue +29 -0
  26. package/template-vp-vue-eslint-vapor/src/hooks/chart/lib.ts +57 -0
  27. package/template-vp-vue-eslint-vapor/src/hooks/chart/useEcharts.ts +65 -0
  28. package/template-vp-vue-eslint-vapor/src/layout/default/header/index.vue +57 -0
  29. package/template-vp-vue-eslint-vapor/src/layout/default/index.vue +138 -0
  30. package/template-vp-vue-eslint-vapor/src/main.ts +19 -0
  31. package/template-vp-vue-eslint-vapor/src/router/guard/index.ts +7 -0
  32. package/template-vp-vue-eslint-vapor/src/router/guard/permissionGuard.ts +13 -0
  33. package/template-vp-vue-eslint-vapor/src/router/index.ts +18 -0
  34. package/template-vp-vue-eslint-vapor/src/router/interface.ts +9 -0
  35. package/template-vp-vue-eslint-vapor/src/router/modules/index.ts +33 -0
  36. package/template-vp-vue-eslint-vapor/src/store/index.ts +11 -0
  37. package/template-vp-vue-eslint-vapor/src/store/modules/user.ts +17 -0
  38. package/template-vp-vue-eslint-vapor/src/styles/font.scss +0 -0
  39. package/template-vp-vue-eslint-vapor/src/styles/index.scss +29 -0
  40. package/template-vp-vue-eslint-vapor/src/styles/variables.scss +3 -0
  41. package/template-vp-vue-eslint-vapor/src/types/vite-env.d.ts +15 -0
  42. package/template-vp-vue-eslint-vapor/src/utils/env.ts +11 -0
  43. package/template-vp-vue-eslint-vapor/src/utils/request/core/index.ts +425 -0
  44. package/template-vp-vue-eslint-vapor/src/utils/request/core/utils.ts +39 -0
  45. package/template-vp-vue-eslint-vapor/src/utils/request/index.ts +44 -0
  46. package/template-vp-vue-eslint-vapor/src/views/example/echart/config.ts +1794 -0
  47. package/template-vp-vue-eslint-vapor/src/views/example/echart/index.vue +20 -0
  48. package/template-vp-vue-eslint-vapor/src/views/example/tree-chart.vue +16 -0
  49. package/template-vp-vue-eslint-vapor/src/views/home/index.vue +16 -0
  50. package/template-vp-vue-eslint-vapor/src/views/login/index.vue +9 -0
  51. package/template-vp-vue-eslint-vapor/tsconfig.json +32 -0
  52. package/template-vp-vue-eslint-vapor/tsconfig.tsbuildinfo +1 -0
  53. package/template-vp-vue-eslint-vapor/uno.config.ts +17 -0
  54. package/template-vp-vue-eslint-vapor/vite.config.ts +66 -0
package/dist/index.mjs CHANGED
@@ -40,6 +40,7 @@ Options:
40
40
 
41
41
  Available templates:
42
42
  ${colorMap.vue("vue-vp-eslint vue")}
43
+ ${colorMap.vue("vp-vue-eslint-vapor vue")}
43
44
  ${colorMap.react("react-rsbuild-biome react")}
44
45
  ${colorMap.react("vp-react react")}
45
46
  ${colorMap.react("vp-react-shadcn react")}
@@ -107,6 +108,10 @@ const FRAMEWORKS = [
107
108
  name: "vue-vp-eslint",
108
109
  display: "vp + eslint",
109
110
  color: colorMap.vue
111
+ }, {
112
+ name: "vp-vue-eslint-vapor",
113
+ display: "vp + eslint + vapor",
114
+ color: colorMap.vue
110
115
  }]
111
116
  },
112
117
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-bubbles",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "type": "module",
5
5
  "author": "bubbles plant",
6
6
  "bin": {
@@ -2,7 +2,7 @@
2
2
  "eslint.enable": false,
3
3
  "prettier.enable": false,
4
4
  "biome.enabled": false,
5
- "npm.scriptRunner": "vp",
5
+ // "npm.scriptRunner": "vp",
6
6
  "editor.defaultFormatter": "oxc.oxc-vscode",
7
7
  "[javascript]": {
8
8
  "editor.defaultFormatter": "oxc.oxc-vscode"
@@ -20,6 +20,7 @@
20
20
  "editor.formatOnSave": true,
21
21
  "editor.formatOnSaveMode": "file",
22
22
  "editor.codeActionsOnSave": {
23
- "source.fixAll.oxc": "explicit"
23
+ "source.organizeImports": "always",
24
+ "source.fixAll.oxc": "always"
24
25
  }
25
26
  }
@@ -1,14 +1,73 @@
1
- import { pgEnum } from 'drizzle-orm/pg-core'
2
- import { pgTable, serial, varchar, timestamp } from 'drizzle-orm/pg-core'
1
+ import {
2
+ index,
3
+ integer,
4
+ pgEnum,
5
+ pgTable,
6
+ serial,
7
+ timestamp,
8
+ uuid,
9
+ varchar,
10
+ } from 'drizzle-orm/pg-core'
3
11
 
4
- export const useStatusEnum = pgEnum('user_status', ['active', 'locked', 'disabled'])
12
+ export const userStatusEnum = pgEnum('user_status', ['active', 'locked', 'disabled'])
5
13
 
6
14
  export const authSessionStatusEnum = pgEnum('auth_session_status', ['active', 'revoked'])
7
15
 
16
+ export const refreshFamilyStatusEnum = pgEnum('refresh_family_status', [
17
+ 'active',
18
+ 'revoked',
19
+ 'compromised',
20
+ ])
21
+
22
+ export const refreshTokenStatusEnum = pgEnum('refresh_token_status', [
23
+ 'active',
24
+ 'consumed',
25
+ 'revoked',
26
+ ])
27
+
8
28
  export const users = pgTable('users', {
9
29
  id: serial('id').primaryKey(),
10
30
  name: varchar('name', { length: 100 }).notNull(),
11
31
  email: varchar('email', { length: 255 }).notNull().unique(),
12
- password: varchar('password', { length: 255 }).notNull(),
32
+ // 第一阶段先允许 null,旧账号完成密码回填后再改成 notNull
33
+ passwordHash: varchar('password_hash', { length: 255 }), // .notNull(),
34
+
35
+ status: userStatusEnum('status').default('active').notNull(),
36
+ authEpoch: integer('auth_epoch').default(1).notNull(),
37
+ passwordChangeAt: timestamp('password_change_at', {
38
+ withTimezone: true,
39
+ }),
40
+
13
41
  createdAt: timestamp('create_at').defaultNow().notNull(),
42
+ updatedAt: timestamp('update_at', { withTimezone: true }).defaultNow().notNull(),
43
+ })
44
+
45
+ export const authSessions = pgTable(
46
+ 'auth_sessions',
47
+ {
48
+ id: uuid('id').defaultRandom().primaryKey(),
49
+ userId: integer('user_id')
50
+ .notNull()
51
+ .references(() => users.id, { onDelete: 'restrict' }),
52
+ version: integer('version').default(1).notNull(),
53
+ status: authSessionStatusEnum('status').default('active').notNull(),
54
+ expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
55
+ revokedAt: timestamp('revoked_at', { withTimezone: true }),
56
+ revokeReason: varchar('revoke_reason', { length: 100 }),
57
+ ip: varchar('ip', { length: 64 }),
58
+ userAgent: varchar('user_agent', { length: 500 }),
59
+ createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
60
+ updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
61
+ },
62
+ (table) => [
63
+ index('auth_sessions_user_id_idx').on(table.userId),
64
+ index('auth_sessions_user_status_idx').on(table.userId, table.status),
65
+ ],
66
+ )
67
+
68
+ export const refreshTokenFamilies = pgTable('refresh_token_families', {
69
+ id: uuid('id').defaultRandom().primaryKey(),
70
+ sessionId: uuid('session_id')
71
+ .notNull()
72
+ .references(() => authSessions.id, { onDelete: 'restrict' }),
14
73
  })
@@ -9,8 +9,9 @@ export default defineConfig({
9
9
  singleQuote: true,
10
10
  },
11
11
  lint: {
12
+ plugins: ['unicorn', 'typescript', 'oxc', 'import'],
12
13
  jsPlugins: [{ name: 'vite-plus', specifier: 'vite-plus/oxlint-plugin' }],
13
- rules: { 'vite-plus/prefer-vite-plus-imports': 'error' },
14
+ rules: { 'vite-plus/prefer-vite-plus-imports': 'error', 'import/no-duplicates': 'error' },
14
15
  options: { typeAware: true, typeCheck: true },
15
16
  },
16
17
  run: {
@@ -0,0 +1,6 @@
1
+ VITE_PORT = 9999
2
+ VITE_PATH = '/'
3
+ VITE_APP_NAME = "xxx"
4
+
5
+ # 后端
6
+ VITE_API_AFFIX = 'api'
@@ -0,0 +1,2 @@
1
+ # 后端
2
+ VITE_API_URL = 'http://localhost:8080'
@@ -0,0 +1,2 @@
1
+ # 后端
2
+ VITE_API_URL = 'http://localhost:8080'
@@ -0,0 +1 @@
1
+ NO_COLOR=1 commitlint --edit "$1"
@@ -0,0 +1 @@
1
+ NO_COLOR=1 vp staged
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["VoidZero.vite-plus-extension-pack"]
3
+ }
@@ -0,0 +1,16 @@
1
+ <!--VITE PLUS START-->
2
+
3
+ # Using Vite+, the Unified Toolchain for the Web
4
+
5
+ This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called `vp`. Vite+ is distinct from Vite, and it invokes Vite through `vp dev` and `vp build`. Run `vp help` to print a list of commands and `vp <command> --help` for information about a specific command.
6
+
7
+ Docs are local at `node_modules/vite-plus/docs` or online at https://viteplus.dev/guide/.
8
+
9
+ ## Review Checklist
10
+
11
+ - [ ] Run `vp install` after pulling remote changes and before getting started.
12
+ - [ ] Run `vp check` and `vp test` to format, lint, type check and test changes.
13
+ - [ ] Check if there are `vite.config.ts` tasks or `package.json` scripts necessary for validation, run via `vp run <script>`.
14
+ - [ ] If setup, runtime, or package-manager behavior looks wrong, run `vp env doctor` and include its output when asking for help.
15
+
16
+ <!--VITE PLUS END-->
@@ -0,0 +1,93 @@
1
+ # template-vp-vue-eslint-vapor
2
+
3
+ Vue 3 Vapor 项目模板,基于 Vite+ 统一工具链,集成 Antdv Next UI 组件库、UnoCSS 原子化样式和 ESLint 代码规范。
4
+
5
+ ## 技术栈
6
+
7
+ | 分类 | 技术 | 说明 |
8
+ | --------- | -------------------------------------- | ----------------------------------------------- |
9
+ | 构建工具 | Vite+ (`vp`) | 统一工具链,封装 Vite + Rolldown + Oxlint |
10
+ | 框架 | Vue 3.6 RC | Composition API + `<script setup>` + Vapor 模式 |
11
+ | 语言 | TypeScript 6 | 配合 vue-tsc 进行类型检查 |
12
+ | UI 组件库 | Antdv Next | 自动按需导入 |
13
+ | 状态管理 | Pinia | 含持久化插件 |
14
+ | 路由 | Vue Router 5 | |
15
+ | 请求库 | Alova | 基于 Axios 适配器,双调用实例 |
16
+ | 样式方案 | UnoCSS | Wind4 + Attributify 预设 |
17
+ | 代码规范 | ESLint (@antfu/eslint-config) + OxLint | |
18
+ | Git 钩子 | Vite+ hooks + Commitlint | |
19
+
20
+ ## 快速开始
21
+
22
+ ```bash
23
+ # 安装依赖
24
+ pnpm install
25
+
26
+ # 启动开发服务器
27
+ pnpm dev
28
+
29
+ # 构建生产包
30
+ pnpm build
31
+
32
+ # 代码检查
33
+ pnpm lint
34
+
35
+ # 代码修复
36
+ pnpm lint:fix
37
+ ```
38
+
39
+ ## 目录结构
40
+
41
+ ```
42
+ src/
43
+ ├── api/ # API 接口定义
44
+ ├── assets/ # 静态资源
45
+ │ ├── icon/ # SVG 图标
46
+ │ └── image/ # 图片资源
47
+ ├── components/ # 公共组件
48
+ │ └── Icon/ # SVG 图标组件
49
+ ├── hooks/ # 组合式函数
50
+ ├── layout/ # 布局组件
51
+ │ └── default/ # 默认布局(侧边栏 + 顶部栏)
52
+ ├── router/ # 路由配置
53
+ │ ├── guard/ # 路由守卫
54
+ │ └── modules/ # 路由模块
55
+ ├── store/ # Pinia 状态管理
56
+ │ └── modules/ # 业务 Store
57
+ ├── styles/ # 全局样式
58
+ ├── types/ # 类型声明(自动生成)
59
+ ├── utils/ # 工具函数
60
+ │ └── request/ # Alova 请求封装
61
+ ├── views/ # 页面视图
62
+ ├── App.vue # 根组件
63
+ └── main.ts # 应用入口
64
+ ```
65
+
66
+ ## 环境变量
67
+
68
+ | 文件 | 用途 |
69
+ | ------------------ | ------------ |
70
+ | `.env` | 公共环境变量 |
71
+ | `.env.development` | 开发环境 |
72
+ | `.env.production` | 生产环境 |
73
+
74
+ 关键变量:
75
+
76
+ | 变量名 | 说明 |
77
+ | ---------------- | ------------------------ |
78
+ | `VITE_PORT` | 开发服务器端口 |
79
+ | `VITE_API_URL` | 后端 API 地址 |
80
+ | `VITE_API_AFFIX` | API 路由前缀(用于代理) |
81
+ | `VITE_APP_NAME` | 应用名称 |
82
+
83
+ ## Vapor 模式
84
+
85
+ 模板在 `vite.config.ts` 中通过 `@vitejs/plugin-vue` 开启 `features.vapor`,用于体验 Vue 3.6 的 Vapor 编译模式。
86
+
87
+ 当前使用 Vue RC 版本,更适合功能验证和提前适配;对稳定性要求较高的生产项目建议选择稳定版 Vue 模板。
88
+
89
+ ## 代码规范
90
+
91
+ - **ESLint**:使用 `@antfu/eslint-config`,单引号、无分号、自动排序 imports
92
+ - **OxLint**:作为 ESLint 的补充,提供更快的 lint 速度
93
+ - **Commitlint**:提交信息需遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范
@@ -0,0 +1 @@
1
+ export default { extends: ["@commitlint/config-conventional"] };
@@ -0,0 +1,13 @@
1
+ import antfu from '@antfu/eslint-config'
2
+ import oxlint from 'eslint-plugin-oxlint'
3
+
4
+ export default antfu(
5
+ {
6
+ formatters: {
7
+ css: true,
8
+ html: true,
9
+ },
10
+ vue: true,
11
+ unocss: true,
12
+ },
13
+ ).append(...oxlint.configs['flat/recommended'])
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Vite + Vue + TS</title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/main.ts"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "template-vp-vue-eslint-vapor",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vp dev --mode development",
8
+ "build": "vue-tsc -b && vp build",
9
+ "preview": "vp preview",
10
+ "lint": "oxlint && eslint",
11
+ "lint:fix": "oxlint && eslint --fix",
12
+ "prepare": "vp config"
13
+ },
14
+ "dependencies": {
15
+ "@alova/adapter-axios": "^2.0.20",
16
+ "@antdv-next/icons": "^1.1.1",
17
+ "alova": "^3.5.3",
18
+ "antdv-next": "^1.4.5",
19
+ "axios": "^1.18.1",
20
+ "dayjs": "^1.11.21",
21
+ "echarts": "^6.1.0",
22
+ "nprogress": "^0.2.0",
23
+ "pinia": "^4.0.2",
24
+ "pinia-plugin-persistedstate": "^4.7.1",
25
+ "radashi": "^12.9.1",
26
+ "vue": "3.6.0-rc.2",
27
+ "vue-router": "^5.2.0"
28
+ },
29
+ "devDependencies": {
30
+ "@antdv-next/auto-import-resolver": "^1.1.0",
31
+ "@antfu/eslint-config": "^9.2.0",
32
+ "@commitlint/cli": "^21.2.1",
33
+ "@commitlint/config-conventional": "^21.2.0",
34
+ "@types/node": "^26.1.1",
35
+ "@types/nprogress": "^0.2.3",
36
+ "@unocss/eslint-plugin": "^66.7.5",
37
+ "@unocss/preset-attributify": "^66.7.5",
38
+ "@unocss/preset-wind4": "^66.7.5",
39
+ "@vitejs/plugin-vue": "^6.0.8",
40
+ "@vue/tsconfig": "^0.9.1",
41
+ "eslint": "10.8.0",
42
+ "eslint-plugin-format": "^2.0.1",
43
+ "eslint-plugin-oxlint": "^1.75.0",
44
+ "fast-glob": "^3.3.3",
45
+ "oxlint": "^1.75.0",
46
+ "sass": "^1.102.0",
47
+ "typescript": "^6.0.3",
48
+ "unocss": "66.7.5",
49
+ "unplugin-auto-import": "^21.0.0",
50
+ "unplugin-vue-components": "^32.1.0",
51
+ "vite": "npm:@voidzero-dev/vite-plus-core@0.2.6",
52
+ "vite-plugin-inspect": "^12.0.2",
53
+ "vite-plugin-svg-icons": "^2.0.1",
54
+ "vite-plus": "^0.2.6",
55
+ "vue-tsc": "^3.3.8"
56
+ },
57
+ "devEngines": {
58
+ "packageManager": {
59
+ "name": "pnpm",
60
+ "version": "11.11.0",
61
+ "onFail": "download"
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,2 @@
1
+ allowBuilds:
2
+ "@parcel/watcher": false
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
@@ -0,0 +1,7 @@
1
+ <script setup lang="ts"></script>
2
+
3
+ <template>
4
+ <RouterView />
5
+ </template>
6
+
7
+ <style scoped></style>
@@ -0,0 +1,12 @@
1
+ import request from "@/utils/request";
2
+
3
+ export const EXPIRE_TIME = 60 * 10 * 1000;
4
+
5
+ export function getTree() {
6
+ return request.Get("/xxx/xx", {
7
+ cacheFor: {
8
+ mode: "restore",
9
+ expire: EXPIRE_TIME,
10
+ },
11
+ });
12
+ }
@@ -0,0 +1,3 @@
1
+ <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M8.34912 1.55823C8.72361 1.23724 9.27639 1.23724 9.65088 1.55823L15.5981 6.65588C15.8493 6.87118 15.9784 7.1972 15.9419 7.526L15.0991 15.11C15.0429 15.6164 14.6145 15.9996 14.105 15.9996H3.89502C3.38553 15.9996 2.95714 15.6164 2.90088 15.11L2.05811 7.526C2.02157 7.1972 2.15067 6.87118 2.40186 6.65588L8.34912 1.55823ZM9.00049 9.99963C7.89603 9.99963 7.00066 10.8952 7.00049 11.9996V13.9996C7.00049 14.5519 7.4482 14.9996 8.00049 14.9996H10.0005C10.5526 14.9994 11.0005 14.5518 11.0005 13.9996V11.9996C11.0003 10.8953 10.1048 9.99985 9.00049 9.99963Z" fill="currentColor"/>
3
+ </svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="currentColor" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="currentColor" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
@@ -0,0 +1,29 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ icon: string;
4
+ }>();
5
+ const attrs = useAttrs();
6
+ </script>
7
+
8
+ <template>
9
+ <svg class="svg-icon" aria-hidden="true" v-bind="attrs">
10
+ <use :href="`#icon-${icon}`" />
11
+ </svg>
12
+ </template>
13
+
14
+ <style lang="scss" scoped>
15
+ .svg-icon {
16
+ display: flex;
17
+ justify-content: center;
18
+ align-items: center;
19
+ width: 1em;
20
+ height: 1em;
21
+ fill: currentColor;
22
+ overflow: hidden;
23
+ }
24
+
25
+ .svg-external-icon {
26
+ background-color: currentColor;
27
+ mask-size: cover !important;
28
+ }
29
+ </style>
@@ -0,0 +1,57 @@
1
+ import {
2
+ BarChart,
3
+ GraphChart,
4
+ LineChart,
5
+ MapChart,
6
+ PictorialBarChart,
7
+ PieChart,
8
+ RadarChart,
9
+ } from "echarts/charts";
10
+ import {
11
+ AriaComponent,
12
+ CalendarComponent,
13
+ DataZoomComponent,
14
+ GraphicComponent,
15
+ GridComponent,
16
+ LegendComponent,
17
+ ParallelComponent,
18
+ PolarComponent,
19
+ RadarComponent,
20
+ TimelineComponent,
21
+ TitleComponent,
22
+ ToolboxComponent,
23
+ TooltipComponent,
24
+ VisualMapComponent,
25
+ } from "echarts/components";
26
+ import * as echarts from "echarts/core";
27
+ // TODO 如果想换成SVG渲染,就导出SVGRenderer,
28
+ // 并且放到 echarts.use 里,注释掉 CanvasRenderer
29
+ import { /* SVGRenderer */ CanvasRenderer } from "echarts/renderers";
30
+
31
+ echarts.use([
32
+ LegendComponent,
33
+ TitleComponent,
34
+ TooltipComponent,
35
+ GridComponent,
36
+ PolarComponent,
37
+ AriaComponent,
38
+ ParallelComponent,
39
+ BarChart,
40
+ LineChart,
41
+ PieChart,
42
+ MapChart,
43
+ RadarChart,
44
+ GraphChart,
45
+ // TODO 因为要兼容Online图表自适应打印,所以改成 CanvasRenderer,可能会模糊
46
+ CanvasRenderer,
47
+ PictorialBarChart,
48
+ RadarComponent,
49
+ ToolboxComponent,
50
+ DataZoomComponent,
51
+ VisualMapComponent,
52
+ TimelineComponent,
53
+ CalendarComponent,
54
+ GraphicComponent,
55
+ ]);
56
+
57
+ export default echarts;
@@ -0,0 +1,65 @@
1
+ import type { EChartsOption } from "echarts";
2
+
3
+ import type { ShallowRef } from "vue";
4
+
5
+ import { debounce } from "radashi";
6
+
7
+ import echarts from "./lib";
8
+
9
+ type setOptionsType = (options: EChartsOption, clear?: boolean) => void;
10
+
11
+ export function useECharts(
12
+ elRef: Ref<HTMLDivElement> | Readonly<ShallowRef<HTMLDivElement | null>>,
13
+ ) {
14
+ let chartInstance: echarts.ECharts | null = null;
15
+ let resizeObserver: ResizeObserver | undefined;
16
+
17
+ const resize = () => {
18
+ chartInstance?.resize();
19
+ };
20
+
21
+ const initCharts = () => {
22
+ if (!elRef) return;
23
+ const el = unref(elRef);
24
+ if (!el) return;
25
+
26
+ resizeObserver = new ResizeObserver(
27
+ debounce(
28
+ {
29
+ delay: 100,
30
+ },
31
+ resize,
32
+ ),
33
+ );
34
+ resizeObserver.observe(el);
35
+
36
+ chartInstance = echarts.init(el);
37
+ };
38
+
39
+ const setOptions: setOptionsType = (options, clear = true) => {
40
+ if (!chartInstance) {
41
+ initCharts();
42
+ if (!chartInstance) return;
43
+ }
44
+ clear && chartInstance?.clear();
45
+ chartInstance?.setOption(options);
46
+ };
47
+
48
+ const getInstance: () => echarts.ECharts | null = () => {
49
+ if (!chartInstance) initCharts();
50
+ return chartInstance;
51
+ };
52
+
53
+ onUnmounted(() => {
54
+ chartInstance?.dispose();
55
+ resizeObserver?.disconnect();
56
+ resizeObserver = undefined;
57
+ });
58
+
59
+ return {
60
+ setOptions,
61
+ resize,
62
+ echarts,
63
+ getInstance,
64
+ };
65
+ }
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import { Avatar, Dropdown } from "antdv-next";
3
+ import { defineComponent, h } from "vue";
4
+
5
+ import { useUserStoreWithOut } from "@/store/modules/user";
6
+
7
+ const userStore = useUserStoreWithOut();
8
+ const router = useRouter();
9
+
10
+ function handleMenuClick({ key }: { key: string }) {
11
+ if (key === "logout") {
12
+ userStore.$reset();
13
+ router.push("/login");
14
+ }
15
+ }
16
+
17
+ const dropdownItems = [{ key: "logout", label: "退出登录" }];
18
+
19
+ const VdomUserDropdown = defineComponent({
20
+ name: "VdomUserDropdown",
21
+ setup() {
22
+ return () =>
23
+ h(
24
+ Dropdown,
25
+ {
26
+ trigger: ["click"],
27
+ menu: {
28
+ items: dropdownItems,
29
+ },
30
+ onMenuClick: handleMenuClick,
31
+ },
32
+ {
33
+ default: () =>
34
+ h("div", { class: "flex-center gap-2 cursor-pointer" }, [
35
+ h(
36
+ Avatar,
37
+ {
38
+ size: 32,
39
+ src: userStore.avatar,
40
+ },
41
+ {
42
+ default: () => userStore.name?.charAt(0).toUpperCase(),
43
+ },
44
+ ),
45
+ h("span", { class: "text-sm" }, userStore.name),
46
+ ]),
47
+ },
48
+ );
49
+ },
50
+ });
51
+ </script>
52
+
53
+ <template>
54
+ <div class="flex gap-3 items-center">
55
+ <VdomUserDropdown />
56
+ </div>
57
+ </template>