@ctzy-web-client/plugin-component-vue 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/package.json +43 -0
  2. package/src/advance-select/advance-operation.vue +44 -0
  3. package/src/advance-select/advance-option.vue +115 -0
  4. package/src/advance-select/advance-select.vue +343 -0
  5. package/src/advance-select/events-helpers.js +40 -0
  6. package/src/advance-select/index.js +13 -0
  7. package/src/advance-select/use-advance-option.js +58 -0
  8. package/src/advance-select/use-advance-select.js +142 -0
  9. package/src/application-slot/application-slot.js +70 -0
  10. package/src/application-slot/breadcrumb-item.vue +12 -0
  11. package/src/application-slot/header-tools-item.vue +12 -0
  12. package/src/application-slot/index.js +17 -0
  13. package/src/breadcrumb-select/breadcrumb-select.vue +97 -0
  14. package/src/breadcrumb-select/index.js +6 -0
  15. package/src/components.js +39 -0
  16. package/src/contextmenu/contextmenu-item.vue +13 -0
  17. package/src/contextmenu/contextmenu.vue +56 -0
  18. package/src/contextmenu/index.js +11 -0
  19. package/src/contextmenu/use-contextmenu.js +117 -0
  20. package/src/data-form/data-form-item.vue +49 -0
  21. package/src/data-form/data-form.vue +212 -0
  22. package/src/data-form/dynamic-component.js +24 -0
  23. package/src/data-form/form-components/Blots/AtBlot.js +32 -0
  24. package/src/data-form/form-components/bwa-date-picker.vue +43 -0
  25. package/src/data-form/form-components/bwa-date-time-picker.vue +49 -0
  26. package/src/data-form/form-components/bwa-input-float.vue +41 -0
  27. package/src/data-form/form-components/bwa-input-integer.vue +58 -0
  28. package/src/data-form/form-components/bwa-input.vue +32 -0
  29. package/src/data-form/form-components/bwa-multi-select.vue +27 -0
  30. package/src/data-form/form-components/bwa-rich-text-tinymce.vue +561 -0
  31. package/src/data-form/form-components/bwa-rich-text.vue +395 -0
  32. package/src/data-form/form-components/bwa-select.vue +67 -0
  33. package/src/data-form/form-components/bwa-textarea.vue +28 -0
  34. package/src/data-form/form-components/bwa-upload.vue +145 -0
  35. package/src/data-form/form-components/bwa-user-multi-select.vue +25 -0
  36. package/src/data-form/form-components/bwa-user-select.vue +81 -0
  37. package/src/data-form/index.js +35 -0
  38. package/src/data-table/data-column-view.vue +131 -0
  39. package/src/data-table/data-table-card.vue +81 -0
  40. package/src/data-table/data-table-column.vue +52 -0
  41. package/src/data-table/data-table.vue +426 -0
  42. package/src/data-table/dynamic-component.js +58 -0
  43. package/src/data-table/index.js +13 -0
  44. package/src/data-table/use-datatable-drag.js +156 -0
  45. package/src/datatable-settings/datatable-settings.vue +323 -0
  46. package/src/datatable-settings/index.js +6 -0
  47. package/src/date-range/date-picker.vue +115 -0
  48. package/src/date-range/date-range.vue +202 -0
  49. package/src/date-range/index.js +6 -0
  50. package/src/drag-list/constants.js +1 -0
  51. package/src/drag-list/drag-item.vue +46 -0
  52. package/src/drag-list/drag-list.vue +50 -0
  53. package/src/drag-list/index.js +6 -0
  54. package/src/drag-list/use-drag-list.js +209 -0
  55. package/src/dragable/constants.js +3 -0
  56. package/src/dragable/dragable-item.vue +19 -0
  57. package/src/dragable/dragable-operation.vue +28 -0
  58. package/src/dragable/dragable.vue +26 -0
  59. package/src/dragable/index.js +14 -0
  60. package/src/dragable/use-dragable.js +227 -0
  61. package/src/filter-panel/conditions/condition.js +35 -0
  62. package/src/filter-panel/conditions/date-range-condition.vue +35 -0
  63. package/src/filter-panel/conditions/department-condition/data.json +29537 -0
  64. package/src/filter-panel/conditions/department-condition/department-condition.vue +92 -0
  65. package/src/filter-panel/conditions/department-condition/department-node.vue +52 -0
  66. package/src/filter-panel/conditions/index.js +22 -0
  67. package/src/filter-panel/conditions/input-condition.vue +63 -0
  68. package/src/filter-panel/conditions/multi-user-condition.vue +56 -0
  69. package/src/filter-panel/conditions/multiple-menu-condition.vue +45 -0
  70. package/src/filter-panel/conditions/single-menu-condition.vue +58 -0
  71. package/src/filter-panel/conditions/single-user-condition.vue +56 -0
  72. package/src/filter-panel/filter-panel-item.vue +46 -0
  73. package/src/filter-panel/filter-panel.vue +149 -0
  74. package/src/filter-panel/index.js +17 -0
  75. package/src/filter-panel/use-filter-panel-item.js +59 -0
  76. package/src/filter-panel/use-filter-panel.js +203 -0
  77. package/src/hooks/use-data/index.js +234 -0
  78. package/src/index.js +48 -0
  79. package/src/layout/index.js +6 -0
  80. package/src/layout/layout.vue +74 -0
  81. package/src/make-installer.js +36 -0
  82. package/src/math/Rectangle.js +28 -0
  83. package/src/menu/index.js +6 -0
  84. package/src/menu/menu-item.vue +41 -0
  85. package/src/menu/menu.vue +53 -0
  86. package/src/panel/index.js +6 -0
  87. package/src/panel/panel.vue +42 -0
  88. package/src/panel-tabs/index.js +6 -0
  89. package/src/panel-tabs/panel-tabs.js +92 -0
  90. package/src/pct-filter-panel/index.js +10 -0
  91. package/src/pct-filter-panel/pct-compents/index.js +10 -0
  92. package/src/pct-filter-panel/pct-compents/pct-Input-condition.vue +63 -0
  93. package/src/pct-filter-panel/pct-compents/pct-date-range-condition.vue +60 -0
  94. package/src/pct-filter-panel/pct-compents/pct-multiple-menu-condition.vue +177 -0
  95. package/src/pct-filter-panel/pct-compents/pct-multiple-menu-condition2.vue +142 -0
  96. package/src/pct-filter-panel/pct-filter-panel-item.vue +46 -0
  97. package/src/pct-filter-panel/pct-filter-panel.vue +201 -0
  98. package/src/pct-filter-panel/use-filter-panel-item.js +61 -0
  99. package/src/pct-filter-panel/use-filter-panel.js +206 -0
  100. package/src/plugins.js +3 -0
  101. package/src/progress/index.js +8 -0
  102. package/src/progress/progress-item.vue +81 -0
  103. package/src/progress/progress.vue +58 -0
  104. package/src/progress/use-progress.js +66 -0
  105. package/src/utils/db.js +8 -0
  106. package/src/utils.js +263 -0
  107. package/src/where-filter-panel/index.js +0 -0
  108. package/src/where-filter-panel/use-where-filter-panel.js +28 -0
  109. package/src/where-filter-panel/where-filter-panel.vue +9 -0
  110. package/style/advance-select.scss +316 -0
  111. package/style/breadcrumb-select.scss +80 -0
  112. package/style/common/var.scss +240 -0
  113. package/style/common.scss +48 -0
  114. package/style/contextmenu.scss +58 -0
  115. package/style/data-form.scss +35 -0
  116. package/style/data-table.scss +81 -0
  117. package/style/datatable-settings.scss +125 -0
  118. package/style/date-range.scss +136 -0
  119. package/style/department-condition.scss +39 -0
  120. package/style/drag-list.scss +68 -0
  121. package/style/dragable.scss +8 -0
  122. package/style/filter-panel.scss +199 -0
  123. package/style/index.scss +22 -0
  124. package/style/input-condition.scss +30 -0
  125. package/style/layout.scss +70 -0
  126. package/style/menu.scss +184 -0
  127. package/style/mixins/_var.scss +21 -0
  128. package/style/mixins/config.scss +4 -0
  129. package/style/mixins/function.scss +62 -0
  130. package/style/mixins/mixins.scss +88 -0
  131. package/style/panel-tabs.scss +60 -0
  132. package/style/panel.scss +110 -0
  133. package/style/pct-filter-panel.scss +306 -0
  134. package/style/progress.scss +122 -0
  135. package/style/rich-text.scss +30 -0
  136. package/style/theme/theme.scss +161 -0
  137. package/style/theme/var.scss +34 -0
  138. package/style/var.scss +21 -0
@@ -0,0 +1,142 @@
1
+ import { computed, reactive, unref, watch } from 'vue';
2
+ import { debounce } from 'lodash';
3
+
4
+ export const useAdvanceSelectStates = (props) => {
5
+ return reactive({
6
+ options: new Map(),
7
+ cachedOptions: new Map(),
8
+ optionsCount: 0,
9
+ selected: props.multiple ? [] : {},
10
+ search: '',
11
+ isShowPopper: false,
12
+ });
13
+ };
14
+
15
+ export const useAdvanceSelect = (props, states, ctx) => {
16
+ const cachedOptions = computed(() =>
17
+ Array.from(states.cachedOptions.values())
18
+ );
19
+
20
+ watch(
21
+ computed(() => states.isShowPopper),
22
+ (isShowPopper) => {
23
+ if (!isShowPopper) {
24
+ states.search = '';
25
+ }
26
+ }
27
+ );
28
+
29
+ watch(
30
+ () => props.modelValue,
31
+ () => {
32
+ setSelected();
33
+ },
34
+ { flush: 'post', deep: true }
35
+ );
36
+
37
+ const selectedLabel = computed(() => {
38
+ return props.multiple
39
+ ? states.selected.map((selected) => selected.label)
40
+ : states.selected.label || props.modelValue;
41
+ });
42
+
43
+ const getOption = (value) => {
44
+ let option = null;
45
+ for (const item of cachedOptions.value) {
46
+ if (item.value === value) {
47
+ option = {
48
+ value,
49
+ label: item.currentLabel,
50
+ };
51
+ break;
52
+ }
53
+ }
54
+
55
+ if (option) {
56
+ return option;
57
+ }
58
+
59
+ return { value, label: value };
60
+ };
61
+
62
+ const setSelected = () => {
63
+ if (!props.multiple) {
64
+ const option = getOption(props.modelValue);
65
+ states.selected = option;
66
+ return;
67
+ }
68
+ const result = [];
69
+ if (Array.isArray(props.modelValue)) {
70
+ props.modelValue.forEach((value) => {
71
+ result.push(getOption(value));
72
+ });
73
+ }
74
+ states.selected = result;
75
+ };
76
+
77
+ const onOptionCreate = (option) => {
78
+ states.optionsCount++;
79
+ states.options.set(option.value, option);
80
+ states.cachedOptions.set(option.value, option);
81
+ };
82
+
83
+ const onOptionDestroy = (key, option) => {
84
+ if (states.options.get(key) === option) {
85
+ states.optionsCount--;
86
+ states.options.delete(key);
87
+ }
88
+ };
89
+
90
+ const handleClearClick = () => {
91
+ ctx.emit('update:modelValue', props.multiple ? [] : '');
92
+ if (props.closeAfterSelection) {
93
+ states.isShowPopper = false;
94
+ }
95
+ };
96
+
97
+ const handleOptionSelect = (option) => {
98
+ if (props.multiple) {
99
+ const value = (props.modelValue || []).slice();
100
+ const optionIndex = value.indexOf(option.value);
101
+ if (optionIndex > -1) {
102
+ if (props.required && value.length === 1) {
103
+ return;
104
+ }
105
+
106
+ value.splice(optionIndex, 1);
107
+ } else if (
108
+ props.multipleLimit <= 0 ||
109
+ value.length < props.multipleLimit
110
+ ) {
111
+ value.push(option.value);
112
+ }
113
+ ctx.emit('update:modelValue', value);
114
+ if (props.closeAfterSelection) {
115
+ states.isShowPopper = false;
116
+ }
117
+ } else {
118
+ ctx.emit('update:modelValue', option.value);
119
+ states.isShowPopper = false;
120
+ }
121
+ };
122
+
123
+ const hidePoppper = () => {
124
+ states.isShowPopper = false;
125
+ };
126
+
127
+ watch(
128
+ computed(() => states.options.entries()),
129
+ () => {
130
+ setSelected();
131
+ }
132
+ );
133
+
134
+ return {
135
+ selectedLabel,
136
+ onOptionCreate,
137
+ onOptionDestroy,
138
+ handleClearClick,
139
+ handleOptionSelect,
140
+ hidePoppper,
141
+ };
142
+ };
@@ -0,0 +1,70 @@
1
+ import {
2
+ Fragment,
3
+ h,
4
+ onBeforeUnmount,
5
+ onMounted,
6
+ render,
7
+ useSlots,
8
+ effectScope,
9
+ effect,
10
+ } from 'vue';
11
+ import { useGlobalConfig, applicationKey } from 'web-base-client-vue';
12
+
13
+ let uuid = 1;
14
+
15
+ const ApplicationSlot = {
16
+ name: 'BwaApplicationSlot',
17
+ props: {
18
+ type: String,
19
+ },
20
+ setup(props) {
21
+ let currentUuid = uuid++;
22
+
23
+ const slots = useSlots();
24
+
25
+ const application = useGlobalConfig(applicationKey);
26
+
27
+ const scope = effectScope();
28
+
29
+ let container = null;
30
+
31
+ onMounted(() => {
32
+ container = document.createElement('div');
33
+
34
+ scope.run(() => {
35
+ effect(() => {
36
+ const vnodes = slots.default?.();
37
+ let _vnodes = [...vnodes];
38
+
39
+ for (let i = 0; i < _vnodes.length; i++) {
40
+ const vnode = _vnodes[i];
41
+
42
+ vnode.appContext = ApplicationSlot._context;
43
+
44
+ if (Array.isArray(vnode.children)) {
45
+ _vnodes = _vnodes.concat(vnode.children);
46
+ }
47
+ }
48
+
49
+ const vnode = h(Fragment, vnodes);
50
+ vnode.appContext = ApplicationSlot._context;
51
+
52
+ render(vnode, container);
53
+ });
54
+ });
55
+
56
+ application.value.addApplicationSlot(props.type, currentUuid, container);
57
+ });
58
+
59
+ onBeforeUnmount(() => {
60
+ application.value.removeApplicationSlot(props.type, currentUuid);
61
+ render(null, container);
62
+ container = null;
63
+ scope.stop();
64
+ });
65
+
66
+ return () => h('i', { style: { display: 'none' } });
67
+ },
68
+ };
69
+
70
+ export default ApplicationSlot;
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <ApplicationSlot type="breadcrumbItem">
3
+ <slot></slot>
4
+ </ApplicationSlot>
5
+ </template>
6
+
7
+ <script setup>
8
+ import ApplicationSlot from './application-slot';
9
+ defineOptions({
10
+ name: 'BwaBreadcrumbItem',
11
+ });
12
+ </script>
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <ApplicationSlot type="headerToolItem">
3
+ <slot></slot>
4
+ </ApplicationSlot>
5
+ </template>
6
+
7
+ <script setup>
8
+ import ApplicationSlot from './application-slot';
9
+ defineOptions({
10
+ name: 'BwaHeaderToolsItem',
11
+ });
12
+ </script>
@@ -0,0 +1,17 @@
1
+ import { withInstall } from 'element-plus/es/utils/vue/install';
2
+ import ApplicationSlot from './application-slot.js';
3
+ import BreadcrumbItem from './breadcrumb-item.vue';
4
+ import HeaderToolsItem from './header-tools-item.vue';
5
+
6
+ ApplicationSlot.install = (app) => {
7
+ ApplicationSlot._context = app._context;
8
+ app.component(ApplicationSlot.name, ApplicationSlot);
9
+ app.component(BreadcrumbItem.name, BreadcrumbItem);
10
+ app.component(HeaderToolsItem.name, HeaderToolsItem);
11
+ };
12
+
13
+ export const BwaApplicationSlot = ApplicationSlot;
14
+ export const BwaBreadcrumbItem = withInstall(BreadcrumbItem);
15
+ export const BwaHeaderToolsItem = withInstall(HeaderToolsItem);
16
+
17
+ export default BwaApplicationSlot;
@@ -0,0 +1,97 @@
1
+ <template>
2
+ <BwaAdvanceSelect
3
+ v-bind="attrs"
4
+ :showSelection="false"
5
+ :search-placeholder="searchPlaceholder"
6
+ :multiple="false"
7
+ >
8
+ <template #contentTop v-if="recentEmptyDesc">
9
+ <div :class="ns.be('item', 'top')">
10
+ <slot name="recent">
11
+ <div :class="ns.be('item', 'top-empty')">{{ recentEmptyDesc }}</div>
12
+ </slot>
13
+ </div>
14
+ </template>
15
+
16
+ <template #contentBottom>
17
+ <AdvanceOperation v-if="showAll" :class="ns.be('item', 'opt')" @click="emit('all')">
18
+ <i class="ptp-caozuo-chakan ptp-icon"></i>
19
+ <span :class="ns.be('item', 'opt-label')">{{ allDesc }}</span>
20
+ </AdvanceOperation>
21
+ <AdvanceOperation v-if="showMine" :class="ns.be('item', 'opt')" @click="emit('mine')">
22
+ <i class="ptp-caozuo-chakan ptp-icon"></i>
23
+ <span :class="ns.be('item', 'opt-label')">{{ allMine }}</span>
24
+ </AdvanceOperation>
25
+ <AdvanceOperation v-if="showSave" :class="ns.be('item', 'opt')" @click="emit('save')">
26
+ <ElIcon><CirclePlus /></ElIcon>
27
+ <span :class="ns.be('item', 'opt-label')">{{ saveDesc }}</span>
28
+ </AdvanceOperation>
29
+ </template>
30
+ <slot></slot>
31
+
32
+ <template #reference="{ label }">
33
+ <ElButton :class="ns.be('item', 'dropdown')">
34
+ <i class="ptp-qiehuan ptp-icon"></i>
35
+ <span :class="ns.be('item', 'content')">
36
+ {{ label || defaultLabel }}
37
+ </span>
38
+ <ElIcon><ArrowDown /></ElIcon>
39
+ </ElButton>
40
+ </template>
41
+ </BwaAdvanceSelect>
42
+ </template>
43
+
44
+ <script setup>
45
+ import { ElButton, ElIcon } from 'element-plus';
46
+ import { useAttrs } from 'vue';
47
+ import { useNamespace } from 'web-base-client-vue';
48
+ import BwaAdvanceSelect from '../advance-select';
49
+ import AdvanceOperation from '../advance-select/advance-operation.vue';
50
+
51
+ defineOptions({ name: 'BwaBreadcrumbSelect' });
52
+
53
+ const props = defineProps({
54
+ defaultLabel: {
55
+ type: String,
56
+ default: '请选择',
57
+ },
58
+ recentEmptyDesc: {
59
+ type: String,
60
+ default: '最近访问项目',
61
+ },
62
+ searchPlaceholder: {
63
+ type: String,
64
+ default: '项目名称',
65
+ },
66
+ allDesc: {
67
+ type: String,
68
+ default: '全部项目',
69
+ },
70
+ allMine: {
71
+ type: String,
72
+ default: '我的项目',
73
+ },
74
+ saveDesc: {
75
+ type: String,
76
+ default: '新增项目',
77
+ },
78
+ showSave: {
79
+ type: Boolean,
80
+ default: true,
81
+ },
82
+ showMine: {
83
+ type: Boolean,
84
+ default: false,
85
+ },
86
+ showAll: {
87
+ type: Boolean,
88
+ default: true
89
+ }
90
+ });
91
+
92
+ const emit = defineEmits(['all','mine', 'save']);
93
+
94
+ const attrs = useAttrs();
95
+
96
+ const ns = useNamespace('breadcrumb');
97
+ </script>
@@ -0,0 +1,6 @@
1
+ import { withInstall } from 'element-plus/es/utils/vue/install';
2
+ import BreadcrumbSelect from './breadcrumb-select.vue';
3
+
4
+ export const BwaBreadcrumbSelect = withInstall(BreadcrumbSelect);
5
+
6
+ export default BwaBreadcrumbSelect;
@@ -0,0 +1,39 @@
1
+ import { BwaDataForm } from './data-form';
2
+ import { BwaDataTable } from './data-table';
3
+ import { BwaFilterPanel, BwaCondition } from './filter-panel';
4
+ import { BwaAdvanceSelect } from './advance-select';
5
+ import { BwaDateRange } from './date-range';
6
+ import { BwaApplicationSlot } from './application-slot';
7
+ import { BwaLayout } from './layout';
8
+ import { BwaMenu } from './menu';
9
+ import { BwaPanel } from './panel';
10
+ import { BwaPanelTab } from './panel-tabs';
11
+ import { BwaBreadcrumbSelect } from './breadcrumb-select';
12
+ import { BwaDataTableSetting } from './datatable-settings';
13
+ import { BwaDraglist } from './drag-list';
14
+ import { BwaProgress } from './progress';
15
+ import { BwaDragable } from './dragable';
16
+ import { BwaPctFilterPanel } from './pct-filter-panel';
17
+ import { BwaPctMultipleMenuCondition, BwaPctInputCondition, BwaPctDateRangeCondition } from './pct-filter-panel/pct-compents'
18
+ export default [
19
+ BwaDataForm,
20
+ BwaDataTable,
21
+ BwaFilterPanel,
22
+ BwaAdvanceSelect,
23
+ BwaDateRange,
24
+ BwaCondition,
25
+ BwaApplicationSlot,
26
+ BwaLayout,
27
+ BwaMenu,
28
+ BwaPanel,
29
+ BwaPanelTab,
30
+ BwaBreadcrumbSelect,
31
+ BwaDataTableSetting,
32
+ BwaDraglist,
33
+ BwaProgress,
34
+ BwaDragable,
35
+ BwaPctFilterPanel,
36
+ BwaPctMultipleMenuCondition,
37
+ BwaPctInputCondition,
38
+ BwaPctDateRangeCondition
39
+ ];
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <div :class="ns.b()">
3
+ <slot></slot>
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+ import { useNamespace } from 'web-base-client-vue';
9
+
10
+ defineOptions({ name: 'BwaContextmenuItem' });
11
+
12
+ const ns = useNamespace('contextmenu-item');
13
+ </script>
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <div :class="ns.b()">
3
+ <ElScrollbar max-height="400px" ref="scrollbarRef">
4
+ <div
5
+ v-for="menu in menus"
6
+ @click="clickHandle(menu)"
7
+ :key="menu.id"
8
+ :class="ns.b('item')"
9
+ >
10
+ {{ menu.label }}
11
+ </div>
12
+ </ElScrollbar>
13
+ </div>
14
+ </template>
15
+
16
+ <script setup>
17
+ import { ElScrollbar } from 'element-plus';
18
+ import { computed, onMounted, ref, unref, watch } from 'vue';
19
+ import { useNamespace } from 'web-base-client-vue';
20
+
21
+ defineOptions({ name: 'BwaContextmenu' });
22
+
23
+ const props = defineProps({
24
+ visible: {
25
+ type: Boolean,
26
+ default: false,
27
+ },
28
+ menus: {
29
+ type: Array,
30
+ default: () => [],
31
+ },
32
+ });
33
+
34
+ const emit = defineEmits(['select']);
35
+
36
+ const ns = useNamespace('contextmenu');
37
+
38
+ const scrollbarRef = ref(null);
39
+
40
+ const clickHandle = (item) => {
41
+ emit('select', item);
42
+ };
43
+
44
+ onMounted(() => {
45
+ watch(
46
+ computed(() => props.visible),
47
+ (visible) => {
48
+ if (!visible) {
49
+ return;
50
+ }
51
+
52
+ unref(scrollbarRef).scrollTo(0, 0);
53
+ }
54
+ );
55
+ });
56
+ </script>
@@ -0,0 +1,11 @@
1
+ import Contextmenu from './contextmenu.vue';
2
+
3
+ Contextmenu.install = (app) => {
4
+ Contextmenu._context = app._context;
5
+ app.component(Contextmenu.name, Contextmenu);
6
+ };
7
+
8
+ export const BwaContextmenu = Contextmenu;
9
+ export { useContextmenu } from './use-contextmenu';
10
+
11
+ export default BwaContextmenu;
@@ -0,0 +1,117 @@
1
+ import {
2
+ createApp,
3
+ h,
4
+ nextTick,
5
+ onBeforeUnmount,
6
+ onMounted,
7
+ reactive,
8
+ ref,
9
+ unref,
10
+ vShow,
11
+ withDirectives,
12
+ } from 'vue';
13
+ import { useWindowSize, useElementBounding } from '@vueuse/core';
14
+ import { useNamespace } from 'web-base-client-vue';
15
+ import Contextmenu from './contextmenu.vue';
16
+
17
+ export function useContextmenu({ menus = [] } = {}) {
18
+ const ns = useNamespace('contextmenu');
19
+
20
+ menus = ref([...menus]);
21
+
22
+ let el = document.createElement('div');
23
+
24
+ const contextmenuWrapper = ref(null);
25
+
26
+ const visible = ref(false);
27
+
28
+ const bounding = ref(null);
29
+ const position = reactive({ x: 0, y: 0 });
30
+
31
+ const windowSize = useWindowSize();
32
+
33
+ let resolve = null;
34
+
35
+ const contextmenuInstance = createApp({
36
+ setup() {
37
+ onMounted(() => {
38
+ bounding.value = useElementBounding(contextmenuWrapper);
39
+ });
40
+
41
+ return () =>
42
+ withDirectives(
43
+ h(
44
+ 'div',
45
+ {
46
+ class: ns.e('wrapper'),
47
+ ref: contextmenuWrapper,
48
+ tabIndex: -1,
49
+ style: {
50
+ left: position.x + 'px',
51
+ top: position.y + 'px',
52
+ },
53
+ onContextmenu(e) {
54
+ e.preventDefault();
55
+ e.stopPropagation();
56
+ },
57
+ onBlur() {
58
+ resolve?.(null);
59
+ visible.value = false;
60
+ },
61
+ },
62
+ [
63
+ h(Contextmenu, {
64
+ menus: unref(menus),
65
+ visible: unref(visible),
66
+ onSelect(item) {
67
+ resolve?.(item);
68
+ visible.value = false;
69
+ },
70
+ }),
71
+ ]
72
+ ),
73
+ [[vShow, unref(visible)]]
74
+ );
75
+ },
76
+ });
77
+
78
+ const showContextmenu = async (x, y) => {
79
+ if (!Array.isArray(unref(menus)) || !unref(menus).length) {
80
+ return null;
81
+ }
82
+
83
+ visible.value = true;
84
+
85
+ let promise = new Promise((_resolve) => {
86
+ resolve = _resolve;
87
+ });
88
+
89
+ await nextTick();
90
+
91
+ position.x = x;
92
+ position.y = y;
93
+
94
+ if (windowSize.height.value - position.y < bounding.value.height) {
95
+ position.y = windowSize.height.value - bounding.value.height;
96
+ }
97
+ if (windowSize.width.value - position.x < bounding.value.width) {
98
+ position.x = windowSize.width.value - bounding.value.width;
99
+ }
100
+
101
+ contextmenuWrapper.value.focus();
102
+
103
+ return promise;
104
+ };
105
+
106
+ onMounted(() => {
107
+ contextmenuInstance.mount(el);
108
+ document.body.appendChild(el);
109
+ });
110
+
111
+ onBeforeUnmount(() => {
112
+ document.body.removeChild(el);
113
+ contextmenuInstance.unmount();
114
+ });
115
+
116
+ return { showContextmenu };
117
+ }
@@ -0,0 +1,49 @@
1
+ <template>
2
+ <ElFormItem
3
+ v-if="formColumn && formColumn.visible"
4
+ v-bind="attrs"
5
+ :label="label"
6
+ :class="{ custom: !$slots.default }"
7
+ :prop="formColumn.fullAttrName"
8
+ >
9
+ <slot :column="formColumn" :record="dataForm.data" :dataForm="dataForm">
10
+ <DynamicComponent :column="formColumn" :record="dataForm.data" />
11
+ </slot>
12
+ </ElFormItem>
13
+ </template>
14
+
15
+ <script setup>
16
+ import { ElFormItem, formContextKey } from 'element-plus';
17
+ import { inject, computed, useAttrs, provide, reactive } from 'vue';
18
+ import { dataFormKey } from 'web-base-client-vue';
19
+ import DynamicComponent from './dynamic-component.js';
20
+
21
+ defineOptions({ name: 'BwaDataFormItem' });
22
+
23
+ const props = defineProps({
24
+ name: { type: String },
25
+ isShowLabelColon: { type: Boolean }
26
+ });
27
+
28
+ const attrs = useAttrs();
29
+
30
+ const dataForm = inject(dataFormKey);
31
+
32
+ const formContext = inject(formContextKey, {});
33
+
34
+ const formColumn = dataForm
35
+ .getDisplayColumns()
36
+ .find((col) => col.fullAttrName == props.name);
37
+
38
+ const label = computed(() => {
39
+ return attrs.label || (formColumn ? formColumn.title + (props.isShowLabelColon ? ' :' : '') : '');
40
+ });
41
+
42
+ const _formContext = {};
43
+ _formContext.disabled = computed(
44
+ () => formContext.disabled || formColumn?.disabled
45
+ );
46
+ Reflect.setPrototypeOf(_formContext, formContext);
47
+
48
+ provide(formContextKey, reactive(_formContext));
49
+ </script>