@jari-ace/element-plus-component 0.2.0 → 0.2.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.
- package/README.md +1 -18
- package/dist/components/form/JaForm.vue.d.ts +3 -0
- package/dist/components/form/JaForm.vue.d.ts.map +1 -1
- package/dist/components/form/JaForm.vue.js +22 -68
- package/dist/components/form/JaForm.vue.js.map +1 -1
- package/dist/components/formItem/JaFormItem.vue.d.ts +4 -0
- package/dist/components/formItem/JaFormItem.vue.d.ts.map +1 -1
- package/dist/components/formItem/JaFormItem.vue.js +26 -8
- package/dist/components/formItem/JaFormItem.vue.js.map +1 -1
- package/dist/components/userPicker/src/JaUserList.vue.d.ts.map +1 -1
- package/dist/components/userPicker/src/JaUserList.vue.js +41 -7
- package/dist/components/userPicker/src/JaUserList.vue.js.map +1 -1
- package/dist/components/userPicker/src/JaUserPicker.vue.d.ts +9 -2
- package/dist/components/userPicker/src/JaUserPicker.vue.d.ts.map +1 -1
- package/dist/components/userPicker/src/JaUserPicker.vue.js +7 -2
- package/dist/components/userPicker/src/JaUserPicker.vue.js.map +1 -1
- package/dist/components/userPicker/src/UserPicker.vue.d.ts +33 -112
- package/dist/components/userPicker/src/UserPicker.vue.d.ts.map +1 -1
- package/dist/components/userPicker/src/UserPicker.vue.js +262 -288
- package/dist/components/userPicker/src/UserPicker.vue.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/formUtils.d.ts +7 -0
- package/dist/utils/formUtils.d.ts.map +1 -0
- package/dist/utils/formUtils.js +54 -0
- package/dist/utils/formUtils.js.map +1 -0
- package/lib/index.css +1 -1
- package/lib/index.js +1904 -1830
- package/lib/index.umd.cjs +2 -2
- package/package.json +61 -61
- package/packages/components/autoComplete/JaAutoComplete.vue +47 -47
- package/packages/components/autoComplete/index.ts +5 -5
- package/packages/components/avatar/JaAvatar.vue +126 -126
- package/packages/components/avatar/avatarToken.ts +11 -11
- package/packages/components/avatar/defaultImg.ts +14 -14
- package/packages/components/avatar/index.ts +7 -7
- package/packages/components/button/JaButton.vue +51 -51
- package/packages/components/button/index.ts +4 -4
- package/packages/components/channelPicker/index.ts +7 -7
- package/packages/components/channelPicker/src/ChannelPicker.vue +43 -43
- package/packages/components/channelPicker/src/JaChannelPicker.vue +42 -42
- package/packages/components/checkbox/JaCheckbox.vue +73 -73
- package/packages/components/checkbox/index.ts +4 -4
- package/packages/components/checkboxGroup/JaCheckboxGroup.vue +45 -45
- package/packages/components/checkboxGroup/index.ts +4 -4
- package/packages/components/customGroupTree/index.ts +10 -10
- package/packages/components/customGroupTree/src/customGroupTree.vue +91 -91
- package/packages/components/datePicker/JaDatePicker.vue +52 -52
- package/packages/components/datePicker/index.ts +4 -4
- package/packages/components/departmentPicker/index.ts +4 -4
- package/packages/components/departmentPicker/src/DepartmentPicker.vue +107 -107
- package/packages/components/departmentPicker/src/consts.ts +2 -2
- package/packages/components/departmentTree/index.ts +10 -10
- package/packages/components/departmentTree/src/departmentTree.vue +135 -135
- package/packages/components/dropdownButton/JaDropdownButton.vue +59 -59
- package/packages/components/dropdownButton/index.ts +4 -4
- package/packages/components/enumList/EnumListInput.vue +107 -107
- package/packages/components/enumList/JaEnumList.vue +39 -39
- package/packages/components/enumList/index.ts +7 -7
- package/packages/components/enumPicker/index.ts +5 -5
- package/packages/components/enumPicker/src/EnumPicker.vue +103 -103
- package/packages/components/form/JaForm.vue +146 -186
- package/packages/components/form/index.ts +5 -5
- package/packages/components/form/types.ts +4 -4
- package/packages/components/formItem/JaFormItem.vue +87 -68
- package/packages/components/formItem/index.ts +4 -4
- package/packages/components/index.ts +34 -34
- package/packages/components/input/JaInput.vue +143 -143
- package/packages/components/input/index.ts +4 -4
- package/packages/components/inputI18n/I18nBundleEditor.vue +76 -76
- package/packages/components/inputI18n/InputI18n.vue +146 -146
- package/packages/components/inputI18n/JaInputI18n.vue +50 -50
- package/packages/components/inputI18n/index.ts +8 -8
- package/packages/components/inputNumber/JaInputNumber.vue +98 -98
- package/packages/components/inputNumber/index.ts +4 -4
- package/packages/components/mapItemList/JaMapItemList.vue +35 -35
- package/packages/components/mapItemList/MapItemListInput.vue +191 -191
- package/packages/components/mapItemList/index.ts +7 -7
- package/packages/components/numberList/JaNumberList.vue +36 -36
- package/packages/components/numberList/NumberListInput.vue +111 -111
- package/packages/components/numberList/index.ts +7 -7
- package/packages/components/properyPicker/JaPropertyPicker.vue +38 -38
- package/packages/components/properyPicker/PropertyPicker.vue +314 -314
- package/packages/components/properyPicker/index.ts +7 -7
- package/packages/components/radioGroup/JaRadioGroup.vue +50 -50
- package/packages/components/radioGroup/index.ts +4 -4
- package/packages/components/rolePicker/RoleEditor.vue +129 -129
- package/packages/components/rolePicker/RolePicker.vue +44 -44
- package/packages/components/rolePicker/RolePickerRaw.vue +56 -56
- package/packages/components/rolePicker/baseRolePicker.vue +87 -87
- package/packages/components/rolePicker/index.ts +10 -10
- package/packages/components/scrollbar/Scrollbar.vue +89 -89
- package/packages/components/scrollbar/index.ts +5 -5
- package/packages/components/scrollbar/utils.ts +17 -17
- package/packages/components/select/JaSelect.vue +48 -48
- package/packages/components/select/index.ts +4 -4
- package/packages/components/stringList/JaStringList.vue +36 -36
- package/packages/components/stringList/StringListInput.vue +96 -96
- package/packages/components/stringList/index.ts +7 -7
- package/packages/components/switch/JaSwitch.vue +50 -50
- package/packages/components/switch/index.ts +4 -4
- package/packages/components/timePicker/JaTimePicker.vue +52 -52
- package/packages/components/timePicker/index.ts +5 -5
- package/packages/components/tip/index.ts +4 -4
- package/packages/components/tip/src/AceTip.vue +43 -43
- package/packages/components/upload/index.ts +6 -6
- package/packages/components/upload/src/Upload.vue +25 -25
- package/packages/components/upload/src/type.ts +3 -3
- package/packages/components/userGroupPicker/index.ts +4 -4
- package/packages/components/userGroupPicker/src/UserGroupPicker.vue +94 -94
- package/packages/components/userGroupTree/index.ts +10 -10
- package/packages/components/userGroupTree/src/userGroupTree.vue +149 -149
- package/packages/components/userPicker/index.ts +10 -10
- package/packages/components/userPicker/src/CustomGroupManager.vue +189 -189
- package/packages/components/userPicker/src/JaUserList.vue +317 -283
- package/packages/components/userPicker/src/JaUserPicker.vue +40 -37
- package/packages/components/userPicker/src/UserPicker.vue +472 -376
- package/packages/components/userSelectDialog/index.ts +6 -6
- package/packages/components/userSelectDialog/src/userSelectDialog.vue +462 -462
- package/packages/components/userTag/UserInfoTag.vue +397 -397
- package/packages/components/userTag/index.ts +6 -6
- package/packages/components/userTag/sharedAxios.ts +8 -8
- package/packages/directives/auth/index.ts +41 -41
- package/packages/directives/autofocus/index.ts +29 -29
- package/packages/directives/index.ts +10 -10
- package/packages/directives/shortcut/index.ts +192 -192
- package/packages/hooks/useAppInstances.ts +34 -34
- package/packages/hooks/useBackendValidations.ts +81 -81
- package/packages/hooks/useBridage.ts +157 -157
- package/packages/hooks/useClassificationLevels.ts +62 -62
- package/packages/hooks/useDateTimeShortCuts.ts +65 -65
- package/packages/hooks/useRealms.ts +28 -28
- package/packages/hooks/useTreeData.ts +45 -45
- package/packages/hooks/useUserRefQuery.ts +232 -232
- package/packages/index.ts +24 -21
- package/packages/list.json +7 -7
- package/packages/types/custom.d.ts +13 -13
- package/packages/types/window.d.ts +16 -16
- package/packages/utils/formUtils.ts +57 -0
- package/packages/utils/install.ts +43 -43
- package/packages/utils/objectUtils.ts +31 -31
- package/theme-style/fonts/iconfont.json +5196 -5196
- package/theme-style/index.scss +10 -10
- package/theme-style/styles/element-plus-var.scss +1419 -1419
- package/theme-style/styles/iconfont.css +2979 -2979
- package/theme-style/styles/theme-var.scss +72 -72
- package/theme-style/styles/transition.scss +122 -122
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {type SFCWithInstall, withInstall} from "../../utils/install";
|
|
2
|
-
import UserInfoTag from "./UserInfoTag.vue";
|
|
3
|
-
|
|
4
|
-
export const JaUserInfoTag: SFCWithInstall<typeof UserInfoTag> = withInstall(UserInfoTag);
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import {type SFCWithInstall, withInstall} from "../../utils/install";
|
|
2
|
+
import UserInfoTag from "./UserInfoTag.vue";
|
|
3
|
+
|
|
4
|
+
export const JaUserInfoTag: SFCWithInstall<typeof UserInfoTag> = withInstall(UserInfoTag);
|
|
5
|
+
|
|
6
|
+
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {createAxiosWithoutCache, type IAceAxios} from "@jari-ace/app-bolts";
|
|
2
|
-
|
|
3
|
-
let axios: IAceAxios | undefined;
|
|
4
|
-
|
|
5
|
-
export function useAxios() {
|
|
6
|
-
if (!axios) axios = createAxiosWithoutCache();
|
|
7
|
-
return axios;
|
|
8
|
-
}
|
|
1
|
+
import {createAxiosWithoutCache, type IAceAxios} from "@jari-ace/app-bolts";
|
|
2
|
+
|
|
3
|
+
let axios: IAceAxios | undefined;
|
|
4
|
+
|
|
5
|
+
export function useAxios() {
|
|
6
|
+
if (!axios) axios = createAxiosWithoutCache();
|
|
7
|
+
return axios;
|
|
8
|
+
}
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
import type {DirectiveBinding} from "vue";
|
|
2
|
-
import {useLoginUser} from "@jari-ace/app-bolts";
|
|
3
|
-
|
|
4
|
-
function disableOrHideElement(modifiers: any, el: HTMLElement) {
|
|
5
|
-
if (modifiers.disable) {
|
|
6
|
-
(el as any).disabled = true;
|
|
7
|
-
el.classList.add('disabled');
|
|
8
|
-
} else {
|
|
9
|
-
el.style.display = 'none';
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* v-auth指令用法:
|
|
15
|
-
* 默认如果用户有指定角色,就显示,否则隐藏:
|
|
16
|
-
* v-auth="role1"
|
|
17
|
-
* 支持多个角色检查,默认为并且关系,即要求用户拥有全部指定角色:
|
|
18
|
-
* 数组参数形式 v-auth="[role1, role2] 或者 字符串参数 v-auth="'role1-name,role2-name'"
|
|
19
|
-
* 也可以修改为拥有任一角色即可:
|
|
20
|
-
* v-auth.any="[role1, role2]"
|
|
21
|
-
* 如果要不隐藏只禁用:
|
|
22
|
-
* v-auth.disable="role1"
|
|
23
|
-
*/
|
|
24
|
-
export default {
|
|
25
|
-
// 当指令绑定到元素时调用
|
|
26
|
-
mounted(el: HTMLElement, binding: DirectiveBinding<string | string[] | undefined>) {
|
|
27
|
-
const user = useLoginUser();
|
|
28
|
-
const {value, modifiers} = binding;
|
|
29
|
-
const userPermissions = (typeof value === "string" ? value.split(/,/) : (value ?? []));
|
|
30
|
-
if (!userPermissions || userPermissions.length === 0) return;
|
|
31
|
-
if (modifiers.any) {
|
|
32
|
-
if (!userPermissions.some(p => user.hasRole(p))) {
|
|
33
|
-
disableOrHideElement(modifiers, el);
|
|
34
|
-
}
|
|
35
|
-
} else {
|
|
36
|
-
if (!userPermissions.every(p => user.hasRole(p))) {
|
|
37
|
-
disableOrHideElement(modifiers, el);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
1
|
+
import type {DirectiveBinding} from "vue";
|
|
2
|
+
import {useLoginUser} from "@jari-ace/app-bolts";
|
|
3
|
+
|
|
4
|
+
function disableOrHideElement(modifiers: any, el: HTMLElement) {
|
|
5
|
+
if (modifiers.disable) {
|
|
6
|
+
(el as any).disabled = true;
|
|
7
|
+
el.classList.add('disabled');
|
|
8
|
+
} else {
|
|
9
|
+
el.style.display = 'none';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* v-auth指令用法:
|
|
15
|
+
* 默认如果用户有指定角色,就显示,否则隐藏:
|
|
16
|
+
* v-auth="role1"
|
|
17
|
+
* 支持多个角色检查,默认为并且关系,即要求用户拥有全部指定角色:
|
|
18
|
+
* 数组参数形式 v-auth="[role1, role2] 或者 字符串参数 v-auth="'role1-name,role2-name'"
|
|
19
|
+
* 也可以修改为拥有任一角色即可:
|
|
20
|
+
* v-auth.any="[role1, role2]"
|
|
21
|
+
* 如果要不隐藏只禁用:
|
|
22
|
+
* v-auth.disable="role1"
|
|
23
|
+
*/
|
|
24
|
+
export default {
|
|
25
|
+
// 当指令绑定到元素时调用
|
|
26
|
+
mounted(el: HTMLElement, binding: DirectiveBinding<string | string[] | undefined>) {
|
|
27
|
+
const user = useLoginUser();
|
|
28
|
+
const {value, modifiers} = binding;
|
|
29
|
+
const userPermissions = (typeof value === "string" ? value.split(/,/) : (value ?? []));
|
|
30
|
+
if (!userPermissions || userPermissions.length === 0) return;
|
|
31
|
+
if (modifiers.any) {
|
|
32
|
+
if (!userPermissions.some(p => user.hasRole(p))) {
|
|
33
|
+
disableOrHideElement(modifiers, el);
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
if (!userPermissions.every(p => user.hasRole(p))) {
|
|
37
|
+
disableOrHideElement(modifiers, el);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 在组件mount后自动聚焦控件
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const timeoutHandles = new Map<HTMLElement, number>();
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
mounted(el: HTMLElement) {
|
|
9
|
-
let handle;
|
|
10
|
-
if (el instanceof HTMLInputElement) {
|
|
11
|
-
handle = setTimeout(() => el?.focus(), 500)
|
|
12
|
-
timeoutHandles.set(el, handle);
|
|
13
|
-
} else {
|
|
14
|
-
const el1 = el.querySelectorAll('input')
|
|
15
|
-
if (el1.length > 0 && el1.item(0) instanceof HTMLInputElement) {
|
|
16
|
-
handle = setTimeout(() => (
|
|
17
|
-
el1?.item(0) as HTMLInputElement
|
|
18
|
-
)?.focus(), 500)
|
|
19
|
-
timeoutHandles.set(el, handle)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
onUnmounted(el: HTMLElement) {
|
|
24
|
-
if (timeoutHandles.has(el)) {
|
|
25
|
-
clearTimeout(timeoutHandles.get(el))
|
|
26
|
-
timeoutHandles.delete(el)
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 在组件mount后自动聚焦控件
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const timeoutHandles = new Map<HTMLElement, number>();
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
mounted(el: HTMLElement) {
|
|
9
|
+
let handle;
|
|
10
|
+
if (el instanceof HTMLInputElement) {
|
|
11
|
+
handle = setTimeout(() => el?.focus(), 500)
|
|
12
|
+
timeoutHandles.set(el, handle);
|
|
13
|
+
} else {
|
|
14
|
+
const el1 = el.querySelectorAll('input')
|
|
15
|
+
if (el1.length > 0 && el1.item(0) instanceof HTMLInputElement) {
|
|
16
|
+
handle = setTimeout(() => (
|
|
17
|
+
el1?.item(0) as HTMLInputElement
|
|
18
|
+
)?.focus(), 500)
|
|
19
|
+
timeoutHandles.set(el, handle)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
onUnmounted(el: HTMLElement) {
|
|
24
|
+
if (timeoutHandles.has(el)) {
|
|
25
|
+
clearTimeout(timeoutHandles.get(el))
|
|
26
|
+
timeoutHandles.delete(el)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import autofocus from "./autofocus";
|
|
2
|
-
import shortcut from "./shortcut";
|
|
3
|
-
import auth from "./auth";
|
|
4
|
-
import type {App} from "vue";
|
|
5
|
-
|
|
6
|
-
export function installDirectives(app: App) {
|
|
7
|
-
app.directive('focus', autofocus)
|
|
8
|
-
app.directive('shortcut', shortcut)
|
|
9
|
-
app.directive('auth', auth)
|
|
10
|
-
}
|
|
1
|
+
import autofocus from "./autofocus";
|
|
2
|
+
import shortcut from "./shortcut";
|
|
3
|
+
import auth from "./auth";
|
|
4
|
+
import type {App} from "vue";
|
|
5
|
+
|
|
6
|
+
export function installDirectives(app: App) {
|
|
7
|
+
app.directive('focus', autofocus)
|
|
8
|
+
app.directive('shortcut', shortcut)
|
|
9
|
+
app.directive('auth', auth)
|
|
10
|
+
}
|
|
@@ -1,192 +1,192 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type DirectiveBinding,
|
|
3
|
-
type RendererElement,
|
|
4
|
-
type RendererNode,
|
|
5
|
-
type VNode
|
|
6
|
-
} from "vue";
|
|
7
|
-
|
|
8
|
-
function isValidShortcut(keys: string[]): boolean {
|
|
9
|
-
const validModifiers = ["Ctrl", "Alt", "Shift", "Meta"];
|
|
10
|
-
const validKeys = [
|
|
11
|
-
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
|
|
12
|
-
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
|
13
|
-
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "Tab",
|
|
14
|
-
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
|
|
15
|
-
"ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight",
|
|
16
|
-
"Enter", "Escape", "Space"
|
|
17
|
-
];
|
|
18
|
-
if (keys.length < 2) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
22
|
-
if (!validModifiers.includes(keys[i])) {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
const mainKey = keys[keys.length - 1];
|
|
27
|
-
return validKeys.includes(mainKey);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
type ShortCutCallback = (el: HTMLElement, binding: DirectiveBinding<ShortCutCallback>, vNode: VNode) => void;
|
|
31
|
-
|
|
32
|
-
let currentHandler: Record<string, ShortcutHandlerStackItem> = {};
|
|
33
|
-
|
|
34
|
-
function registerShortcut(binding: DirectiveBinding<ShortCutCallback>,
|
|
35
|
-
el: HTMLElement,
|
|
36
|
-
vNode: VNode<RendererNode, RendererElement, {
|
|
37
|
-
[p: string]: any
|
|
38
|
-
}>) {
|
|
39
|
-
const keys = binding.arg?.split('+') ?? [];
|
|
40
|
-
if (!keys || keys.length === 0) return;
|
|
41
|
-
if (isValidShortcut(keys)) {
|
|
42
|
-
if (el.__vueShortcutHandler__) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const handler = (event: KeyboardEvent) => {
|
|
46
|
-
let isMatch = true;
|
|
47
|
-
for (const key of keys) {
|
|
48
|
-
if (key === 'Ctrl' && !event.ctrlKey) isMatch = false;
|
|
49
|
-
if (key === 'Alt' && !event.altKey) isMatch = false;
|
|
50
|
-
if (key === 'Shift' && !event.shiftKey) isMatch = false;
|
|
51
|
-
if (key === 'Meta' && !event.metaKey) isMatch = false;
|
|
52
|
-
}
|
|
53
|
-
const mainKey = keys.length > 0 ? keys[keys.length - 1] : null;
|
|
54
|
-
if (event.key && mainKey && event.key.toUpperCase()
|
|
55
|
-
!== mainKey.toUpperCase()) isMatch = false;
|
|
56
|
-
let disabled = false;
|
|
57
|
-
if (vNode.component) {
|
|
58
|
-
disabled = vNode.component.props?.disabled as boolean
|
|
59
|
-
} else if (vNode.props) {
|
|
60
|
-
disabled = vNode.props.disabled as boolean
|
|
61
|
-
} else {
|
|
62
|
-
disabled = el.hasAttribute('disabled')
|
|
63
|
-
}
|
|
64
|
-
if (isMatch && !disabled) {
|
|
65
|
-
event.preventDefault();
|
|
66
|
-
if (binding.value) {
|
|
67
|
-
binding.value(el, binding, vNode)
|
|
68
|
-
} else {
|
|
69
|
-
el.focus();
|
|
70
|
-
el.click();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
doRegister({
|
|
75
|
-
keys: binding.arg,
|
|
76
|
-
handler,
|
|
77
|
-
el,
|
|
78
|
-
prev: currentHandler[binding.arg]
|
|
79
|
-
});
|
|
80
|
-
} else {
|
|
81
|
-
console.warn(`Invalid shortcut key combination: ${keys.join('+')}`);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function unregisterShortcut(el: HTMLElement) {
|
|
86
|
-
if (el.__vueShortcutHandler__) {
|
|
87
|
-
doUnregister(el.__vueShortcutHandler__);
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function doRegister(item: ShortcutHandlerStackItem) {
|
|
93
|
-
const current = item.prev;
|
|
94
|
-
const doc = (
|
|
95
|
-
window.rawWindow ?? window
|
|
96
|
-
).document;
|
|
97
|
-
if (current) {
|
|
98
|
-
doc.removeEventListener('keydown', current.handler);
|
|
99
|
-
}
|
|
100
|
-
doc.addEventListener('keydown', item.handler);
|
|
101
|
-
currentHandler[item.keys] = item;
|
|
102
|
-
item.el.__vueShortcutHandler__ = item;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function doUnregister(item: ShortcutHandlerStackItem) {
|
|
106
|
-
const current = currentHandler[item.keys];
|
|
107
|
-
if (current && current == item) {
|
|
108
|
-
const doc = (
|
|
109
|
-
window.rawWindow ?? window
|
|
110
|
-
).document;
|
|
111
|
-
doc.removeEventListener('keydown', item.handler);
|
|
112
|
-
if (item.prev) {
|
|
113
|
-
doc.addEventListener('keydown', item.prev.handler);
|
|
114
|
-
currentHandler[item.keys] = item.prev;
|
|
115
|
-
} else {
|
|
116
|
-
currentHandler[item.keys] = undefined;
|
|
117
|
-
}
|
|
118
|
-
} else if (current) {
|
|
119
|
-
//如果不是当前快捷键,就从栈链中移除
|
|
120
|
-
let p = current;
|
|
121
|
-
while (p && p.prev != item) {
|
|
122
|
-
p = p.prev;
|
|
123
|
-
}
|
|
124
|
-
if (p) {
|
|
125
|
-
p.prev = item.prev;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
if (item.prev) {
|
|
129
|
-
delete item.prev;
|
|
130
|
-
}
|
|
131
|
-
delete item.el.__vueShortcutHandler__;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// 判断元素是否可见的辅助函数
|
|
135
|
-
const isElementVisible = (el: HTMLElement) => {
|
|
136
|
-
// 检查元素或其父元素是否被隐藏
|
|
137
|
-
if (el.offsetParent === null) {
|
|
138
|
-
return false; // 如果 offsetParent 为 null,说明元素或其父元素被隐藏
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// 检查元素是否在视口内
|
|
142
|
-
const rect = el.getBoundingClientRect();
|
|
143
|
-
const win = window.rawWindow ?? window;
|
|
144
|
-
return (
|
|
145
|
-
rect.top <= win.innerHeight &&
|
|
146
|
-
rect.bottom >= 0 &&
|
|
147
|
-
rect.left <= win.innerWidth &&
|
|
148
|
-
rect.right >= 0
|
|
149
|
-
);
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
// 配置 Intersection Observer
|
|
153
|
-
const observerOption = {
|
|
154
|
-
root: null, // 默认为视口
|
|
155
|
-
rootMargin: '0px',
|
|
156
|
-
threshold: 0.1, // 当 10% 的元素可见时触发
|
|
157
|
-
};
|
|
158
|
-
/**
|
|
159
|
-
* 支持对元素标签点击事件添加快捷键触发,完整的写法:
|
|
160
|
-
* <div v-shortcut:Alt+N="() => doClick()"></div>
|
|
161
|
-
* 如果元素已经定义了click事件,那么可以简写为
|
|
162
|
-
* <div v-shortcut:Alt+N @click="doClick"><div>
|
|
163
|
-
*/
|
|
164
|
-
export default {
|
|
165
|
-
mounted(el: HTMLElement, binding: DirectiveBinding<ShortCutCallback>, vNode: VNode) {
|
|
166
|
-
// 如果元素已经可见,直接注册快捷键
|
|
167
|
-
if (isElementVisible(el)) {
|
|
168
|
-
registerShortcut(binding, el, vNode);
|
|
169
|
-
}
|
|
170
|
-
// 回调函数,处理可见性变化
|
|
171
|
-
const callback = (entries) => {
|
|
172
|
-
entries.forEach((entry) => {
|
|
173
|
-
if (entry.isIntersecting) {
|
|
174
|
-
// 元素可见时触发
|
|
175
|
-
registerShortcut(binding, el, vNode);
|
|
176
|
-
} else {
|
|
177
|
-
// 元素不可见时触发
|
|
178
|
-
unregisterShortcut(el);
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
};
|
|
182
|
-
// 创建观察器
|
|
183
|
-
const observer = new IntersectionObserver(callback, observerOption);
|
|
184
|
-
el.__visibilityObserver__ = observer; // 将观察器挂载到元素上,便于卸载时使用
|
|
185
|
-
observer.observe(el); // 开始观察
|
|
186
|
-
},
|
|
187
|
-
unmounted(el: HTMLElement) {
|
|
188
|
-
el.__visibilityObserver__.disconnect();
|
|
189
|
-
delete el.__visibilityObserver__;
|
|
190
|
-
unregisterShortcut(el);
|
|
191
|
-
}
|
|
192
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
type DirectiveBinding,
|
|
3
|
+
type RendererElement,
|
|
4
|
+
type RendererNode,
|
|
5
|
+
type VNode
|
|
6
|
+
} from "vue";
|
|
7
|
+
|
|
8
|
+
function isValidShortcut(keys: string[]): boolean {
|
|
9
|
+
const validModifiers = ["Ctrl", "Alt", "Shift", "Meta"];
|
|
10
|
+
const validKeys = [
|
|
11
|
+
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
|
|
12
|
+
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
|
13
|
+
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "Tab",
|
|
14
|
+
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
|
|
15
|
+
"ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight",
|
|
16
|
+
"Enter", "Escape", "Space"
|
|
17
|
+
];
|
|
18
|
+
if (keys.length < 2) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
22
|
+
if (!validModifiers.includes(keys[i])) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const mainKey = keys[keys.length - 1];
|
|
27
|
+
return validKeys.includes(mainKey);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type ShortCutCallback = (el: HTMLElement, binding: DirectiveBinding<ShortCutCallback>, vNode: VNode) => void;
|
|
31
|
+
|
|
32
|
+
let currentHandler: Record<string, ShortcutHandlerStackItem> = {};
|
|
33
|
+
|
|
34
|
+
function registerShortcut(binding: DirectiveBinding<ShortCutCallback>,
|
|
35
|
+
el: HTMLElement,
|
|
36
|
+
vNode: VNode<RendererNode, RendererElement, {
|
|
37
|
+
[p: string]: any
|
|
38
|
+
}>) {
|
|
39
|
+
const keys = binding.arg?.split('+') ?? [];
|
|
40
|
+
if (!keys || keys.length === 0) return;
|
|
41
|
+
if (isValidShortcut(keys)) {
|
|
42
|
+
if (el.__vueShortcutHandler__) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const handler = (event: KeyboardEvent) => {
|
|
46
|
+
let isMatch = true;
|
|
47
|
+
for (const key of keys) {
|
|
48
|
+
if (key === 'Ctrl' && !event.ctrlKey) isMatch = false;
|
|
49
|
+
if (key === 'Alt' && !event.altKey) isMatch = false;
|
|
50
|
+
if (key === 'Shift' && !event.shiftKey) isMatch = false;
|
|
51
|
+
if (key === 'Meta' && !event.metaKey) isMatch = false;
|
|
52
|
+
}
|
|
53
|
+
const mainKey = keys.length > 0 ? keys[keys.length - 1] : null;
|
|
54
|
+
if (event.key && mainKey && event.key.toUpperCase()
|
|
55
|
+
!== mainKey.toUpperCase()) isMatch = false;
|
|
56
|
+
let disabled = false;
|
|
57
|
+
if (vNode.component) {
|
|
58
|
+
disabled = vNode.component.props?.disabled as boolean
|
|
59
|
+
} else if (vNode.props) {
|
|
60
|
+
disabled = vNode.props.disabled as boolean
|
|
61
|
+
} else {
|
|
62
|
+
disabled = el.hasAttribute('disabled')
|
|
63
|
+
}
|
|
64
|
+
if (isMatch && !disabled) {
|
|
65
|
+
event.preventDefault();
|
|
66
|
+
if (binding.value) {
|
|
67
|
+
binding.value(el, binding, vNode)
|
|
68
|
+
} else {
|
|
69
|
+
el.focus();
|
|
70
|
+
el.click();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
doRegister({
|
|
75
|
+
keys: binding.arg,
|
|
76
|
+
handler,
|
|
77
|
+
el,
|
|
78
|
+
prev: currentHandler[binding.arg]
|
|
79
|
+
});
|
|
80
|
+
} else {
|
|
81
|
+
console.warn(`Invalid shortcut key combination: ${keys.join('+')}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function unregisterShortcut(el: HTMLElement) {
|
|
86
|
+
if (el.__vueShortcutHandler__) {
|
|
87
|
+
doUnregister(el.__vueShortcutHandler__);
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function doRegister(item: ShortcutHandlerStackItem) {
|
|
93
|
+
const current = item.prev;
|
|
94
|
+
const doc = (
|
|
95
|
+
window.rawWindow ?? window
|
|
96
|
+
).document;
|
|
97
|
+
if (current) {
|
|
98
|
+
doc.removeEventListener('keydown', current.handler);
|
|
99
|
+
}
|
|
100
|
+
doc.addEventListener('keydown', item.handler);
|
|
101
|
+
currentHandler[item.keys] = item;
|
|
102
|
+
item.el.__vueShortcutHandler__ = item;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function doUnregister(item: ShortcutHandlerStackItem) {
|
|
106
|
+
const current = currentHandler[item.keys];
|
|
107
|
+
if (current && current == item) {
|
|
108
|
+
const doc = (
|
|
109
|
+
window.rawWindow ?? window
|
|
110
|
+
).document;
|
|
111
|
+
doc.removeEventListener('keydown', item.handler);
|
|
112
|
+
if (item.prev) {
|
|
113
|
+
doc.addEventListener('keydown', item.prev.handler);
|
|
114
|
+
currentHandler[item.keys] = item.prev;
|
|
115
|
+
} else {
|
|
116
|
+
currentHandler[item.keys] = undefined;
|
|
117
|
+
}
|
|
118
|
+
} else if (current) {
|
|
119
|
+
//如果不是当前快捷键,就从栈链中移除
|
|
120
|
+
let p = current;
|
|
121
|
+
while (p && p.prev != item) {
|
|
122
|
+
p = p.prev;
|
|
123
|
+
}
|
|
124
|
+
if (p) {
|
|
125
|
+
p.prev = item.prev;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (item.prev) {
|
|
129
|
+
delete item.prev;
|
|
130
|
+
}
|
|
131
|
+
delete item.el.__vueShortcutHandler__;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 判断元素是否可见的辅助函数
|
|
135
|
+
const isElementVisible = (el: HTMLElement) => {
|
|
136
|
+
// 检查元素或其父元素是否被隐藏
|
|
137
|
+
if (el.offsetParent === null) {
|
|
138
|
+
return false; // 如果 offsetParent 为 null,说明元素或其父元素被隐藏
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 检查元素是否在视口内
|
|
142
|
+
const rect = el.getBoundingClientRect();
|
|
143
|
+
const win = window.rawWindow ?? window;
|
|
144
|
+
return (
|
|
145
|
+
rect.top <= win.innerHeight &&
|
|
146
|
+
rect.bottom >= 0 &&
|
|
147
|
+
rect.left <= win.innerWidth &&
|
|
148
|
+
rect.right >= 0
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// 配置 Intersection Observer
|
|
153
|
+
const observerOption = {
|
|
154
|
+
root: null, // 默认为视口
|
|
155
|
+
rootMargin: '0px',
|
|
156
|
+
threshold: 0.1, // 当 10% 的元素可见时触发
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* 支持对元素标签点击事件添加快捷键触发,完整的写法:
|
|
160
|
+
* <div v-shortcut:Alt+N="() => doClick()"></div>
|
|
161
|
+
* 如果元素已经定义了click事件,那么可以简写为
|
|
162
|
+
* <div v-shortcut:Alt+N @click="doClick"><div>
|
|
163
|
+
*/
|
|
164
|
+
export default {
|
|
165
|
+
mounted(el: HTMLElement, binding: DirectiveBinding<ShortCutCallback>, vNode: VNode) {
|
|
166
|
+
// 如果元素已经可见,直接注册快捷键
|
|
167
|
+
if (isElementVisible(el)) {
|
|
168
|
+
registerShortcut(binding, el, vNode);
|
|
169
|
+
}
|
|
170
|
+
// 回调函数,处理可见性变化
|
|
171
|
+
const callback = (entries) => {
|
|
172
|
+
entries.forEach((entry) => {
|
|
173
|
+
if (entry.isIntersecting) {
|
|
174
|
+
// 元素可见时触发
|
|
175
|
+
registerShortcut(binding, el, vNode);
|
|
176
|
+
} else {
|
|
177
|
+
// 元素不可见时触发
|
|
178
|
+
unregisterShortcut(el);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
// 创建观察器
|
|
183
|
+
const observer = new IntersectionObserver(callback, observerOption);
|
|
184
|
+
el.__visibilityObserver__ = observer; // 将观察器挂载到元素上,便于卸载时使用
|
|
185
|
+
observer.observe(el); // 开始观察
|
|
186
|
+
},
|
|
187
|
+
unmounted(el: HTMLElement) {
|
|
188
|
+
el.__visibilityObserver__.disconnect();
|
|
189
|
+
delete el.__visibilityObserver__;
|
|
190
|
+
unregisterShortcut(el);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import {type AppInstance, createAxiosWithoutCache, useAppApi} from "@jari-ace/app-bolts";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
let appCache: AppInstance[] = [];
|
|
5
|
-
|
|
6
|
-
export async function useAppInstances() {
|
|
7
|
-
const axios = createAxiosWithoutCache()
|
|
8
|
-
const api = useAppApi(axios)
|
|
9
|
-
if (appCache.length === 0) {
|
|
10
|
-
appCache = await api.getAll(true);
|
|
11
|
-
}
|
|
12
|
-
return {
|
|
13
|
-
async getById(appId: string) {
|
|
14
|
-
let app = appCache.find(a => a.id === appId);
|
|
15
|
-
if (!app) {
|
|
16
|
-
app = await api.getById(appId);
|
|
17
|
-
if (app) {
|
|
18
|
-
appCache.push(app);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return app;
|
|
22
|
-
},
|
|
23
|
-
async getByName(appName: string) {
|
|
24
|
-
let app = appCache.find(a => a.name === appName);
|
|
25
|
-
if (!app) {
|
|
26
|
-
app = await api.getByName(appName);
|
|
27
|
-
if (app) {
|
|
28
|
-
appCache.push(app);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return app;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
1
|
+
import {type AppInstance, createAxiosWithoutCache, useAppApi} from "@jari-ace/app-bolts";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
let appCache: AppInstance[] = [];
|
|
5
|
+
|
|
6
|
+
export async function useAppInstances() {
|
|
7
|
+
const axios = createAxiosWithoutCache()
|
|
8
|
+
const api = useAppApi(axios)
|
|
9
|
+
if (appCache.length === 0) {
|
|
10
|
+
appCache = await api.getAll(true);
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
async getById(appId: string) {
|
|
14
|
+
let app = appCache.find(a => a.id === appId);
|
|
15
|
+
if (!app) {
|
|
16
|
+
app = await api.getById(appId);
|
|
17
|
+
if (app) {
|
|
18
|
+
appCache.push(app);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return app;
|
|
22
|
+
},
|
|
23
|
+
async getByName(appName: string) {
|
|
24
|
+
let app = appCache.find(a => a.name === appName);
|
|
25
|
+
if (!app) {
|
|
26
|
+
app = await api.getByName(appName);
|
|
27
|
+
if (app) {
|
|
28
|
+
appCache.push(app);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return app;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|