@agile-team/wl-skills-kit 2.11.0 → 2.11.2

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 (95) hide show
  1. package/CHANGELOG.md +47 -9
  2. package/README.md +41 -23
  3. package/bin/wl-skills.js +133 -39
  4. package/docs/agent-pipeline-runbook.md +3 -3
  5. package/docs//345/205/250/347/233/230/345/210/206/346/236/220/344/270/216/346/231/272/350/203/275/344/275/223/346/220/255/345/273/272/346/214/207/345/215/227.md +4 -4
  6. package/files/.wl-skills/copilot-instructions-full.md +233 -233
  7. package/files/.wl-skills/docs/jh-pagination.md +505 -505
  8. package/files/.wl-skills/docs/page-spec-schema.md +109 -0
  9. package/files/.wl-skills/docs/request.md +940 -940
  10. package/files/.wl-skills/guides/architecture.md +1 -1
  11. package/files/.wl-skills/skills/core/convention-audit/SKILL.md +3 -3
  12. package/files/.wl-skills/skills/core/page-codegen/SKILL.md +10 -4
  13. package/files/.wl-skills/skills/core/spec-doc-parse/SKILL.md +332 -332
  14. package/files/.wl-skills/skills/core/spec-doc-parse/USAGE.md +97 -97
  15. package/files/.wl-skills/skills/sync/permission-sync/USAGE.md +107 -107
  16. package/files/.wl-skills/src/components/global/C_ParentView/index.vue +3 -3
  17. package/files/.wl-skills/src/components/global/C_RightToolbar/index.vue +157 -157
  18. package/files/.wl-skills/src/components/global/C_SvgIcon/index.vue +31 -31
  19. package/files/.wl-skills/src/components/global/C_SvgIcon/svgicon.js +10 -10
  20. package/files/.wl-skills/src/components/global/C_TagStatus/README.md +264 -264
  21. package/files/.wl-skills/src/components/global/C_TagStatus/config.ts +192 -192
  22. package/files/.wl-skills/src/components/global/C_TagStatus/index.vue +106 -106
  23. package/files/.wl-skills/src/components/global/C_TagStatus/types.ts +64 -64
  24. package/files/.wl-skills/src/components/global/C_Tree/README.md +153 -153
  25. package/files/.wl-skills/src/components/global/C_Tree/index.scss +42 -42
  26. package/files/.wl-skills/src/components/global/C_Tree/index.vue +78 -78
  27. package/files/.wl-skills/src/components/global/C_Tree/types.ts +59 -59
  28. package/files/.wl-skills/src/components/local/c_formModal/README.md +235 -235
  29. package/files/.wl-skills/src/components/local/c_formModal/data.ts +95 -95
  30. package/files/.wl-skills/src/components/local/c_formModal/index.scss +8 -8
  31. package/files/.wl-skills/src/components/local/c_formModal/index.vue +107 -107
  32. package/files/.wl-skills/src/components/local/c_formSections/data.ts +175 -175
  33. package/files/.wl-skills/src/components/local/c_formSections/index.scss +280 -280
  34. package/files/.wl-skills/src/components/local/c_formSections/index.vue +429 -429
  35. package/files/.wl-skills/src/components/local/c_listModal/data.ts +41 -41
  36. package/files/.wl-skills/src/components/local/c_listModal/index.vue +136 -136
  37. package/files/.wl-skills/src/components/local/c_spliterTitle/index.scss +25 -25
  38. package/files/.wl-skills/src/components/local/c_spliterTitle/index.vue +21 -21
  39. package/files/.wl-skills/src/components/remote/AGGrid/README.md +530 -530
  40. package/files/.wl-skills/src/components/remote/BaseForm/README.md +508 -508
  41. package/files/.wl-skills/src/components/remote/BaseQuery/README.md +865 -865
  42. package/files/.wl-skills/src/components/remote/BaseTable/README.md +941 -941
  43. package/files/.wl-skills/src/components/remote/BaseToolbar/README.md +496 -496
  44. package/files/.wl-skills/src/types/page.ts +24 -24
  45. package/files/.wl-skills/standards/04-coding-basics.md +39 -1
  46. package/files/.wl-skills/standards/09-typescript.md +26 -3
  47. package/files/.wl-skills/standards/14-layout-containers.md +6 -6
  48. package/files/.wl-skills/standards/index.md +2 -2
  49. package/files/.wl-skills/templates/README.md +44 -44
  50. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/api.md +54 -54
  51. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/data.ts +346 -346
  52. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/index.scss +1 -1
  53. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add/index.vue +28 -28
  54. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add-form/data.ts +115 -115
  55. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add-form/index.scss +44 -44
  56. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-add-form/index.vue +43 -43
  57. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change/data.ts +338 -338
  58. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change/index.scss +1 -1
  59. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change/index.vue +28 -28
  60. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change-form/data.ts +115 -115
  61. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change-form/index.scss +44 -44
  62. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-apply-change-form/index.vue +43 -43
  63. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/api.md +88 -88
  64. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/data.ts +601 -601
  65. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/index.scss +1 -1
  66. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-archive/index.vue +64 -64
  67. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/api.md +67 -67
  68. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/data.ts +286 -286
  69. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/index.scss +139 -139
  70. package/files/.wl-skills/templates/produce/aiflow/mmwr-customer-detail/index.vue +318 -318
  71. package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/api.md +98 -98
  72. package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/data.ts +543 -543
  73. package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/index.scss +1 -1
  74. package/files/.wl-skills/templates/produce/aiflow/mmwr-temp-customer-archive/index.vue +52 -52
  75. package/files/.wl-skills/templates/sale/demo/add-demo/data.ts +518 -518
  76. package/files/.wl-skills/templates/sale/demo/billet-flame-cut-plan/data.ts +524 -524
  77. package/files/.wl-skills/templates/sale/demo/billet-flame-cut-plan/index.scss +154 -154
  78. package/files/.wl-skills/templates/sale/demo/billet-flame-cut-plan/index.vue +117 -117
  79. package/files/.wl-skills/templates/sale/demo/domestic-trade-order/data.ts +308 -308
  80. package/files/.wl-skills/templates/sale/demo/domestic-trade-order/index.scss +99 -99
  81. package/files/.wl-skills/templates/sale/demo/domestic-trade-order/index.vue +77 -77
  82. package/files/.wl-skills/templates/sale/demo/heat-batch-return/data.ts +367 -367
  83. package/files/.wl-skills/templates/sale/demo/heat-batch-return/index.scss +100 -100
  84. package/files/.wl-skills/templates/sale/demo/heat-batch-return/index.vue +170 -170
  85. package/files/.wl-skills/templates/sale/demo/heat-batch-return/meltDialog.vue +320 -320
  86. package/files/.wl-skills/templates/sale/demo/metallurgical-spec/data.ts +824 -824
  87. package/lib/ast-rules.js +304 -9
  88. package/lib/page-spec.js +588 -0
  89. package/lib/safe-fix.js +115 -0
  90. package/mcp/config.js +47 -47
  91. package/mcp/registry.js +6 -1
  92. package/mcp/tools/projectTools.js +19 -1
  93. package/package.json +16 -11
  94. package/files/.wl-skills/src/components/global/C_Splitter/index.scss +0 -61
  95. package/files/.wl-skills/src/components/global/C_Splitter/index.vue +0 -149
package/mcp/config.js CHANGED
@@ -1,47 +1,47 @@
1
- 'use strict'
2
-
3
- const fs = require('fs')
4
- const path = require('path')
5
-
6
- /**
7
- * 从项目的 .github/skills/sync/env.local.json 加载 MCP 运行配置
8
- * 项目根目录通过环境变量 WL_PROJECT_ROOT 传入(由 .cursor/mcp.json 注入)
9
- */
10
- function loadConfig() {
11
- const projectRoot = process.env.WL_PROJECT_ROOT
12
- ? path.resolve(process.env.WL_PROJECT_ROOT)
13
- : process.cwd()
14
-
15
- const configPath = path.join(projectRoot, '.github', 'skills', 'sync', 'env.local.json')
16
-
17
- if (!fs.existsSync(configPath)) {
18
- throw new Error(
19
- `配置文件不存在: ${configPath}\n` +
20
- `请先执行 npx @agile-team/wl-skills-kit init,然后填写 .github/skills/sync/env.local.json`
21
- )
22
- }
23
-
24
- let raw
25
- try {
26
- raw = JSON.parse(fs.readFileSync(configPath, 'utf8'))
27
- } catch (e) {
28
- throw new Error(`配置文件解析失败: ${e.message}`)
29
- }
30
-
31
- if (!raw.gatewayPath || raw.gatewayPath.includes('你的网关')) {
32
- throw new Error('请在 env.local.json 中填写真实的 gatewayPath(当前为占位值)')
33
- }
34
- if (!raw.token || raw.token.includes('Bearer Token')) {
35
- throw new Error('请在 env.local.json 中填写真实的 token(当前为占位值)')
36
- }
37
-
38
- return {
39
- gatewayPath: raw.gatewayPath.replace(/\/$/, ''), // 去掉尾部斜杠
40
- token: raw.token,
41
- sysAppNo: raw.sysAppNo || '',
42
- menu: raw.menu || {},
43
- dict: raw.dict || {},
44
- }
45
- }
46
-
47
- module.exports = { loadConfig }
1
+ 'use strict'
2
+
3
+ const fs = require('fs')
4
+ const path = require('path')
5
+
6
+ /**
7
+ * 从项目的 .wl-skills/skills/sync/env.local.json 加载 MCP 运行配置
8
+ * 项目根目录通过环境变量 WL_PROJECT_ROOT 传入(由 .cursor/mcp.json 注入)
9
+ */
10
+ function loadConfig() {
11
+ const projectRoot = process.env.WL_PROJECT_ROOT
12
+ ? path.resolve(process.env.WL_PROJECT_ROOT)
13
+ : process.cwd()
14
+
15
+ const configPath = path.join(projectRoot, '.wl-skills', 'skills', 'sync', 'env.local.json')
16
+
17
+ if (!fs.existsSync(configPath)) {
18
+ throw new Error(
19
+ `配置文件不存在: ${configPath}\n` +
20
+ `请先执行 pnpm dlx @agile-team/wl-skills-kit init,然后填写 .wl-skills/skills/sync/env.local.json`
21
+ )
22
+ }
23
+
24
+ let raw
25
+ try {
26
+ raw = JSON.parse(fs.readFileSync(configPath, 'utf8'))
27
+ } catch (e) {
28
+ throw new Error(`配置文件解析失败: ${e.message}`)
29
+ }
30
+
31
+ if (!raw.gatewayPath || raw.gatewayPath.includes('你的网关')) {
32
+ throw new Error('请在 env.local.json 中填写真实的 gatewayPath(当前为占位值)')
33
+ }
34
+ if (!raw.token || raw.token.includes('Bearer Token')) {
35
+ throw new Error('请在 env.local.json 中填写真实的 token(当前为占位值)')
36
+ }
37
+
38
+ return {
39
+ gatewayPath: raw.gatewayPath.replace(/\/$/, ''), // 去掉尾部斜杠
40
+ token: raw.token,
41
+ sysAppNo: raw.sysAppNo || '',
42
+ menu: raw.menu || {},
43
+ dict: raw.dict || {},
44
+ }
45
+ }
46
+
47
+ module.exports = { loadConfig }
package/mcp/registry.js CHANGED
@@ -296,11 +296,16 @@ const DESCRIPTORS = [
296
296
  {
297
297
  name: "wls_validate_page",
298
298
  description:
299
- "校验页面是否符合 wl-skills-kit 最新页面规范:BaseTable+AGGrid+cid、defineColumns、renderOps、mock-first、api.md 等。",
299
+ "校验页面是否符合 wl-skills-kit 最新页面规范:BaseTable+AGGrid+cid、defineColumns、renderOps、mock-first、api.md 等。开启 typecheck 额外执行 vue-tsc/tsc 类型检查(R14)。",
300
300
  inputSchema: {
301
301
  type: "object",
302
302
  properties: {
303
303
  path: { type: "string", description: "页面或目录路径,默认 src/views" },
304
+ typecheck: {
305
+ type: "boolean",
306
+ description:
307
+ "是否额外执行 vue-tsc/tsc --noEmit 类型检查(R14,体积较大,CI 场景开启)",
308
+ },
304
309
  },
305
310
  required: [],
306
311
  },
@@ -4,7 +4,8 @@ const fs = require("fs");
4
4
  const path = require("path");
5
5
  const { execFileSync } = require("child_process");
6
6
  const https = require("https");
7
- const { runAstRules } = require("../../lib/ast-rules");
7
+ const { runAstRules, runTypeCheck } = require("../../lib/ast-rules");
8
+ const { alignPage } = require("../../lib/page-spec");
8
9
 
9
10
  function getProjectRoot() {
10
11
  return process.env.WL_PROJECT_ROOT
@@ -203,6 +204,23 @@ async function handleValidatePage(args) {
203
204
  }
204
205
  }
205
206
 
207
+ // ── page-spec 比对(v2.11.1+,"约定 vs 代码"确定性核对 S1~S5)───────
208
+ for (const page of pages) {
209
+ const absDir = path.join(root, page.dir);
210
+ const { issues: specIssues } = alignPage(absDir, page.dir);
211
+ for (const iss of specIssues) {
212
+ issues.push([iss.dir, iss.level, `[${iss.rule}] ${iss.text}`]);
213
+ }
214
+ }
215
+
216
+ // ── 类型检查 R14(v2.11.2+,仅当 typecheck:true 触发)─────────────────
217
+ if (args && args.typecheck) {
218
+ const tc = runTypeCheck(root);
219
+ for (const iss of tc.issues) {
220
+ issues.push([iss.dir, iss.level, `[${iss.rule}] ${iss.text}`]);
221
+ }
222
+ }
223
+
206
224
  const errors = issues.filter((item) => item[1] === "error").length;
207
225
  const lines = [
208
226
  `✅ 页面校验完成:${scanPath}`,
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@agile-team/wl-skills-kit",
3
- "version": "2.11.0",
4
- "description": "AI Skill 模板包 v2.11.0 — 14 条编码规范 + 11 个 AI Skill + 17 个 MCP Tool,一条命令导入 Vue 3 项目(.wl-skills/ 统一隔离架构)",
3
+ "version": "2.11.2",
4
+ "description": "AI Skill 模板包 v2.11.2 — 14 条编码规范 + 11 个 AI Skill + 17 个 MCP Tool,一条命令导入 Vue 3 项目(.wl-skills/ 统一隔离架构)",
5
5
  "main": "./bin/wl-skills.js",
6
+ "packageManager": "pnpm@11.5.3",
6
7
  "bin": {
7
8
  "wl-skills": "bin/wl-skills.js"
8
9
  },
@@ -37,28 +38,29 @@
37
38
  "url": "git+https://github.com/ChenyCHENYU/wl-skills-kit.git"
38
39
  },
39
40
  "engines": {
40
- "node": ">=16.0.0"
41
+ "node": ">=18.0.0"
41
42
  },
42
43
  "scripts": {
43
- "standards:init": "npx @robot-admin/git-standards init",
44
+ "standards:init": "pnpm dlx @robot-admin/git-standards init",
44
45
  "prepare": "husky",
45
46
  "cz": "git-cz",
46
47
  "lint": "eslint .",
47
48
  "lint:skills": "node scripts/lint-skills.js",
48
49
  "test": "vitest run",
49
50
  "version:verify": "node scripts/verify-version.js",
51
+ "verify": "pnpm version:verify && pnpm lint:skills && pnpm test",
52
+ "ci": "pnpm install --frozen-lockfile && pnpm verify",
53
+ "pack:dry": "npm pack --dry-run --ignore-scripts",
54
+ "release:check": "pnpm verify && npm pack --dry-run --ignore-scripts",
50
55
  "prepublishOnly": "node scripts/verify-version.js && node scripts/lint-skills.js && vitest run"
51
56
  },
52
- "dependencies": {
53
- "xlsx": "^0.18.5"
54
- },
55
57
  "optionalDependencies": {
56
- "@vue/compiler-sfc": "^3.2.0",
57
- "@babel/parser": "^7.20.0"
58
+ "@babel/parser": "^7.20.0",
59
+ "@vue/compiler-sfc": "^3.2.0"
58
60
  },
59
61
  "peerDependencies": {
60
- "@vue/compiler-sfc": "^3.2.0",
61
- "@babel/parser": "^7.20.0"
62
+ "@babel/parser": "^7.20.0",
63
+ "@vue/compiler-sfc": "^3.2.0"
62
64
  },
63
65
  "peerDependenciesMeta": {
64
66
  "@vue/compiler-sfc": {
@@ -91,5 +93,8 @@
91
93
  "src/**/*.{js,jsx,ts,tsx,vue}": [
92
94
  "eslint --fix --no-cache"
93
95
  ]
96
+ },
97
+ "dependencies": {
98
+ "write-excel-file": "^4.1.1"
94
99
  }
95
100
  }
@@ -1,61 +0,0 @@
1
- .my-splitter-container {
2
- display: flex;
3
- width: 100%;
4
- height: 100%;
5
- overflow: hidden;
6
- }
7
-
8
- .is-horizontal {
9
- flex-direction: row;
10
- }
11
- .is-vertical {
12
- flex-direction: column;
13
- }
14
-
15
- .splitter-item {
16
- overflow: auto;
17
- }
18
-
19
- .splitter-trigger {
20
- background-color: #f0f2f5;
21
- display: flex;
22
- align-items: center;
23
- justify-content: center;
24
- transition: background-color 0.2s;
25
- z-index: 10;
26
- }
27
-
28
- .splitter-trigger:hover {
29
- background-color: #409eff;
30
- }
31
-
32
- /* 水平线 */
33
- .is-horizontal > .splitter-trigger {
34
- width: 4px;
35
- cursor: col-resize;
36
- }
37
- .is-horizontal .trigger-line {
38
- width: 1px;
39
- height: 20px;
40
- background: #dcdfe6;
41
- }
42
-
43
- /* 垂直线 */
44
- .is-vertical > .splitter-trigger {
45
- height: 8px;
46
- cursor: row-resize;
47
- background-color: #f5f5f5;
48
- flex-shrink: 0;
49
- display: flex;
50
- align-items: center;
51
- justify-content: center;
52
- }
53
- .is-vertical .trigger-line {
54
- width: 30px;
55
- height: 3px;
56
- background: #d9d9d9;
57
- border-radius: 2px;
58
- }
59
- .is-vertical > .splitter-trigger:hover .trigger-line {
60
- background: #409eff;
61
- }
@@ -1,149 +0,0 @@
1
- <template>
2
- <div
3
- ref="containerRef"
4
- class="my-splitter-container"
5
- :class="[`is-${direction}`]"
6
- >
7
- <template v-for="(item, index) in vnodes" :key="index">
8
- <div class="splitter-item" :style="getItemStyle(index)">
9
- <component :is="item" />
10
- </div>
11
-
12
- <div
13
- v-if="index < vnodes.length - 1"
14
- class="splitter-trigger"
15
- @mousedown="(e) => onMouseDown(e, index)"
16
- >
17
- <div class="trigger-line"></div>
18
- </div>
19
- </template>
20
- </div>
21
- </template>
22
-
23
- <script setup>
24
- import { ref, reactive, onMounted, useSlots, onUnmounted } from "vue";
25
-
26
- // ⚠️ [DEPRECATED] C_Splitter 已废弃,请改用:
27
- // 左右分割 → <jh-drag-col :leftWidth="260"> #left / #right </jh-drag-col>
28
- // 上下分栈 → <jh-drag-row :topHeight="200"> #top / #bottom </jh-drag-row>
29
- // 原因:C_Splitter 在 onMounted 中调用 slots.default() 冻结 vnode 快照,
30
- // 导致子树响应式绑定(v-if / v-show / 插值)与父组件 ref 完全解耦,
31
- // ref 赋值不触发重渲染。详见 .wl-skills/standards/14-layout-containers.md
32
- if (typeof window !== "undefined" && !window.__C_SPLITTER_WARNED__) {
33
- window.__C_SPLITTER_WARNED__ = true;
34
- // eslint-disable-next-line no-console
35
- console.warn(
36
- "[C_Splitter 已废弃] 已检测到 C_Splitter 使用。请改用 jh-drag-col / jh-drag-row。\n" +
37
- "原因:slots.default() 被冻结为 vnode 快照,导致子树响应式失效。\n" +
38
- "详见:.wl-skills/standards/14-layout-containers.md"
39
- );
40
- }
41
-
42
- const props = defineProps({
43
- direction: {
44
- type: String,
45
- default: "horizontal" // horizontal | vertical
46
- },
47
- minSize: {
48
- type: Number,
49
- default: 50
50
- }
51
- });
52
-
53
- const slots = useSlots();
54
- const containerRef = ref(null);
55
- const vnodes = ref([]); // 存储虚拟节点
56
- const paneConfigs = ref([]); // 存储每个面板的 minSize 等配置
57
- const sizes = reactive([]);
58
- const isDragging = ref(false);
59
- let currentTriggerIndex = -1;
60
-
61
- // 初始化:获取插槽并分配初始平均尺寸
62
- onMounted(() => {
63
- const defaultSlots = slots.default ? slots.default() : [];
64
- // 过滤掉注释节点(Symbol(v-cmt))和Fragment,只保留真正的元素
65
- const children = defaultSlots.filter((v) => {
66
- // 排除 Symbol 类型(注释节点)和 Fragment
67
- if (typeof v.type === "symbol") return false;
68
- // 保留 string(原生HTML元素)和 object(组件)
69
- return typeof v.type === "string" || typeof v.type === "object";
70
- });
71
- vnodes.value = children;
72
-
73
- const rect = containerRef.value.getBoundingClientRect();
74
- const totalAvailable =
75
- props.direction === "horizontal" ? rect.width : rect.height;
76
- // vertical 模式 trigger 高度是 8px,horizontal 模式宽度是 4px
77
- const triggerSize = props.direction === "horizontal" ? 4 : 8;
78
- const triggerTotalSize = (children.length - 1) * triggerSize;
79
-
80
- let remainingSize = totalAvailable - triggerTotalSize;
81
- let autoCount = 0;
82
-
83
- // 1. 第一次遍历:解析 initialSize (支持 200 或 "30%")
84
- const tempSizes = children.map((vnode) => {
85
- const initSize = vnode.props?.initialSize;
86
- if (initSize === undefined || initSize === null) {
87
- autoCount++;
88
- return null;
89
- }
90
- const sizePx =
91
- typeof initSize === "string" && initSize.endsWith("%")
92
- ? (parseFloat(initSize) / 100) * (totalAvailable - triggerTotalSize)
93
- : parseFloat(initSize);
94
- remainingSize -= sizePx;
95
- return sizePx;
96
- });
97
-
98
- // 2. 第二次遍历:填充 sizes 和 paneConfigs
99
- tempSizes.forEach((size, idx) => {
100
- sizes.push(size === null ? remainingSize / autoCount : size);
101
- paneConfigs.value.push({
102
- minSize: children[idx].props?.minSize || props.minSize
103
- });
104
- });
105
- });
106
-
107
- const getItemStyle = (index) => {
108
- const prop = props.direction === "horizontal" ? "width" : "height";
109
- return { [prop]: `${sizes[index]}px` };
110
- };
111
-
112
- // 拖拽逻辑
113
- const onMouseDown = (e, index) => {
114
- isDragging.value = true;
115
- currentTriggerIndex = index;
116
- document.body.style.userSelect = "none";
117
- document.body.style.cursor =
118
- props.direction === "horizontal" ? "col-resize" : "row-resize";
119
-
120
- window.addEventListener("mousemove", onMouseMove);
121
- window.addEventListener("mouseup", onMouseUp);
122
- };
123
-
124
- const onMouseMove = (e) => {
125
- if (!isDragging.value) return;
126
- const i = currentTriggerIndex;
127
- const movement = props.direction === "horizontal" ? e.movementX : e.movementY;
128
-
129
- const minCurr = paneConfigs.value[i].minSize;
130
- const minNext = paneConfigs.value[i + 1].minSize;
131
-
132
- if (sizes[i] + movement >= minCurr && sizes[i + 1] - movement >= minNext) {
133
- sizes[i] += movement;
134
- sizes[i + 1] -= movement;
135
- }
136
- };
137
-
138
- const onMouseUp = () => {
139
- isDragging.value = false;
140
- document.body.style.userSelect = "";
141
- document.body.style.cursor = "";
142
- window.removeEventListener("mousemove", onMouseMove);
143
- window.removeEventListener("mouseup", onMouseUp);
144
- };
145
-
146
- onUnmounted(() => onMouseUp())
147
- </script>
148
-
149
- <style scoped src="./index.scss"></style>