@manohub/skill-select-workbench 0.0.1-beta2 → 0.0.1-beta3

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.
package/README.md CHANGED
@@ -1,151 +1,153 @@
1
- # @manohub/skill-select-workbench
2
-
3
- 技能选择帮助(Vue 3 组件包):左侧业务域/技能分类导航树 + 右侧技能表格的双面板选择弹窗,底部已选回显,支持单选/跨页多选、关键字搜索、技能类型过滤。基于 `@farris/ui-vue` 表格与树组件,数据层内置(`@aihub/api-client` 已打包),开箱即用。
4
-
5
- ## 环境要求
6
-
7
- - Vue ^3.4
8
- - `@farris/ui-vue` ^1.8(运行时 peer 依赖,与宿主共享实例)
9
- - 运行环境需可达 AIHub 服务(请求前缀 `/api/runtime/aihub/v1.0`,由部署侧的网关/dev proxy 转发)
10
- - 宿主工程需具备 `@gsp-sys/utils`(宿主框架 SDK,承担平台 request 能力;ManoHarness 体系内的工程天然具备)
11
-
12
- ## 安装
13
-
14
- ```bash
15
- npm install @manohub/skill-select-workbench
16
- # 或
17
- pnpm add @manohub/skill-select-workbench
18
- ```
19
-
20
- ## 快速开始
21
-
22
- ```tsx
23
- import { ref } from 'vue'
24
- import { FButton } from '@farris/ui-vue'
25
- import {
26
- SkillSelectDialog,
27
- SKILL_CATEGORIES,
28
- } from '@manohub/skill-select-workbench'
29
- import type { SkillSelectConfirmPayload, SkillSelectItem } from '@manohub/skill-select-workbench'
30
- import '@manohub/skill-select-workbench/index.css'
31
-
32
- const open = ref(false)
33
- const picked = ref<SkillSelectItem[]>([])
34
-
35
- const handleConfirm = (payload: SkillSelectConfirmPayload) => {
36
- picked.value = payload.items
37
- }
38
- ```
39
-
40
- ```tsx
41
- <FButton type="primary" onClick={() => (open.value = true)}>选择技能</FButton>
42
-
43
- <SkillSelectDialog
44
- modelValue={open.value}
45
- onUpdate:modelValue={(v: boolean) => (open.value = v)}
46
- initSelected={picked.value}
47
- onConfirm={handleConfirm}
48
- />
49
- ```
50
-
51
- > 样式需手动引入一次:`import '@manohub/skill-select-workbench/index.css'`
52
-
53
- ## SkillSelectDialog
54
-
55
- ### Props
56
-
57
- | Prop | 类型 | 默认 | 说明 |
58
- |---|---|---|---|
59
- | `modelValue` | `boolean` | `false` | 弹窗开关(v-model) |
60
- | `singleSelect` | `boolean` | `false` | 单选:一次只能选定一个技能;`false` = 跨页多选 |
61
- | `initSelected` | `SkillSelectItem[]` | `[]` | 打开时回显的已选项 |
62
- | `initCategory` | `string` | `''` | 技能类型(使用类别)锁定,见下方语义 |
63
- | `title` | `string` | `'选择技能'` | 弹窗标题 |
64
-
65
- ### Emits
66
-
67
- | Emit | 载荷 | 触发 |
68
- |---|---|---|
69
- | `update:modelValue` | `boolean` | 关闭弹窗 |
70
- | `confirm` | `{ items: SkillSelectItem[] }` | 点「确定」 |
71
-
72
- ### initCategory 锁定语义
73
-
74
- - `''`(默认):**不锁定**。左侧为业务域树,表格含「技能类型」切换行(全部 / 通用办公技能 / 业务系统技能)。
75
- - `'GENERAL_OFFICE'`:**锁定通用办公类**。隐藏类型切换行,左侧切换为技能分类树(按 `topic` 过滤)。
76
- - `'BUSINESS_SYSTEM'`:**锁定业务系统类**。隐藏类型切换行,左侧为业务域树(按 `businessDomain` 过滤)。
77
-
78
- ### 交互行为
79
-
80
- - **点行切换选中**:点击表格行即选中/取消该技能(勾选框同样可用);单选模式下点已选行取消。
81
- - **跨页保留**:多选模式下翻页不清空勾选。
82
- - **已选回显**:底部操作区展示「已选 N 条」、已选项 chip(可单个删除或一键清空)。
83
- - **搜索**:按技能名称模糊搜索,350ms 防抖。
84
- - **分页**:10 / 20 / 50 每页可切。
85
-
86
- ## SkillSelectField
87
-
88
- 只读字段帮助形态:展示已选文本,点击唤起 SkillSelectDialog。
89
-
90
- ```tsx
91
- import { SkillSelectField } from '@manohub/skill-select-workbench'
92
-
93
- <SkillSelectField
94
- singleSelect
95
- selectedItems={items.value}
96
- onUpdate:selectedItems={(v: SkillSelectItem[]) => (items.value = v)}
97
- />
98
- ```
99
-
100
- | Prop | 类型 | 默认 | 说明 |
101
- |---|---|---|---|
102
- | `singleSelect` | `boolean` | `false` | 单选模式 |
103
- | `disabled` | `boolean` | `false` | 禁用 |
104
- | `placeholder` | `string` | `'请选择技能'` | 空态文案 |
105
- | `selectedItems` | `SkillSelectItem[]` | `[]` | 已选项(v-model) |
106
-
107
- Emits:`update:selectedItems`。
108
-
109
- ## 数据契约
110
-
111
- ```ts
112
- /** 已选技能条目 */
113
- interface SkillSelectItem {
114
- value: string // 技能 id,保存/回传
115
- text: string // 回显文本(displayName || name)
116
- skill?: SkillSummaryResponse // 完整技能快照,确认后可直接消费
117
- }
118
-
119
- interface SkillSelectConfirmPayload {
120
- items: SkillSelectItem[]
121
- }
122
-
123
- /** 由技能快照构造条目 */
124
- function toSkillSelectItem(skill: SkillSummaryResponse): SkillSelectItem
125
- ```
126
-
127
- 确认载荷携带完整技能快照,无需按 id 回查。
128
-
129
- ## 数据接口
130
-
131
- 组件数据经内置数据层请求以下接口(AIHub 服务):
132
-
133
- | 用途 | 接口 |
134
- |---|---|
135
- | 技能分页查询 | `GET /api/runtime/aihub/v1.0/listByAuth` |
136
- | 业务域树 | `GET /api/runtime/aihub/v1.0/business-domains/tree` |
137
- | 技能分类 | `GET /api/runtime/aihub/v1.0/topics` |
138
-
139
- 接入方需保证运行环境可访问上述接口(同域网关或 dev proxy 转发)。
140
-
141
- ## 本地开发
142
-
143
- ```bash
144
- pnpm install
145
- pnpm playground # 启动测试场 http://localhost:3012(/api 代理到 localhost:5300)
146
- pnpm build # 类型检查 + lib 构建(dist/index.js + dist/index.css + d.ts)
147
- ```
148
-
149
- ## License
150
-
151
- MIT
1
+ # @manohub/skill-select-workbench
2
+
3
+ 技能选择帮助(Vue 3 组件包):左侧业务域/技能分类导航树 + 右侧技能表格的双面板选择弹窗,底部已选回显,支持单选/跨页多选、关键字搜索、技能类型过滤。基于 `@farris/ui-vue` 表格与树组件,数据层内置(`@manohub/api-client` 已打包),开箱即用。
4
+
5
+ ## 环境要求
6
+
7
+ - Vue ^3.4
8
+ - `@farris/ui-vue` ^1.8(运行时 peer 依赖,与宿主共享实例)
9
+ - 运行环境需可达 AIHub 服务(请求前缀 `/api/runtime/aihub/v1.0`,由部署侧的网关/dev proxy 转发)
10
+ - 宿主工程需具备 `@gsp-sys/utils`(宿主框架 SDK,承担平台 request 能力;ManoHarness 体系内的工程天然具备)
11
+
12
+ ## 安装
13
+
14
+ ```bash
15
+ npm install @manohub/skill-select-workbench
16
+ # 或
17
+ pnpm add @manohub/skill-select-workbench
18
+ ```
19
+
20
+ ## 快速开始
21
+
22
+ ```tsx
23
+ import { ref } from 'vue'
24
+ import { FButton } from '@farris/ui-vue'
25
+ import {
26
+ SkillSelectDialog,
27
+ SKILL_CATEGORIES,
28
+ } from '@manohub/skill-select-workbench'
29
+ import type { SkillSelectConfirmPayload, SkillSelectItem } from '@manohub/skill-select-workbench'
30
+ import '@manohub/skill-select-workbench/index.css'
31
+
32
+ const open = ref(false)
33
+ const picked = ref<SkillSelectItem[]>([])
34
+
35
+ const handleConfirm = (payload: SkillSelectConfirmPayload) => {
36
+ picked.value = payload.items
37
+ }
38
+ ```
39
+
40
+ ```tsx
41
+ <FButton type="primary" onClick={() => (open.value = true)}>选择技能</FButton>
42
+
43
+ <SkillSelectDialog
44
+ modelValue={open.value}
45
+ onUpdate:modelValue={(v: boolean) => (open.value = v)}
46
+ initSelected={picked.value}
47
+ onConfirm={handleConfirm}
48
+ />
49
+ ```
50
+
51
+ > 样式需手动引入一次:`import '@manohub/skill-select-workbench/index.css'`
52
+
53
+ ## SkillSelectDialog
54
+
55
+ ### Props
56
+
57
+ | Prop | 类型 | 默认 | 说明 |
58
+ |---|---|---|---|
59
+ | `modelValue` | `boolean` | `false` | 弹窗开关(v-model) |
60
+ | `singleSelect` | `boolean` | `false` | 单选:一次只能选定一个技能;`false` = 跨页多选 |
61
+ | `initSelected` | `SkillSelectItem[]` | `[]` | 打开时回显的已选项 |
62
+ | `initCategory` | `string` | `''` | 技能类型(使用类别)锁定,见下方语义 |
63
+ | `orgId` | `string` | `''` | 组织维度过滤(非空走 `listAll`,仅返回该组织可见技能;全类型列、左侧固定业务域树、无类型切换行)。权限分配等场景用 |
64
+ | `title` | `string` | `'选择技能'` | 弹窗标题 |
65
+
66
+ ### Emits
67
+
68
+ | Emit | 载荷 | 触发 |
69
+ |---|---|---|
70
+ | `update:modelValue` | `boolean` | 关闭弹窗 |
71
+ | `confirm` | `{ items: SkillSelectItem[] }` | 点「确定」 |
72
+
73
+ ### initCategory 锁定语义
74
+
75
+ - `''`(默认):**不锁定**。左侧为业务域树,表格含「技能类型」切换行(全部 / 通用办公技能 / 业务系统技能)。
76
+ - `'GENERAL_OFFICE'`:**锁定通用办公类**。隐藏类型切换行,左侧切换为技能分类树(按 `topic` 过滤)。
77
+ - `'BUSINESS_SYSTEM'`:**锁定业务系统类**。隐藏类型切换行,左侧为业务域树(按 `businessDomain` 过滤)。
78
+
79
+ ### 交互行为
80
+
81
+ - **点行切换选中**:点击表格行即选中/取消该技能(勾选框同样可用);单选模式下点已选行取消。
82
+ - **跨页保留**:多选模式下翻页不清空勾选。
83
+ - **已选回显**:底部操作区展示「已选 N 条」、已选项 chip(可单个删除或一键清空)。
84
+ - **搜索**:按技能名称模糊搜索,350ms 防抖。
85
+ - **分页**:10 / 20 / 50 每页可切。
86
+
87
+ ## SkillSelectField
88
+
89
+ 只读字段帮助形态:展示已选文本,点击唤起 SkillSelectDialog。
90
+
91
+ ```tsx
92
+ import { SkillSelectField } from '@manohub/skill-select-workbench'
93
+
94
+ <SkillSelectField
95
+ singleSelect
96
+ selectedItems={items.value}
97
+ onUpdate:selectedItems={(v: SkillSelectItem[]) => (items.value = v)}
98
+ />
99
+ ```
100
+
101
+ | Prop | 类型 | 默认 | 说明 |
102
+ |---|---|---|---|
103
+ | `singleSelect` | `boolean` | `false` | 单选模式 |
104
+ | `asyncMode` | `boolean` | `true` | 兼容字段帮助的占位开关(本组件始终按需异步加载) |
105
+ | `disabled` | `boolean` | `false` | 禁用(不再唤起弹窗) |
106
+ | `placeholder` | `string` | `'请选择技能'` | 空态文案 |
107
+ | `selectedItems` | `SkillSelectItem[]` | `[]` | 已选项(v-model) |
108
+
109
+ Emits:`update:selectedItems`。
110
+
111
+ ## 数据契约
112
+
113
+ ```ts
114
+ /** 已选技能条目 */
115
+ interface SkillSelectItem {
116
+ value: string // 技能 id,保存/回传
117
+ text: string // 回显文本(displayName || name)
118
+ skill?: SkillSummaryResponse // 完整技能快照,确认后可直接消费
119
+ }
120
+
121
+ interface SkillSelectConfirmPayload {
122
+ items: SkillSelectItem[]
123
+ }
124
+
125
+ /** 由技能快照构造条目 */
126
+ function toSkillSelectItem(skill: SkillSummaryResponse): SkillSelectItem
127
+ ```
128
+
129
+ 确认载荷携带完整技能快照,无需按 id 回查。
130
+
131
+ ## 数据接口
132
+
133
+ 组件数据经内置数据层请求以下接口(AIHub 服务):
134
+
135
+ | 用途 | 接口 |
136
+ |---|---|
137
+ | 技能分页查询 | `GET /api/runtime/aihub/v1.0/listByAuth` |
138
+ | 业务域树 | `GET /api/runtime/aihub/v1.0/business-domains/tree` |
139
+ | 技能分类 | `GET /api/runtime/aihub/v1.0/topics` |
140
+
141
+ 接入方需保证运行环境可访问上述接口(同域网关或 dev proxy 转发)。
142
+
143
+ ## 本地开发
144
+
145
+ ```bash
146
+ pnpm install
147
+ pnpm playground # 启动测试场 http://localhost:3012(/api 代理到 localhost:5300)
148
+ pnpm build # 类型检查 + lib 构建(dist/index.js + dist/index.css + d.ts)
149
+ ```
150
+
151
+ ## License
152
+
153
+ MIT
@@ -1,4 +1,4 @@
1
- import type { PageResponse, SkillSummaryResponse } from '@aihub/api-client';
1
+ import type { PageResponse, SkillSummaryResponse } from '@manohub/api-client';
2
2
  import type { SkillDomainTreeNode } from '../types';
3
3
  /** "全部技能"虚拟树节点 ID(选中时不做业务域过滤) */
4
4
  export declare const ALL_SKILLS_NODE_ID = "__all_skills__";
@@ -24,6 +24,9 @@ export interface SkillPageFilter {
24
24
  topic?: string;
25
25
  /** 使用类别(技能类型)过滤:GENERAL_OFFICE / BUSINESS_SYSTEM,缺省查全部 */
26
26
  category?: string;
27
+ /** 组织维度过滤(打开组件时由调用方传入):非空时走 listAll 接口,仅返回该组织可见技能;
28
+ * 服务端该路径不支持 topic/category 过滤(返回通用办公与业务系统两类可见技能),二者会被忽略 */
29
+ orgId?: string;
27
30
  }
28
31
  /**
29
32
  * 技能分页查询(按新契约:分页从 0 开始,返回 { items, total, page, size })
@@ -23,6 +23,12 @@ export declare const SkillSelectDialog: import("vue").DefineComponent<import("vu
23
23
  type: StringConstructor;
24
24
  default: string;
25
25
  };
26
+ /** 组织维度过滤(必传则按 orgid 过滤,权限分配等场景):非空时走 listAll 接口,仅返回该组织可见技能;
27
+ * 该模式下列表为全类型(服务端忽略使用类别/技能分类过滤),左侧导航固定为业务域树、隐藏技能类型切换行 */
28
+ orgId: {
29
+ type: StringConstructor;
30
+ default: string;
31
+ };
26
32
  title: {
27
33
  type: StringConstructor;
28
34
  default: string;
@@ -47,6 +53,12 @@ export declare const SkillSelectDialog: import("vue").DefineComponent<import("vu
47
53
  type: StringConstructor;
48
54
  default: string;
49
55
  };
56
+ /** 组织维度过滤(必传则按 orgid 过滤,权限分配等场景):非空时走 listAll 接口,仅返回该组织可见技能;
57
+ * 该模式下列表为全类型(服务端忽略使用类别/技能分类过滤),左侧导航固定为业务域树、隐藏技能类型切换行 */
58
+ orgId: {
59
+ type: StringConstructor;
60
+ default: string;
61
+ };
50
62
  title: {
51
63
  type: StringConstructor;
52
64
  default: string;
@@ -55,6 +67,7 @@ export declare const SkillSelectDialog: import("vue").DefineComponent<import("vu
55
67
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
56
68
  onConfirm?: ((...args: any[]) => any) | undefined;
57
69
  }>, {
70
+ orgId: string;
58
71
  modelValue: boolean;
59
72
  singleSelect: boolean;
60
73
  initSelected: SkillSelectItem[];
@@ -1,4 +1,4 @@
1
- import type { SkillSummaryResponse } from '@aihub/api-client';
1
+ import type { SkillSummaryResponse } from '@manohub/api-client';
2
2
  import type { SkillSelectItem } from '../types';
3
3
  export interface UseSkillSelectionOptions {
4
4
  /** 单选模式:任一时刻最多保留一个选中项 */
@@ -6,9 +6,11 @@ export interface UseSkillSelectionOptions {
6
6
  }
7
7
  /**
8
8
  * 技能选中集管理(仿 personnel 帮助的 useSelectionState):
9
- * - FDataGrid 勾选通过 selectionValues(受控)+ onSelectionUpdate 全量同步
9
+ * - FDataGrid 勾选通过 selectionValues(受控)同步
10
10
  * - 跨页保持:grid 侧 keepSelectingOnPaging,本 composable 维护全量 Map
11
11
  * - 详情补齐:indexPageItems 登记当前页技能,勾选上报的 id 据此补全快照
12
+ * - 多选对账:farris 逐行点击只上报「本次变化行」的增量 id(勾选/取消同形),
13
+ * 无法全量重建;以行对象上的 __fv_checked__ 标志为准对账(reconcilePageFromFlags)
12
14
  */
13
15
  export declare function useSkillSelection(options?: UseSkillSelectionOptions): {
14
16
  singleSelect: boolean;
@@ -17,6 +19,7 @@ export declare function useSkillSelection(options?: UseSkillSelectionOptions): {
17
19
  count: import("vue").ComputedRef<number>;
18
20
  indexPageItems: (items: SkillSummaryResponse[] | null | undefined) => void;
19
21
  handleGridSelectionUpdate: (rows: unknown[] | undefined, ids?: string[], currentPageIds?: Set<string>) => void;
22
+ reconcilePageFromFlags: (pageRows: unknown[] | null | undefined) => void;
20
23
  toggleItem: (row: unknown) => void;
21
24
  selectRow: (row: unknown) => void;
22
25
  removeItem: (id: string) => void;
package/dist/index.css CHANGED
@@ -1,2 +1 @@
1
- .ssw-overlay{z-index:10000;background:#0f172a73;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.ssw-dialog{color:#232428;background:#fff;border-radius:8px;flex-direction:column;width:960px;max-width:calc(100vw - 48px);height:640px;max-height:calc(100vh - 64px);font-size:13px;display:flex;overflow:hidden;box-shadow:0 12px 40px #0f172a47}.ssw-dialog__header{background:#fff;border-bottom:1px solid #ebeef5;flex-shrink:0;justify-content:space-between;align-items:center;height:44px;padding:0 16px;display:flex}.ssw-dialog__title{font-size:15px;font-weight:600}.ssw-dialog__close{cursor:pointer;background:0 0;border:0;border-radius:4px;justify-content:center;align-items:center;width:28px;height:28px;display:inline-flex}.ssw-dialog__close:hover{background:#f2f3f5}.ssw-icon-close{color:#6b7280;font-size:18px;line-height:1}.ssw-dialog__body{flex:1;min-height:0;display:flex}.ssw-pane{flex-direction:column;min-height:0;display:flex}.ssw-pane--tree{background:#fafbfc;border-right:1px solid #ebeef5;flex-shrink:0;width:240px}.ssw-pane__head{flex-shrink:0;align-items:baseline;gap:8px;padding:10px 14px 8px;font-size:13px;font-weight:600;display:flex}.ssw-tree-wrap{flex:1;min-height:0;padding:0 8px 8px;overflow:hidden}.ssw-tree-empty{text-align:center;color:#a0a4ab;padding:24px 8px;font-size:12px}.ssw-pane--grid{flex:1;min-width:0;padding:10px 16px 8px}.ssw-toolbar{flex-shrink:0;justify-content:flex-end;align-items:center;gap:12px;padding-bottom:10px;display:flex}.ssw-footer-count{color:#4b5563;white-space:nowrap;margin-right:8px;font-size:12px}.ssw-clear-all{color:#2660ff;cursor:pointer;margin-left:8px;text-decoration:none}.ssw-clear-all:hover{opacity:.8}.ssw-search{align-items:center;width:260px;display:flex;position:relative}.ssw-search__input{color:#232428;background:#fff;border:1px solid #d7dbe0;border-radius:4px;outline:none;width:100%;height:30px;padding:0 28px 0 10px;font-size:13px}.ssw-search__input:focus{border-color:#2660ff;box-shadow:0 0 0 2px #2660ff1f}.ssw-search__clear{color:#9ca3af;cursor:pointer;background:0 0;border:0;padding:2px;font-size:14px;line-height:1;position:absolute;right:6px}.ssw-search__clear:hover{color:#4b5563}.ssw-filter{flex-shrink:0;align-items:center;gap:6px;padding-bottom:10px;display:flex}.ssw-filter__label{color:#6b7280;flex-shrink:0;font-size:12px}.ssw-filter__btn{color:#4b5563;cursor:pointer;background:#fff;border:1px solid #d7dbe0;border-radius:4px;height:26px;padding:0 10px;font-size:12px;transition:border-color .15s,color .15s}.ssw-filter__btn:hover:not(.ssw-filter__btn--active){color:#2660ff;border-color:#2660ff}.ssw-filter__btn--active{color:#fff;background:#2660ff;border-color:#2660ff}.ssw-grid-wrap{background:#fff;border:1px solid #ebeef5;border-radius:4px;flex:1;min-height:0;position:relative;overflow:hidden}.ssw-grid-loading,.ssw-grid-empty{color:#6b7280;z-index:5;pointer-events:none;background:#ffffffbf;justify-content:center;align-items:center;font-size:13px;display:flex;position:absolute;inset:0}.ssw-grid-empty{background:#fff}.ssw-pagination{flex-shrink:0;justify-content:flex-end;padding-top:8px;display:flex}.ssw-dialog__footer{background:#fafbfc;border-top:1px solid #ebeef5;flex-shrink:0;align-items:center;gap:16px;min-height:56px;padding:10px 16px;display:flex}.ssw-footer-selection{flex:1;align-items:center;gap:6px;min-width:0;display:flex;overflow-x:auto}.ssw-footer-placeholder{color:#a0a4ab;font-size:12px}.ssw-chip{color:#2660ff;background:#eef3ff;border-radius:12px;flex-shrink:0;align-items:center;gap:4px;max-width:220px;padding:2px 6px 2px 10px;font-size:12px;display:inline-flex}.ssw-chip__text{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.ssw-chip__remove{color:#2660ff;cursor:pointer;padding:0 2px;font-size:14px;line-height:1}.ssw-chip__remove:hover{color:#1d4ed8}.ssw-footer-actions{flex-shrink:0;align-items:center;gap:8px;display:flex}.ssw-field{color:#6b7280;cursor:pointer;box-sizing:border-box;background:#f5f6fa;border:1px solid #d7dbe0;border-radius:4px;justify-content:space-between;align-items:center;gap:8px;width:100%;min-width:200px;height:32px;padding:0 8px 0 12px;transition:border-color .2s;display:inline-flex}.ssw-field:hover:not(.ssw-field--disabled){border-color:#2660ff}.ssw-field--disabled{cursor:not-allowed;opacity:.7}.ssw-field__placeholder{color:#a0a4ab;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.ssw-field__value{text-overflow:ellipsis;white-space:nowrap;color:#232428;flex:1;min-width:0;overflow:hidden}.ssw-field__actions{flex-shrink:0;align-items:center;gap:6px;display:inline-flex}.ssw-field__clear,.ssw-field__open{color:#9ca3af;justify-content:center;align-items:center;padding:2px;font-size:14px;line-height:1;display:inline-flex}.ssw-field__clear:hover,.ssw-field__open:hover{color:#4b5563}.ssw-field__open{color:#2660ff;font-weight:700}
2
- /*$vite$:1*/
1
+ .ssw-overlay{position:fixed;inset:0;z-index:10000;display:flex;align-items:center;justify-content:center;background:#0f172a73}.ssw-dialog{display:flex;flex-direction:column;width:960px;max-width:calc(100vw - 48px);height:640px;max-height:calc(100vh - 64px);background:#fff;border-radius:8px;box-shadow:0 12px 40px #0f172a47;overflow:hidden;font-size:13px;color:#232428}.ssw-dialog__header{display:flex;align-items:center;justify-content:space-between;height:44px;padding:0 16px;border-bottom:1px solid #ebeef5;background:#fff;flex-shrink:0}.ssw-dialog__title{font-size:15px;font-weight:600}.ssw-dialog__close{border:0;background:transparent;width:28px;height:28px;border-radius:4px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.ssw-dialog__close:hover{background:#f2f3f5}.ssw-icon-close{font-size:18px;line-height:1;color:#6b7280}.ssw-dialog__body{display:flex;flex:1;min-height:0}.ssw-pane{display:flex;flex-direction:column;min-height:0}.ssw-pane--tree{width:240px;flex-shrink:0;border-right:1px solid #ebeef5;background:#fafbfc}.ssw-pane__head{display:flex;align-items:baseline;gap:8px;padding:10px 14px 8px;font-weight:600;font-size:13px;flex-shrink:0}.ssw-tree-wrap{flex:1;min-height:0;padding:0 8px 8px;overflow:hidden}.ssw-tree-empty{padding:24px 8px;text-align:center;color:#a0a4ab;font-size:12px}.ssw-pane--grid{flex:1;min-width:0;padding:10px 16px 8px}.ssw-toolbar{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding-bottom:10px;flex-shrink:0}.ssw-footer-count{color:#4b5563;font-size:12px;margin-right:8px;white-space:nowrap}.ssw-clear-all{margin-left:8px;color:#2660ff;cursor:pointer;text-decoration:none}.ssw-clear-all:hover{opacity:.8}.ssw-search{position:relative;display:flex;align-items:center;width:260px}.ssw-search__input{width:100%;height:30px;padding:0 28px 0 10px;border:1px solid #d7dbe0;border-radius:4px;font-size:13px;outline:none;background:#fff;color:#232428}.ssw-search__input:focus{border-color:#2660ff;box-shadow:0 0 0 2px #2660ff1f}.ssw-search__clear{position:absolute;right:6px;border:0;background:transparent;color:#9ca3af;cursor:pointer;font-size:14px;line-height:1;padding:2px}.ssw-search__clear:hover{color:#4b5563}.ssw-filter{display:flex;align-items:center;gap:6px;padding-bottom:10px;flex-shrink:0}.ssw-filter__label{flex-shrink:0;font-size:12px;color:#6b7280}.ssw-filter__btn{height:26px;padding:0 10px;border:1px solid #d7dbe0;border-radius:4px;background:#fff;font-size:12px;color:#4b5563;cursor:pointer;transition:border-color .15s,color .15s}.ssw-filter__btn:hover:not(.ssw-filter__btn--active){border-color:#2660ff;color:#2660ff}.ssw-filter__btn--active{border-color:#2660ff;background:#2660ff;color:#fff}.ssw-grid-wrap{position:relative;flex:1;min-height:0;border:1px solid #ebeef5;border-radius:4px;overflow:hidden;background:#fff}.ssw-grid-loading,.ssw-grid-empty{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffbf;color:#6b7280;font-size:13px;z-index:5;pointer-events:none}.ssw-grid-empty{background:#fff}.ssw-pagination{display:flex;justify-content:flex-end;padding-top:8px;flex-shrink:0}.ssw-dialog__footer{display:flex;align-items:center;gap:16px;min-height:56px;padding:10px 16px;border-top:1px solid #ebeef5;background:#fafbfc;flex-shrink:0}.ssw-footer-selection{flex:1;min-width:0;display:flex;align-items:center;gap:6px;overflow-x:auto}.ssw-footer-placeholder{color:#a0a4ab;font-size:12px}.ssw-chip{display:inline-flex;align-items:center;gap:4px;max-width:220px;padding:2px 6px 2px 10px;background:#eef3ff;border-radius:12px;font-size:12px;color:#2660ff;flex-shrink:0}.ssw-chip__text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ssw-chip__remove{color:#2660ff;cursor:pointer;font-size:14px;line-height:1;padding:0 2px}.ssw-chip__remove:hover{color:#1d4ed8}.ssw-footer-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}.ssw-field{display:inline-flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-width:200px;height:32px;padding:0 8px 0 12px;border:1px solid #d7dbe0;border-radius:4px;background:#f5f6fa;color:#6b7280;cursor:pointer;box-sizing:border-box;transition:border-color .2s}.ssw-field:hover:not(.ssw-field--disabled){border-color:#2660ff}.ssw-field--disabled{cursor:not-allowed;opacity:.7}.ssw-field__placeholder{color:#a0a4ab;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ssw-field__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#232428}.ssw-field__actions{display:inline-flex;align-items:center;gap:6px;flex-shrink:0}.ssw-field__clear,.ssw-field__open{display:inline-flex;align-items:center;justify-content:center;color:#9ca3af;font-size:14px;line-height:1;padding:2px}.ssw-field__clear:hover,.ssw-field__open:hover{color:#4b5563}.ssw-field__open{color:#2660ff;font-weight:700}