@manohub/skill-select-workbench 0.0.1-beta1
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/dist/api/skill-select-data.d.ts +32 -0
- package/dist/components/skill-select-dialog.d.ts +63 -0
- package/dist/components/skill-select-field.d.ts +65 -0
- package/dist/composables/use-skill-selection.d.ts +26 -0
- package/dist/constants.d.ts +17 -0
- package/dist/index.css +2 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +763 -0
- package/dist/types.d.ts +31 -0
- package/package.json +41 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { PageResponse, SkillSummaryResponse } from '@aihub/api-client';
|
|
2
|
+
import type { SkillDomainTreeNode } from '../types';
|
|
3
|
+
/** "全部技能"虚拟树节点 ID(选中时不做业务域过滤) */
|
|
4
|
+
export declare const ALL_SKILLS_NODE_ID = "__all_skills__";
|
|
5
|
+
/** 业务域树(含"全部技能"虚拟根,直接作为 FTreeView 的 data) */
|
|
6
|
+
export declare function loadDomainTreeWithRoot(): Promise<SkillDomainTreeNode[]>;
|
|
7
|
+
/** 业务域树(真实接口返回,缓存在模块级) */
|
|
8
|
+
export declare function loadDomainTree(): Promise<SkillDomainTreeNode[]>;
|
|
9
|
+
/** 扁平化业务域树,code → name 映射(表格"业务域"列展示用) */
|
|
10
|
+
export declare function flattenDomainCodeName(nodes: SkillDomainTreeNode[]): Map<string, string>;
|
|
11
|
+
/** topic → 名称 映射(模块级缓存):技能的 topic 字段可能存 id 或 code,两种 key 都登记 */
|
|
12
|
+
export declare function loadTopicNameMap(): Promise<Map<string, string>>;
|
|
13
|
+
/** 技能分类导航节点(扁平):每个 topic 一个节点,code 为空者跳过(无法作为过滤参数) */
|
|
14
|
+
export declare function loadTopicNavNodes(): Promise<SkillDomainTreeNode[]>;
|
|
15
|
+
/** 技能分类导航树(含"全部技能"虚拟根,供通用办公类技能左侧导航) */
|
|
16
|
+
export declare function loadTopicTreeWithRoot(): Promise<SkillDomainTreeNode[]>;
|
|
17
|
+
/** 技能查询参数(封装 listSkills 的过滤子集) */
|
|
18
|
+
export interface SkillPageFilter {
|
|
19
|
+
page?: number;
|
|
20
|
+
size?: number;
|
|
21
|
+
keyword?: string;
|
|
22
|
+
businessDomain?: string;
|
|
23
|
+
/** 技能分类(topic code)过滤 */
|
|
24
|
+
topic?: string;
|
|
25
|
+
/** 使用类别(技能类型)过滤:GENERAL_OFFICE / BUSINESS_SYSTEM,缺省查全部 */
|
|
26
|
+
category?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 技能分页查询(按新契约:分页从 0 开始,返回 { items, total, page, size })
|
|
30
|
+
* @param signal 供调用方取消请求
|
|
31
|
+
*/
|
|
32
|
+
export declare function querySkillPage(filter: SkillPageFilter, signal?: AbortSignal): Promise<PageResponse<SkillSummaryResponse>>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type PropType } from 'vue';
|
|
2
|
+
import type { SkillSelectItem } from '../types';
|
|
3
|
+
/** 使用类别常量(与后端 SkillCategory 枚举一致) */
|
|
4
|
+
export declare const SKILL_CATEGORY_GENERAL = "GENERAL_OFFICE";
|
|
5
|
+
export declare const SKILL_CATEGORY_BIZ = "BUSINESS_SYSTEM";
|
|
6
|
+
export declare const SkillSelectDialog: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
7
|
+
modelValue: {
|
|
8
|
+
type: BooleanConstructor;
|
|
9
|
+
default: boolean;
|
|
10
|
+
};
|
|
11
|
+
/** 单选模式:一次只能选定一个技能 */
|
|
12
|
+
singleSelect: {
|
|
13
|
+
type: BooleanConstructor;
|
|
14
|
+
default: boolean;
|
|
15
|
+
};
|
|
16
|
+
/** 打开弹窗时的初始已选项(回显) */
|
|
17
|
+
initSelected: {
|
|
18
|
+
type: PropType<SkillSelectItem[]>;
|
|
19
|
+
default: () => SkillSelectItem[];
|
|
20
|
+
};
|
|
21
|
+
/** 调用方指定的技能类型(使用类别):GENERAL_OFFICE / BUSINESS_SYSTEM。非空=锁定该类型,隐藏类型切换行,仅加载该类型数据;'' = 不锁定(弹窗内可选全部) */
|
|
22
|
+
initCategory: {
|
|
23
|
+
type: StringConstructor;
|
|
24
|
+
default: string;
|
|
25
|
+
};
|
|
26
|
+
title: {
|
|
27
|
+
type: StringConstructor;
|
|
28
|
+
default: string;
|
|
29
|
+
};
|
|
30
|
+
}>, () => JSX.Element | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:modelValue" | "confirm")[], "update:modelValue" | "confirm", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
31
|
+
modelValue: {
|
|
32
|
+
type: BooleanConstructor;
|
|
33
|
+
default: boolean;
|
|
34
|
+
};
|
|
35
|
+
/** 单选模式:一次只能选定一个技能 */
|
|
36
|
+
singleSelect: {
|
|
37
|
+
type: BooleanConstructor;
|
|
38
|
+
default: boolean;
|
|
39
|
+
};
|
|
40
|
+
/** 打开弹窗时的初始已选项(回显) */
|
|
41
|
+
initSelected: {
|
|
42
|
+
type: PropType<SkillSelectItem[]>;
|
|
43
|
+
default: () => SkillSelectItem[];
|
|
44
|
+
};
|
|
45
|
+
/** 调用方指定的技能类型(使用类别):GENERAL_OFFICE / BUSINESS_SYSTEM。非空=锁定该类型,隐藏类型切换行,仅加载该类型数据;'' = 不锁定(弹窗内可选全部) */
|
|
46
|
+
initCategory: {
|
|
47
|
+
type: StringConstructor;
|
|
48
|
+
default: string;
|
|
49
|
+
};
|
|
50
|
+
title: {
|
|
51
|
+
type: StringConstructor;
|
|
52
|
+
default: string;
|
|
53
|
+
};
|
|
54
|
+
}>> & Readonly<{
|
|
55
|
+
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
56
|
+
onConfirm?: ((...args: any[]) => any) | undefined;
|
|
57
|
+
}>, {
|
|
58
|
+
modelValue: boolean;
|
|
59
|
+
singleSelect: boolean;
|
|
60
|
+
initSelected: SkillSelectItem[];
|
|
61
|
+
initCategory: string;
|
|
62
|
+
title: string;
|
|
63
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type PropType } from 'vue';
|
|
2
|
+
import type { SkillSelectItem } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* 技能选择字段帮助(对标 personnel-workbench 的 TreeSelectField 用法):
|
|
5
|
+
* 只读展示已选技能,点击唤起 SkillSelectDialog。
|
|
6
|
+
* 用法:
|
|
7
|
+
* <SkillSelectField :selectedItems="items" singleSelect @update:selectedItems="v => (items = v)" />
|
|
8
|
+
*/
|
|
9
|
+
export declare const SkillSelectField: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
10
|
+
/** 单选模式 */
|
|
11
|
+
singleSelect: {
|
|
12
|
+
type: BooleanConstructor;
|
|
13
|
+
default: boolean;
|
|
14
|
+
};
|
|
15
|
+
/** 兼容字段帮助的 asyncMode 开关(本组件始终按需异步加载,保留以对齐既有调用方) */
|
|
16
|
+
asyncMode: {
|
|
17
|
+
type: BooleanConstructor;
|
|
18
|
+
default: boolean;
|
|
19
|
+
};
|
|
20
|
+
disabled: {
|
|
21
|
+
type: BooleanConstructor;
|
|
22
|
+
default: boolean;
|
|
23
|
+
};
|
|
24
|
+
placeholder: {
|
|
25
|
+
type: StringConstructor;
|
|
26
|
+
default: string;
|
|
27
|
+
};
|
|
28
|
+
/** 当前已选技能(v-model) */
|
|
29
|
+
selectedItems: {
|
|
30
|
+
type: PropType<SkillSelectItem[]>;
|
|
31
|
+
default: () => SkillSelectItem[];
|
|
32
|
+
};
|
|
33
|
+
}>, () => JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "update:selectedItems"[], "update:selectedItems", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
34
|
+
/** 单选模式 */
|
|
35
|
+
singleSelect: {
|
|
36
|
+
type: BooleanConstructor;
|
|
37
|
+
default: boolean;
|
|
38
|
+
};
|
|
39
|
+
/** 兼容字段帮助的 asyncMode 开关(本组件始终按需异步加载,保留以对齐既有调用方) */
|
|
40
|
+
asyncMode: {
|
|
41
|
+
type: BooleanConstructor;
|
|
42
|
+
default: boolean;
|
|
43
|
+
};
|
|
44
|
+
disabled: {
|
|
45
|
+
type: BooleanConstructor;
|
|
46
|
+
default: boolean;
|
|
47
|
+
};
|
|
48
|
+
placeholder: {
|
|
49
|
+
type: StringConstructor;
|
|
50
|
+
default: string;
|
|
51
|
+
};
|
|
52
|
+
/** 当前已选技能(v-model) */
|
|
53
|
+
selectedItems: {
|
|
54
|
+
type: PropType<SkillSelectItem[]>;
|
|
55
|
+
default: () => SkillSelectItem[];
|
|
56
|
+
};
|
|
57
|
+
}>> & Readonly<{
|
|
58
|
+
"onUpdate:selectedItems"?: ((...args: any[]) => any) | undefined;
|
|
59
|
+
}>, {
|
|
60
|
+
singleSelect: boolean;
|
|
61
|
+
disabled: boolean;
|
|
62
|
+
asyncMode: boolean;
|
|
63
|
+
placeholder: string;
|
|
64
|
+
selectedItems: SkillSelectItem[];
|
|
65
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SkillSummaryResponse } from '@aihub/api-client';
|
|
2
|
+
import type { SkillSelectItem } from '../types';
|
|
3
|
+
export interface UseSkillSelectionOptions {
|
|
4
|
+
/** 单选模式:任一时刻最多保留一个选中项 */
|
|
5
|
+
singleSelect?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* 技能选中集管理(仿 personnel 帮助的 useSelectionState):
|
|
9
|
+
* - FDataGrid 勾选通过 selectionValues(受控)+ onSelectionUpdate 全量同步
|
|
10
|
+
* - 跨页保持:grid 侧 keepSelectingOnPaging,本 composable 维护全量 Map
|
|
11
|
+
* - 详情补齐:indexPageItems 登记当前页技能,勾选上报的 id 据此补全快照
|
|
12
|
+
*/
|
|
13
|
+
export declare function useSkillSelection(options?: UseSkillSelectionOptions): {
|
|
14
|
+
singleSelect: boolean;
|
|
15
|
+
selectedIds: import("vue").ComputedRef<string[]>;
|
|
16
|
+
items: import("vue").ComputedRef<SkillSelectItem[]>;
|
|
17
|
+
count: import("vue").ComputedRef<number>;
|
|
18
|
+
indexPageItems: (items: SkillSummaryResponse[] | null | undefined) => void;
|
|
19
|
+
handleGridSelectionUpdate: (rows: unknown[] | undefined, ids?: string[], currentPageIds?: Set<string>) => void;
|
|
20
|
+
toggleItem: (row: unknown) => void;
|
|
21
|
+
selectRow: (row: unknown) => void;
|
|
22
|
+
removeItem: (id: string) => void;
|
|
23
|
+
clear: () => void;
|
|
24
|
+
restore: (items: SkillSelectItem[] | null | undefined) => void;
|
|
25
|
+
};
|
|
26
|
+
export type SkillSelectionStore = ReturnType<typeof useSkillSelection>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** 技能使用类别(对应 api-client SkillCategory 枚举,与 aihub-skill 共享常量保持一致) */
|
|
2
|
+
export declare const SKILL_CATEGORIES: readonly [{
|
|
3
|
+
readonly value: "GENERAL_OFFICE";
|
|
4
|
+
readonly label: "通用办公技能";
|
|
5
|
+
}, {
|
|
6
|
+
readonly value: "BUSINESS_SYSTEM";
|
|
7
|
+
readonly label: "业务系统技能";
|
|
8
|
+
}];
|
|
9
|
+
export type SkillCategoryValue = (typeof SKILL_CATEGORIES)[number]['value'];
|
|
10
|
+
/** 默认使用类别:通用办公技能 */
|
|
11
|
+
export declare const DEFAULT_CATEGORY = "GENERAL_OFFICE";
|
|
12
|
+
/** 类别编码 → 中文名(未匹配返回原值) */
|
|
13
|
+
export declare function categoryLabel(code: string | null | undefined): string;
|
|
14
|
+
/** 表格默认每页条数 */
|
|
15
|
+
export declare const SKILL_PAGE_SIZE = 10;
|
|
16
|
+
/** 分页可选项 */
|
|
17
|
+
export declare const SKILL_PAGE_SIZE_OPTIONS: number[];
|
package/dist/index.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
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*/
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
export * from './types';
|
|
3
|
+
export * from './constants';
|
|
4
|
+
export { ALL_SKILLS_NODE_ID, loadDomainTree, loadDomainTreeWithRoot, loadTopicNameMap, querySkillPage, } from './api/skill-select-data';
|
|
5
|
+
export type { SkillPageFilter } from './api/skill-select-data';
|
|
6
|
+
export { useSkillSelection } from './composables/use-skill-selection';
|
|
7
|
+
export type { UseSkillSelectionOptions, SkillSelectionStore } from './composables/use-skill-selection';
|
|
8
|
+
export { SkillSelectDialog } from './components/skill-select-dialog';
|
|
9
|
+
export { SkillSelectField } from './components/skill-select-field';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,763 @@
|
|
|
1
|
+
import { request as e } from "@gsp-sys/utils";
|
|
2
|
+
import { computed as t, createTextVNode as n, createVNode as r, defineComponent as i, ref as a, shallowRef as o, watch as s } from "vue";
|
|
3
|
+
import { FButton as c, FDataGrid as ee, FPagination as l, FTreeView as u } from "@farris/ui-vue";
|
|
4
|
+
//#region src/types.ts
|
|
5
|
+
var d = { items: [] };
|
|
6
|
+
function f(e) {
|
|
7
|
+
let t = e.displayName || e.name;
|
|
8
|
+
return {
|
|
9
|
+
value: e.id,
|
|
10
|
+
text: t,
|
|
11
|
+
skill: e
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/constants.ts
|
|
16
|
+
var p = [{
|
|
17
|
+
value: "GENERAL_OFFICE",
|
|
18
|
+
label: "通用办公技能"
|
|
19
|
+
}, {
|
|
20
|
+
value: "BUSINESS_SYSTEM",
|
|
21
|
+
label: "业务系统技能"
|
|
22
|
+
}], m = "GENERAL_OFFICE";
|
|
23
|
+
function h(e) {
|
|
24
|
+
if (!e) return "-";
|
|
25
|
+
let t = p.find((t) => t.value === e);
|
|
26
|
+
return t ? t.label : e;
|
|
27
|
+
}
|
|
28
|
+
var g = 10, _ = [
|
|
29
|
+
10,
|
|
30
|
+
20,
|
|
31
|
+
50
|
|
32
|
+
], v = class extends Error {
|
|
33
|
+
status;
|
|
34
|
+
details;
|
|
35
|
+
code;
|
|
36
|
+
category;
|
|
37
|
+
constructor(e, t, n, r, i) {
|
|
38
|
+
super(e), this.name = "ApiError", this.status = t, this.details = n, this.code = r, this.category = i;
|
|
39
|
+
}
|
|
40
|
+
get serverMessage() {
|
|
41
|
+
return this.details;
|
|
42
|
+
}
|
|
43
|
+
get innerMessage() {
|
|
44
|
+
return this.details;
|
|
45
|
+
}
|
|
46
|
+
}, y = "/api/runtime/aihub/v1.0";
|
|
47
|
+
function b() {
|
|
48
|
+
return typeof window > "u" ? {} : window.__SKILLHUB_RUNTIME_CONFIG__ ?? {};
|
|
49
|
+
}
|
|
50
|
+
function x(e) {
|
|
51
|
+
let t = b().apiBaseUrl;
|
|
52
|
+
return t && e.startsWith("/") ? `${t.replace(/\/$/, "")}${e}` : e;
|
|
53
|
+
}
|
|
54
|
+
var S = {
|
|
55
|
+
GET: "get",
|
|
56
|
+
POST: "post",
|
|
57
|
+
PUT: "put",
|
|
58
|
+
DELETE: "delete",
|
|
59
|
+
PATCH: "patch"
|
|
60
|
+
};
|
|
61
|
+
function C(e) {
|
|
62
|
+
let t = {};
|
|
63
|
+
typeof e?.body == "string" && (t["Content-Type"] = "application/json");
|
|
64
|
+
try {
|
|
65
|
+
t["Accept-Language"] = localStorage.getItem("language") || navigator.language.split("-")[0] || "en";
|
|
66
|
+
} catch {}
|
|
67
|
+
return t;
|
|
68
|
+
}
|
|
69
|
+
function te(e) {
|
|
70
|
+
if (e && typeof e == "object" && !Array.isArray(e)) {
|
|
71
|
+
let t = e;
|
|
72
|
+
if ("code" in t && "data" in t || "success" in t && "data" in t) return null;
|
|
73
|
+
}
|
|
74
|
+
return e;
|
|
75
|
+
}
|
|
76
|
+
function w(e) {
|
|
77
|
+
let t = e?.message ?? e?.Message ?? e?.errorMessage;
|
|
78
|
+
return typeof t == "string" && t ? t : void 0;
|
|
79
|
+
}
|
|
80
|
+
function T(e) {
|
|
81
|
+
if (e instanceof v) return e;
|
|
82
|
+
let t = e;
|
|
83
|
+
if (t?.isAxiosError) {
|
|
84
|
+
if (t.code === "ECONNABORTED" || t.code === "ETIMEDOUT") return new v("error.request.timeout", 408, "");
|
|
85
|
+
let e = t.response?.status ?? 0, n = w(t.response?.data) ?? `HTTP ${e || 0}`;
|
|
86
|
+
return new v(n, e, n);
|
|
87
|
+
}
|
|
88
|
+
if (e && typeof e == "object") {
|
|
89
|
+
let t = e, n = w(t) ?? "error", r = Number(t.code ?? t.Code ?? t.status) || 0, i = t.error;
|
|
90
|
+
return new v(n, r, n, i?.code, i?.category);
|
|
91
|
+
}
|
|
92
|
+
return typeof e == "string" ? new v(e || "error", 0, e || "error") : e instanceof Error ? new v(e.message || "error", 0, e.message || "error") : new v("error", 0, "");
|
|
93
|
+
}
|
|
94
|
+
async function E(t, n, r) {
|
|
95
|
+
let i = (n?.method ? S[n.method.toUpperCase()] : "get") ?? "get";
|
|
96
|
+
try {
|
|
97
|
+
return te(await e({
|
|
98
|
+
url: t,
|
|
99
|
+
method: i,
|
|
100
|
+
headers: C(n),
|
|
101
|
+
data: n?.body,
|
|
102
|
+
notLoading: !0,
|
|
103
|
+
...r ? { responseType: r } : {}
|
|
104
|
+
}));
|
|
105
|
+
} catch (e) {
|
|
106
|
+
throw T(e);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function D(e) {
|
|
110
|
+
let t = new URLSearchParams();
|
|
111
|
+
for (let [n, r] of Object.entries(e)) r != null && r !== "" && t.append(n, String(r));
|
|
112
|
+
let n = t.toString();
|
|
113
|
+
return n ? `?${n}` : "";
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region ../api-client/src/fetch/repo.ts
|
|
117
|
+
function O(e, t) {
|
|
118
|
+
return E(x(e), t);
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region ../api-client/src/fetch/skill.ts
|
|
122
|
+
function k(e, t) {
|
|
123
|
+
return E(x(e), t);
|
|
124
|
+
}
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region ../api-client/src/api/custom-skills.ts
|
|
127
|
+
var A = `${y}/customSkills`;
|
|
128
|
+
async function j(e, t) {
|
|
129
|
+
return k(`${A}/listByAuth${D({
|
|
130
|
+
page: e.page,
|
|
131
|
+
size: e.size,
|
|
132
|
+
keyword: e.keyword,
|
|
133
|
+
group: e.group,
|
|
134
|
+
businessDomain: e.businessDomain,
|
|
135
|
+
topic: e.topic,
|
|
136
|
+
category: e.category,
|
|
137
|
+
repo: e.repo
|
|
138
|
+
})}`, { signal: t });
|
|
139
|
+
}
|
|
140
|
+
`${y}`;
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region ../api-client/src/api/topics.ts
|
|
143
|
+
var M = `${y}/topics`;
|
|
144
|
+
async function N() {
|
|
145
|
+
return O(M);
|
|
146
|
+
}
|
|
147
|
+
`${y}`;
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region ../api-client/src/api/business-domains.ts
|
|
150
|
+
async function P() {
|
|
151
|
+
return await k("/api/runtime/aihub/v1.0/business-domains/tree") ?? [];
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/api/skill-select-data.ts
|
|
155
|
+
var F = "__all_skills__", I = null, L = null, R = null, z = null;
|
|
156
|
+
async function B() {
|
|
157
|
+
return R || z || (z = N().then((e) => (R = e ?? [], R)).finally(() => {
|
|
158
|
+
z = null;
|
|
159
|
+
}), z);
|
|
160
|
+
}
|
|
161
|
+
function V(e) {
|
|
162
|
+
return {
|
|
163
|
+
id: e?.id ?? e?.code ?? "",
|
|
164
|
+
code: e?.code ?? e?.id,
|
|
165
|
+
name: e?.name ?? e?.code ?? "未命名",
|
|
166
|
+
children: Array.isArray(e?.children) ? e.children.map(V) : void 0
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
async function ne() {
|
|
170
|
+
return [{
|
|
171
|
+
id: F,
|
|
172
|
+
name: "全部技能",
|
|
173
|
+
children: await H()
|
|
174
|
+
}];
|
|
175
|
+
}
|
|
176
|
+
async function H() {
|
|
177
|
+
return I || L || (L = P().then((e) => (e ?? []).map(V)).then((e) => (I = e, e)).finally(() => {
|
|
178
|
+
L = null;
|
|
179
|
+
}), L);
|
|
180
|
+
}
|
|
181
|
+
function re(e) {
|
|
182
|
+
let t = /* @__PURE__ */ new Map(), n = (e) => {
|
|
183
|
+
for (let r of e) r.code && t.set(r.code, r.name), r.children && n(r.children);
|
|
184
|
+
};
|
|
185
|
+
return n(e), t;
|
|
186
|
+
}
|
|
187
|
+
async function U() {
|
|
188
|
+
let e = await B(), t = /* @__PURE__ */ new Map();
|
|
189
|
+
for (let n of e) {
|
|
190
|
+
let e = n?.name ?? n?.code ?? n?.id;
|
|
191
|
+
e && (n?.code && t.set(n.code, e), n?.id && t.set(n.id, e));
|
|
192
|
+
}
|
|
193
|
+
return t;
|
|
194
|
+
}
|
|
195
|
+
async function W() {
|
|
196
|
+
return (await B()).filter((e) => !!e?.code).map((e) => ({
|
|
197
|
+
id: e.code,
|
|
198
|
+
code: e.code,
|
|
199
|
+
name: e?.name ?? e.code
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
async function ie() {
|
|
203
|
+
return [{
|
|
204
|
+
id: F,
|
|
205
|
+
name: "全部技能",
|
|
206
|
+
children: await W()
|
|
207
|
+
}];
|
|
208
|
+
}
|
|
209
|
+
function G(e, t) {
|
|
210
|
+
return j({
|
|
211
|
+
page: e.page ?? 0,
|
|
212
|
+
size: e.size ?? 10,
|
|
213
|
+
keyword: e.keyword?.trim() || void 0,
|
|
214
|
+
businessDomain: e.businessDomain || void 0,
|
|
215
|
+
topic: e.topic || void 0,
|
|
216
|
+
category: e.category || void 0
|
|
217
|
+
}, t);
|
|
218
|
+
}
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region src/composables/use-skill-selection.ts
|
|
221
|
+
function K(e) {
|
|
222
|
+
let t = e ?? {};
|
|
223
|
+
return (t?.raw ?? t)?.id ?? t?.id;
|
|
224
|
+
}
|
|
225
|
+
function q(e = {}) {
|
|
226
|
+
let n = e.singleSelect ?? !1, r = o(/* @__PURE__ */ new Map()), i = o(/* @__PURE__ */ new Map());
|
|
227
|
+
function a(e) {
|
|
228
|
+
if (!e?.length) return;
|
|
229
|
+
let t = new Map(i.value);
|
|
230
|
+
for (let n of e) t.set(n.id, n);
|
|
231
|
+
i.value = t;
|
|
232
|
+
}
|
|
233
|
+
function s(e, t) {
|
|
234
|
+
let a = n && e.length > 1 ? e.slice(-1) : e, o = /* @__PURE__ */ new Map();
|
|
235
|
+
for (let e of a) {
|
|
236
|
+
let t = r.value.get(e);
|
|
237
|
+
if (t) {
|
|
238
|
+
o.set(e, t);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
let n = i.value.get(e);
|
|
242
|
+
n ? o.set(e, f(n)) : o.set(e, {
|
|
243
|
+
value: e,
|
|
244
|
+
text: e
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
if (t) for (let [e, n] of r.value) t.has(e) || o.set(e, n);
|
|
248
|
+
r.value = o;
|
|
249
|
+
}
|
|
250
|
+
function c(e, t, n) {
|
|
251
|
+
s(Array.isArray(t) && t.length ? t : Array.isArray(e) ? e.map(K).filter(Boolean) : [], n);
|
|
252
|
+
}
|
|
253
|
+
function ee(e) {
|
|
254
|
+
let t = K(e);
|
|
255
|
+
if (!t) return;
|
|
256
|
+
let n = new Map(r.value);
|
|
257
|
+
if (n.has(t)) n.delete(t);
|
|
258
|
+
else {
|
|
259
|
+
let e = i.value.get(t);
|
|
260
|
+
n.set(t, e ? f(e) : {
|
|
261
|
+
value: t,
|
|
262
|
+
text: t
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
r.value = n;
|
|
266
|
+
}
|
|
267
|
+
function l(e) {
|
|
268
|
+
let t = K(e);
|
|
269
|
+
t && s([t]);
|
|
270
|
+
}
|
|
271
|
+
function u(e) {
|
|
272
|
+
let t = new Map(r.value);
|
|
273
|
+
t.delete(e), r.value = t;
|
|
274
|
+
}
|
|
275
|
+
function d() {
|
|
276
|
+
r.value = /* @__PURE__ */ new Map();
|
|
277
|
+
}
|
|
278
|
+
function p(e) {
|
|
279
|
+
if (!e?.length) {
|
|
280
|
+
r.value = /* @__PURE__ */ new Map();
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
let t = /* @__PURE__ */ new Map();
|
|
284
|
+
for (let n of e) n?.value && t.set(n.value, n);
|
|
285
|
+
r.value = t;
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
singleSelect: n,
|
|
289
|
+
selectedIds: t(() => [...r.value.keys()]),
|
|
290
|
+
items: t(() => [...r.value.values()]),
|
|
291
|
+
count: t(() => r.value.size),
|
|
292
|
+
indexPageItems: a,
|
|
293
|
+
handleGridSelectionUpdate: c,
|
|
294
|
+
toggleItem: ee,
|
|
295
|
+
selectRow: l,
|
|
296
|
+
removeItem: u,
|
|
297
|
+
clear: d,
|
|
298
|
+
restore: p
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
//#endregion
|
|
302
|
+
//#region src/components/skill-select-dialog.tsx
|
|
303
|
+
var ae = [
|
|
304
|
+
{
|
|
305
|
+
field: "_name",
|
|
306
|
+
title: "技能名称",
|
|
307
|
+
width: "26%",
|
|
308
|
+
showEllipsis: !0,
|
|
309
|
+
showTips: !0,
|
|
310
|
+
tipMode: "auto"
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
field: "_version",
|
|
314
|
+
title: "最新版本",
|
|
315
|
+
width: "10%"
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
field: "_category",
|
|
319
|
+
title: "使用类别",
|
|
320
|
+
width: "14%",
|
|
321
|
+
showEllipsis: !0
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
field: "_topicName",
|
|
325
|
+
title: "技能分类",
|
|
326
|
+
width: "17%",
|
|
327
|
+
showEllipsis: !0,
|
|
328
|
+
showTips: !0,
|
|
329
|
+
tipMode: "auto"
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
field: "_domainName",
|
|
333
|
+
title: "所属业务域",
|
|
334
|
+
width: "18%",
|
|
335
|
+
showEllipsis: !0,
|
|
336
|
+
showTips: !0,
|
|
337
|
+
tipMode: "auto"
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
field: "_author",
|
|
341
|
+
title: "作者",
|
|
342
|
+
width: "15%",
|
|
343
|
+
showEllipsis: !0
|
|
344
|
+
}
|
|
345
|
+
], oe = "GENERAL_OFFICE", se = [
|
|
346
|
+
{
|
|
347
|
+
field: "_name",
|
|
348
|
+
title: "技能名称",
|
|
349
|
+
width: "33%",
|
|
350
|
+
showEllipsis: !0,
|
|
351
|
+
showTips: !0,
|
|
352
|
+
tipMode: "auto"
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
field: "_version",
|
|
356
|
+
title: "最新版本",
|
|
357
|
+
width: "34%"
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
field: "_topicName",
|
|
361
|
+
title: "技能分类",
|
|
362
|
+
width: "33%",
|
|
363
|
+
showEllipsis: !0,
|
|
364
|
+
showTips: !0,
|
|
365
|
+
tipMode: "auto"
|
|
366
|
+
}
|
|
367
|
+
], ce = [
|
|
368
|
+
{
|
|
369
|
+
field: "_name",
|
|
370
|
+
title: "技能名称",
|
|
371
|
+
width: "33%",
|
|
372
|
+
showEllipsis: !0,
|
|
373
|
+
showTips: !0,
|
|
374
|
+
tipMode: "auto"
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
field: "_version",
|
|
378
|
+
title: "最新版本",
|
|
379
|
+
width: "34%"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
field: "_domainName",
|
|
383
|
+
title: "所属业务域",
|
|
384
|
+
width: "33%",
|
|
385
|
+
showEllipsis: !0,
|
|
386
|
+
showTips: !0,
|
|
387
|
+
tipMode: "auto"
|
|
388
|
+
}
|
|
389
|
+
], J = /* @__PURE__ */ i({
|
|
390
|
+
name: "SkillSelectDialog",
|
|
391
|
+
props: {
|
|
392
|
+
modelValue: {
|
|
393
|
+
type: Boolean,
|
|
394
|
+
default: !1
|
|
395
|
+
},
|
|
396
|
+
singleSelect: {
|
|
397
|
+
type: Boolean,
|
|
398
|
+
default: !1
|
|
399
|
+
},
|
|
400
|
+
initSelected: {
|
|
401
|
+
type: Array,
|
|
402
|
+
default: () => []
|
|
403
|
+
},
|
|
404
|
+
initCategory: {
|
|
405
|
+
type: String,
|
|
406
|
+
default: ""
|
|
407
|
+
},
|
|
408
|
+
title: {
|
|
409
|
+
type: String,
|
|
410
|
+
default: "选择技能"
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
emits: ["update:modelValue", "confirm"],
|
|
414
|
+
setup(e, { emit: i }) {
|
|
415
|
+
let o = t(() => e.modelValue), d = t(() => e.initCategory === oe), f = a(null), m = a(null), g = a(0), v = a(F), y = a(/* @__PURE__ */ new Map()), b = a(/* @__PURE__ */ new Map()), x = t(() => d.value ? m.value : f.value), S = t(() => x.value ? [x.value] : []), C = t(() => e.initCategory === "GENERAL_OFFICE" ? se : e.initCategory === "BUSINESS_SYSTEM" ? ce : ae), te = {
|
|
416
|
+
enableSelectRow: !0,
|
|
417
|
+
multiSelect: !1,
|
|
418
|
+
showCheckbox: !1,
|
|
419
|
+
showSelectAll: !1,
|
|
420
|
+
showSelection: !0
|
|
421
|
+
}, w = a(""), T = a(""), E = a(""), D = a(0), O = a(10), k = a(0), A = a([]), j = a(!1), M = a(null), N = a(0), P = q({ singleSelect: e.singleSelect }), I = t(() => e.singleSelect ? {
|
|
422
|
+
enableSelectRow: !1,
|
|
423
|
+
multiSelect: !1,
|
|
424
|
+
showCheckbox: !0,
|
|
425
|
+
showSelectAll: !1,
|
|
426
|
+
showSelection: !1
|
|
427
|
+
} : {
|
|
428
|
+
enableSelectRow: !1,
|
|
429
|
+
multiSelect: !0,
|
|
430
|
+
showCheckbox: !0,
|
|
431
|
+
showSelectAll: !0,
|
|
432
|
+
showSelection: !1,
|
|
433
|
+
multiSelectMode: "DependOnCheck",
|
|
434
|
+
keepSelectingOnPaging: !0
|
|
435
|
+
});
|
|
436
|
+
function L(e) {
|
|
437
|
+
return {
|
|
438
|
+
...e,
|
|
439
|
+
_name: e.displayName || e.name,
|
|
440
|
+
_version: e.latestVersion || "-",
|
|
441
|
+
_category: h(e.category),
|
|
442
|
+
_topicName: e.topic ? b.value.get(e.topic) ?? e.topic : "-",
|
|
443
|
+
_domainName: e.businessDomain ? y.value.get(e.businessDomain) ?? e.businessDomain : "-",
|
|
444
|
+
_author: e.ownerDisplayName || e.author || "-"
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
let R = t(() => A.value.map(L));
|
|
448
|
+
s(R, (e) => {
|
|
449
|
+
M.value?.updateDataSource && M.value.updateDataSource(e);
|
|
450
|
+
}, { flush: "post" });
|
|
451
|
+
async function z() {
|
|
452
|
+
let e = ++N.value;
|
|
453
|
+
j.value = !0;
|
|
454
|
+
try {
|
|
455
|
+
let t = B(), n = await G({
|
|
456
|
+
page: D.value,
|
|
457
|
+
size: O.value,
|
|
458
|
+
keyword: T.value,
|
|
459
|
+
businessDomain: d.value ? void 0 : t,
|
|
460
|
+
topic: d.value ? t : void 0,
|
|
461
|
+
category: E.value || void 0
|
|
462
|
+
});
|
|
463
|
+
if (e !== N.value) return;
|
|
464
|
+
A.value = n?.items ?? [], k.value = n?.total ?? 0, P.indexPageItems(A.value);
|
|
465
|
+
} catch (t) {
|
|
466
|
+
if (e !== N.value) return;
|
|
467
|
+
A.value = [], k.value = 0, console.error("[skill-select-workbench] 查询技能列表失败", t);
|
|
468
|
+
} finally {
|
|
469
|
+
e === N.value && (j.value = !1);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
function B() {
|
|
473
|
+
let e = x.value;
|
|
474
|
+
if (!e || v.value === "__all_skills__") return;
|
|
475
|
+
let t = (e) => {
|
|
476
|
+
if (e) for (let n of e) {
|
|
477
|
+
if (n.id === v.value) return n.code;
|
|
478
|
+
let e = t(n.children);
|
|
479
|
+
if (e) return e;
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
return t(e.children);
|
|
483
|
+
}
|
|
484
|
+
function V(e) {
|
|
485
|
+
e?.id && (v.value = e.id, D.value = 0, z());
|
|
486
|
+
}
|
|
487
|
+
let H = t(() => (A.value.length, P.selectedIds.value));
|
|
488
|
+
function W(e, t) {
|
|
489
|
+
let n = new Set(A.value.map((e) => e.id));
|
|
490
|
+
P.handleGridSelectionUpdate(e, t, n);
|
|
491
|
+
}
|
|
492
|
+
let K = null;
|
|
493
|
+
function J(e) {
|
|
494
|
+
K = e.target;
|
|
495
|
+
}
|
|
496
|
+
function Y() {
|
|
497
|
+
let e = K;
|
|
498
|
+
return !!e && typeof e.closest == "function" && !!e.closest(".custom-checkbox, label, input[type=\"checkbox\"]");
|
|
499
|
+
}
|
|
500
|
+
function le(e) {
|
|
501
|
+
let t = e ?? {};
|
|
502
|
+
return t.raw?.id ?? t.id;
|
|
503
|
+
}
|
|
504
|
+
function ue(t, n) {
|
|
505
|
+
if (!Y()) {
|
|
506
|
+
if (e.singleSelect) {
|
|
507
|
+
let e = le(n), t = P.items.value;
|
|
508
|
+
if (e && t.length === 1 && t[0].value === e) {
|
|
509
|
+
P.clear();
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
P.selectRow(n);
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
P.toggleItem(n);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
function de(e) {
|
|
519
|
+
D.value = e, z();
|
|
520
|
+
}
|
|
521
|
+
function fe(e) {
|
|
522
|
+
O.value = e, D.value = 0, z();
|
|
523
|
+
}
|
|
524
|
+
function X(e) {
|
|
525
|
+
E.value = e, D.value = 0, z();
|
|
526
|
+
}
|
|
527
|
+
let Z;
|
|
528
|
+
function pe(e) {
|
|
529
|
+
w.value = e.target.value, Z && clearTimeout(Z), Z = setTimeout(() => {
|
|
530
|
+
T.value = w.value.trim(), D.value = 0, z();
|
|
531
|
+
}, 350);
|
|
532
|
+
}
|
|
533
|
+
function me() {
|
|
534
|
+
w.value = "", T.value = "", D.value = 0, z();
|
|
535
|
+
}
|
|
536
|
+
let Q = !1;
|
|
537
|
+
async function he() {
|
|
538
|
+
if (!Q) {
|
|
539
|
+
Q = !0;
|
|
540
|
+
try {
|
|
541
|
+
w.value = "", T.value = "", E.value = e.initCategory, D.value = 0, O.value = 10, k.value = 0, A.value = [], N.value++, v.value = F, P.restore(e.initSelected);
|
|
542
|
+
try {
|
|
543
|
+
if (d.value) {
|
|
544
|
+
if (!m.value) {
|
|
545
|
+
let e = await ie();
|
|
546
|
+
m.value = e[0], g.value++;
|
|
547
|
+
}
|
|
548
|
+
} else if (!f.value) {
|
|
549
|
+
let e = await ne();
|
|
550
|
+
f.value = e[0], y.value = re(e[0]?.children ?? []), g.value++;
|
|
551
|
+
}
|
|
552
|
+
if (b.value.size === 0) {
|
|
553
|
+
let e = await U();
|
|
554
|
+
b.value.size === 0 && (b.value = e);
|
|
555
|
+
}
|
|
556
|
+
} catch (e) {
|
|
557
|
+
console.error("[skill-select-workbench] 加载筛选数据失败", e);
|
|
558
|
+
}
|
|
559
|
+
await z();
|
|
560
|
+
} finally {
|
|
561
|
+
Q = !1;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
s(o, (e) => {
|
|
566
|
+
e && he();
|
|
567
|
+
}, { immediate: !0 });
|
|
568
|
+
function $() {
|
|
569
|
+
i("update:modelValue", !1);
|
|
570
|
+
}
|
|
571
|
+
function ge() {
|
|
572
|
+
i("confirm", { items: P.items.value }), $();
|
|
573
|
+
}
|
|
574
|
+
function _e(e) {
|
|
575
|
+
P.removeItem(e);
|
|
576
|
+
}
|
|
577
|
+
function ve() {
|
|
578
|
+
P.clear();
|
|
579
|
+
}
|
|
580
|
+
function ye(e) {
|
|
581
|
+
e.stopPropagation();
|
|
582
|
+
}
|
|
583
|
+
return () => o.value ? r("div", {
|
|
584
|
+
class: "ssw-overlay",
|
|
585
|
+
onMousedown: ye,
|
|
586
|
+
onClick: ye
|
|
587
|
+
}, [r("div", {
|
|
588
|
+
class: "ssw-dialog",
|
|
589
|
+
role: "dialog",
|
|
590
|
+
"aria-modal": "true"
|
|
591
|
+
}, [
|
|
592
|
+
r("div", { class: "ssw-dialog__header" }, [r("span", { class: "ssw-dialog__title" }, [e.title]), r("button", {
|
|
593
|
+
type: "button",
|
|
594
|
+
class: "ssw-dialog__close",
|
|
595
|
+
onClick: $,
|
|
596
|
+
"aria-label": "关闭"
|
|
597
|
+
}, [r("span", { class: "ssw-icon-close" }, [n("×")])])]),
|
|
598
|
+
r("div", { class: "ssw-dialog__body" }, [r("div", { class: "ssw-pane ssw-pane--tree" }, [r("div", { class: "ssw-pane__head" }, [r("span", null, [d.value ? "技能分类" : "业务域"])]), r("div", { class: "ssw-tree-wrap" }, [S.value.length ? r(u, {
|
|
599
|
+
key: g.value,
|
|
600
|
+
data: S.value,
|
|
601
|
+
idField: "id",
|
|
602
|
+
displayField: "name",
|
|
603
|
+
columns: [{
|
|
604
|
+
field: "name",
|
|
605
|
+
title: "",
|
|
606
|
+
width: "100%",
|
|
607
|
+
showEllipsis: !0,
|
|
608
|
+
showTips: !0,
|
|
609
|
+
tipMode: "auto"
|
|
610
|
+
}],
|
|
611
|
+
selection: te,
|
|
612
|
+
selectionValues: [v.value],
|
|
613
|
+
fit: !0,
|
|
614
|
+
onClickRow: (e, t) => V(t)
|
|
615
|
+
}, null) : r("div", { class: "ssw-tree-empty" }, [n("加载中…")])])]), r("div", { class: "ssw-pane ssw-pane--grid" }, [
|
|
616
|
+
r("div", { class: "ssw-toolbar" }, [r("div", { class: "ssw-search" }, [r("input", {
|
|
617
|
+
class: "ssw-search__input",
|
|
618
|
+
placeholder: "搜索技能名称",
|
|
619
|
+
value: w.value,
|
|
620
|
+
onInput: pe
|
|
621
|
+
}, null), w.value ? r("button", {
|
|
622
|
+
type: "button",
|
|
623
|
+
class: "ssw-search__clear",
|
|
624
|
+
onClick: me
|
|
625
|
+
}, [n("×")]) : null])]),
|
|
626
|
+
!e.initCategory && r("div", { class: "ssw-filter" }, [
|
|
627
|
+
r("span", { class: "ssw-filter__label" }, [n("技能类型")]),
|
|
628
|
+
r("button", {
|
|
629
|
+
type: "button",
|
|
630
|
+
class: ["ssw-filter__btn", E.value === "" ? "ssw-filter__btn--active" : ""].join(" "),
|
|
631
|
+
onClick: () => X("")
|
|
632
|
+
}, [n("全部")]),
|
|
633
|
+
p.map((e) => r("button", {
|
|
634
|
+
type: "button",
|
|
635
|
+
class: ["ssw-filter__btn", E.value === e.value ? "ssw-filter__btn--active" : ""].join(" "),
|
|
636
|
+
onClick: () => X(e.value)
|
|
637
|
+
}, [e.label]))
|
|
638
|
+
]),
|
|
639
|
+
r("div", {
|
|
640
|
+
class: "ssw-grid-wrap",
|
|
641
|
+
onClickCapture: J
|
|
642
|
+
}, [
|
|
643
|
+
r(ee, {
|
|
644
|
+
ref: M,
|
|
645
|
+
idField: "id",
|
|
646
|
+
data: R.value,
|
|
647
|
+
columns: C.value,
|
|
648
|
+
selection: I.value,
|
|
649
|
+
selectionValues: H.value,
|
|
650
|
+
onSelectionUpdate: W,
|
|
651
|
+
onClickRow: ue,
|
|
652
|
+
fit: !0,
|
|
653
|
+
showHeader: !0
|
|
654
|
+
}, null),
|
|
655
|
+
j.value && r("div", { class: "ssw-grid-loading" }, [n("加载中…")]),
|
|
656
|
+
!j.value && R.value.length === 0 && r("div", { class: "ssw-grid-empty" }, [n("暂无可选技能")])
|
|
657
|
+
]),
|
|
658
|
+
k.value > 0 && r("div", { class: "ssw-pagination" }, [r(l, {
|
|
659
|
+
currentPage: D.value + 1,
|
|
660
|
+
totalItems: k.value,
|
|
661
|
+
pageSize: O.value,
|
|
662
|
+
pageList: _,
|
|
663
|
+
showPageList: !0,
|
|
664
|
+
showGoButton: !1,
|
|
665
|
+
showPageInfo: !0,
|
|
666
|
+
"onUpdate:currentPage": (e) => de(e - 1),
|
|
667
|
+
"onUpdate:pageSize": (e) => fe(e)
|
|
668
|
+
}, null)])
|
|
669
|
+
])]),
|
|
670
|
+
r("div", { class: "ssw-dialog__footer" }, [r("div", { class: "ssw-footer-selection" }, [P.items.value.length === 0 ? r("span", { class: "ssw-footer-placeholder" }, [e.singleSelect ? "请选择一个技能" : "请选择技能,可跨页多选"]) : P.items.value.map((e) => r("span", {
|
|
671
|
+
key: e.value,
|
|
672
|
+
class: "ssw-chip",
|
|
673
|
+
title: e.text
|
|
674
|
+
}, [r("span", { class: "ssw-chip__text" }, [e.text]), r("a", {
|
|
675
|
+
class: "ssw-chip__remove",
|
|
676
|
+
onClick: (t) => {
|
|
677
|
+
t.stopPropagation(), _e(e.value);
|
|
678
|
+
}
|
|
679
|
+
}, [n("×")])]))]), r("div", { class: "ssw-footer-actions" }, [
|
|
680
|
+
r("span", { class: "ssw-footer-count" }, [
|
|
681
|
+
n("已选 "),
|
|
682
|
+
P.count.value,
|
|
683
|
+
n(" 条"),
|
|
684
|
+
P.count.value > 0 && r("a", {
|
|
685
|
+
class: "ssw-clear-all",
|
|
686
|
+
onClick: ve
|
|
687
|
+
}, [n("清空")])
|
|
688
|
+
]),
|
|
689
|
+
r(c, { onClick: $ }, { default: () => [n("取消")] }),
|
|
690
|
+
r(c, {
|
|
691
|
+
type: "primary",
|
|
692
|
+
onClick: ge
|
|
693
|
+
}, { default: () => [n("确定")] })
|
|
694
|
+
])])
|
|
695
|
+
])]) : null;
|
|
696
|
+
}
|
|
697
|
+
}), Y = /* @__PURE__ */ i({
|
|
698
|
+
name: "SkillSelectField",
|
|
699
|
+
props: {
|
|
700
|
+
singleSelect: {
|
|
701
|
+
type: Boolean,
|
|
702
|
+
default: !1
|
|
703
|
+
},
|
|
704
|
+
asyncMode: {
|
|
705
|
+
type: Boolean,
|
|
706
|
+
default: !0
|
|
707
|
+
},
|
|
708
|
+
disabled: {
|
|
709
|
+
type: Boolean,
|
|
710
|
+
default: !1
|
|
711
|
+
},
|
|
712
|
+
placeholder: {
|
|
713
|
+
type: String,
|
|
714
|
+
default: "请选择技能"
|
|
715
|
+
},
|
|
716
|
+
selectedItems: {
|
|
717
|
+
type: Array,
|
|
718
|
+
default: () => []
|
|
719
|
+
}
|
|
720
|
+
},
|
|
721
|
+
emits: ["update:selectedItems"],
|
|
722
|
+
setup(e, { emit: t }) {
|
|
723
|
+
let i = a(!1);
|
|
724
|
+
function o() {
|
|
725
|
+
e.disabled || (i.value = !0);
|
|
726
|
+
}
|
|
727
|
+
function s(e) {
|
|
728
|
+
t("update:selectedItems", e.items), i.value = !1;
|
|
729
|
+
}
|
|
730
|
+
function c(e) {
|
|
731
|
+
e.stopPropagation();
|
|
732
|
+
}
|
|
733
|
+
return () => {
|
|
734
|
+
let a = e.selectedItems ?? [];
|
|
735
|
+
return r("div", null, [r("div", {
|
|
736
|
+
class: ["ssw-field", { "ssw-field--disabled": e.disabled }].join(" "),
|
|
737
|
+
onClick: o
|
|
738
|
+
}, [a.length === 0 ? r("span", { class: "ssw-field__placeholder" }, [e.placeholder]) : r("span", {
|
|
739
|
+
class: "ssw-field__value",
|
|
740
|
+
title: a.map((e) => e.text).join("、")
|
|
741
|
+
}, [e.singleSelect ? a[a.length - 1]?.text : `${a[0]?.text}${a.length > 1 ? ` 等 ${a.length} 项` : ""}`]), r("span", { class: "ssw-field__actions" }, [a.length > 0 && r("a", {
|
|
742
|
+
class: "ssw-field__clear",
|
|
743
|
+
role: "button",
|
|
744
|
+
"aria-label": "清空",
|
|
745
|
+
onClick: (e) => {
|
|
746
|
+
c(e), t("update:selectedItems", []);
|
|
747
|
+
}
|
|
748
|
+
}, [n("×")]), r("span", {
|
|
749
|
+
class: "ssw-field__open",
|
|
750
|
+
role: "button",
|
|
751
|
+
"aria-label": "选择"
|
|
752
|
+
}, [n("···")])])]), i.value && r(J, {
|
|
753
|
+
modelValue: i.value,
|
|
754
|
+
"onUpdate:modelValue": (e) => i.value = e,
|
|
755
|
+
singleSelect: e.singleSelect,
|
|
756
|
+
initSelected: a,
|
|
757
|
+
onConfirm: s
|
|
758
|
+
}, null)]);
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
//#endregion
|
|
763
|
+
export { F as ALL_SKILLS_NODE_ID, m as DEFAULT_CATEGORY, d as EMPTY_SKILL_SELECT_PAYLOAD, p as SKILL_CATEGORIES, g as SKILL_PAGE_SIZE, _ as SKILL_PAGE_SIZE_OPTIONS, J as SkillSelectDialog, Y as SkillSelectField, h as categoryLabel, H as loadDomainTree, ne as loadDomainTreeWithRoot, U as loadTopicNameMap, G as querySkillPage, f as toSkillSelectItem, q as useSkillSelection };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SkillSummaryResponse } from '@aihub/api-client';
|
|
2
|
+
/** 左侧筛选树的节点(业务域层级),数据结构与 listBusinessDomains 返回值对齐 */
|
|
3
|
+
export interface SkillDomainTreeNode {
|
|
4
|
+
/** 节点 ID(业务域 id;"全部技能"虚拟节点为固定串 __all_skills__) */
|
|
5
|
+
id: string;
|
|
6
|
+
/** 业务域编码(作为 listSkills 的 businessDomain 过滤值;缺省回退为 id) */
|
|
7
|
+
code?: string;
|
|
8
|
+
/** 展示名称 */
|
|
9
|
+
name: string;
|
|
10
|
+
/** 子业务域 */
|
|
11
|
+
children?: SkillDomainTreeNode[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 选中的技能项(对外契约,语义对齐 @gsp-sys 组织选择帮助的 selectedItems 条目):
|
|
15
|
+
* - value:技能 id,用于保存/回传
|
|
16
|
+
* - text:回显文本(displayName || name)
|
|
17
|
+
* - skill:完整技能快照,供确认后消费方直接使用
|
|
18
|
+
*/
|
|
19
|
+
export interface SkillSelectItem {
|
|
20
|
+
value: string;
|
|
21
|
+
text: string;
|
|
22
|
+
skill?: SkillSummaryResponse | null;
|
|
23
|
+
}
|
|
24
|
+
/** 弹窗确认回调的载荷 */
|
|
25
|
+
export interface SkillSelectConfirmPayload {
|
|
26
|
+
items: SkillSelectItem[];
|
|
27
|
+
}
|
|
28
|
+
/** 空载荷(确认时无可选技能时使用) */
|
|
29
|
+
export declare const EMPTY_SKILL_SELECT_PAYLOAD: SkillSelectConfirmPayload;
|
|
30
|
+
/** 由技能快照构造对外条目(文本取 displayName || name) */
|
|
31
|
+
export declare function toSkillSelectItem(skill: SkillSummaryResponse): SkillSelectItem;
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@manohub/skill-select-workbench",
|
|
3
|
+
"version": "0.0.1-beta1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "技能选择帮助(共享组件包):左业务域树 + 右技能表双面板选择,基于 @farris/ui-vue 与 @aihub/api-client 新契约",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./index.css": "./dist/index.css"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"sideEffects": [
|
|
20
|
+
"**/*.css"
|
|
21
|
+
],
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"@farris/ui-vue": "^1.8.0",
|
|
24
|
+
"vue": "^3.4.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@farris/ui-vue": "1.8.4",
|
|
28
|
+
"@gsp-sys/utils": "^0.0.6",
|
|
29
|
+
"@vitejs/plugin-vue-jsx": "^5.1.6",
|
|
30
|
+
"typescript": "^5.5.3",
|
|
31
|
+
"vite": "^8.2.2",
|
|
32
|
+
"vue": "^3.4.37",
|
|
33
|
+
"vue-tsc": "^2.0.29",
|
|
34
|
+
"@aihub/api-client": "0.0.1"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"typecheck": "vue-tsc --noEmit -p tsconfig.json",
|
|
38
|
+
"build": "pnpm typecheck && vite build && vue-tsc -p tsconfig.build.json",
|
|
39
|
+
"playground": "vite --config playground/vite.config.ts"
|
|
40
|
+
}
|
|
41
|
+
}
|