@dt-frames/ui 1.0.9 → 1.0.10

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 (57) hide show
  1. package/es/components/forms/src/types/form.type.d.ts +3 -3
  2. package/es/components/index.d.ts +3 -2
  3. package/es/components/source/src/hooks/useSource.d.ts +4 -4
  4. package/es/components/source/src/types/table.type.d.ts +1 -1
  5. package/es/components/table/src/components/TableActions.d.ts +2 -2
  6. package/es/components/table/src/components/setting/Download.d.ts +2 -2
  7. package/es/components/table/src/components/setting/Size.d.ts +2 -2
  8. package/es/components/table/src/index.d.ts +2 -2
  9. package/es/components/tree/index.d.ts +2 -0
  10. package/es/components/tree/src/hooks/useTree.d.ts +14 -0
  11. package/es/components/tree/src/props.d.ts +101 -0
  12. package/es/components/tree/src/type/tree.d.ts +85 -0
  13. package/es/components/tree/src/utils/tree.d.ts +5 -0
  14. package/es/components/upload/index.d.ts +3 -0
  15. package/es/components/upload/src/helper.d.ts +4 -0
  16. package/es/components/upload/src/index.d.ts +2784 -0
  17. package/es/components/upload/src/props.d.ts +40 -0
  18. package/es/components/upload/src/upload.d.ts +1630 -0
  19. package/es/index.js +1697 -215
  20. package/es/style/components/table/index.less +2 -2
  21. package/es/style/components/tree/index.less +41 -0
  22. package/es/style/components/upload/index.less +43 -0
  23. package/es/theme/sider/components/basic-menu/basic-menu.d.ts +3 -3
  24. package/es/theme/tabs/components/TabContent.d.ts +2 -2
  25. package/package.json +2 -1
  26. package/src/components/curd/src/hooks/useCurd.tsx +1 -1
  27. package/src/components/forms/src/components/formItem.vue +15 -2
  28. package/src/components/forms/src/hooks/useFormEvents.ts +4 -3
  29. package/src/components/forms/src/hooks/useFormValues.ts +1 -1
  30. package/src/components/forms/src/types/form.type.ts +3 -3
  31. package/src/components/index.ts +9 -3
  32. package/src/components/modal/src/index.vue +1 -1
  33. package/src/components/source/src/hooks/useFetch.ts +5 -3
  34. package/src/components/source/src/hooks/useSource.ts +28 -8
  35. package/src/components/source/src/types/table.type.ts +1 -1
  36. package/src/components/table/index.less +2 -2
  37. package/src/components/table/src/hooks/useDataSource.ts +0 -13
  38. package/src/components/tree/index.less +41 -0
  39. package/src/components/tree/index.ts +5 -0
  40. package/src/components/tree/src/components/TreeHeader.vue +97 -0
  41. package/src/components/tree/src/hooks/useTree.ts +239 -0
  42. package/src/components/tree/src/index.vue +392 -0
  43. package/src/components/tree/src/props.ts +133 -0
  44. package/src/components/tree/src/type/tree.ts +105 -0
  45. package/src/components/tree/src/utils/tree.ts +73 -0
  46. package/src/components/upload/index.less +43 -0
  47. package/src/components/upload/index.ts +7 -0
  48. package/src/components/upload/src/helper.ts +32 -0
  49. package/src/components/upload/src/index.vue +38 -0
  50. package/src/components/upload/src/props.ts +48 -0
  51. package/src/components/upload/src/upload.vue +166 -0
  52. package/src/theme/header/helper/menu-tree.ts +2 -2
  53. package/src/theme/sider/helper/split-menu.ts +2 -2
  54. package/es/components/dialog/index.d.ts +0 -2
  55. package/es/components/dialog/src/hooks/useDialog.d.ts +0 -3
  56. package/src/components/dialog/index.ts +0 -5
  57. package/src/components/dialog/src/hooks/useDialog.ts +0 -85
@@ -77,8 +77,8 @@
77
77
  display: inline-block;
78
78
  vertical-align: middle;
79
79
  cursor: pointer;
80
- svg{
81
- display: flex;
80
+ i{
81
+ color: @primary-color;
82
82
  }
83
83
  }
84
84
 
@@ -0,0 +1,41 @@
1
+ .dt-tree{
2
+ display: flex;
3
+ flex-direction: column;
4
+ height: 100%;
5
+
6
+ .dt-tree-header{
7
+ .headerTitle{
8
+ text-align: center;
9
+ line-height: 32px;
10
+ font-weight: bolder;
11
+ }
12
+
13
+ .dt-tree-search{
14
+ display: flex;
15
+ padding: 0 0 10px 10px;
16
+ border-bottom: 1px solid #e7e7e7;
17
+ &>i{
18
+ width: 24px;
19
+ display: block;
20
+ text-align: center;
21
+ cursor: pointer;
22
+ }
23
+ .dt-tree-search-input{
24
+ flex: 1;
25
+ input{
26
+ font-size: 12px;
27
+ }
28
+ }
29
+ }
30
+ }
31
+
32
+ .ant-spin-nested-loading{
33
+ flex: 1;
34
+ overflow-y: auto;
35
+ padding: 10px 0;
36
+
37
+ .tree-title{
38
+ font-size: 12px;
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,43 @@
1
+ .dt-upload-wrap{
2
+ height: 350px;
3
+ padding: 10px 20px;
4
+ display: flex;
5
+ flex-direction: column;
6
+
7
+ .ant-table-wrapper{
8
+ flex: 1;
9
+ .ant-table-body{
10
+ border-bottom: 1px solid #e7e7e7;
11
+ }
12
+ }
13
+ }
14
+
15
+ .file-header{
16
+ display: flex;
17
+ flex-direction: row;
18
+ justify-content: space-between;
19
+ &>div{
20
+ display: flex;
21
+ flex-direction: row;
22
+ button{
23
+ margin-right: 10px;
24
+ }
25
+ }
26
+ }
27
+
28
+ .file-type-tips{
29
+ line-height: 24px;
30
+ padding: 5px 10px;
31
+ font-size: 12px;
32
+ display: flex;
33
+ margin: 10px 0;
34
+ border: 1px dashed @primary-color;
35
+ cursor: inherit;
36
+ span i{
37
+ color: @primary-color;
38
+ margin-right: 7px;
39
+ }
40
+ i{
41
+ color: #666;
42
+ }
43
+ }
@@ -125,7 +125,7 @@ declare const _sfc_main: import("vue").DefineComponent<{
125
125
  'onUpdate:openKeys': import("vue").PropType<(keys: import("ant-design-vue/lib/_util/type").Key[]) => void>;
126
126
  'onUpdate:selectedKeys': import("vue").PropType<(keys: import("ant-design-vue/lib/_util/type").Key[]) => void>;
127
127
  'onUpdate:activeKey': import("vue").PropType<(key: import("ant-design-vue/lib/_util/type").Key) => void>;
128
- }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "disabled" | "mode" | "theme" | "multiple" | "inlineCollapsed" | "disabledOverflow" | "forceSubMenuRender" | "selectable" | "inlineIndent" | "subMenuOpenDelay" | "subMenuCloseDelay" | "triggerSubMenuAction">;
128
+ }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "disabled" | "mode" | "multiple" | "selectable" | "inlineCollapsed" | "disabledOverflow" | "forceSubMenuRender" | "theme" | "inlineIndent" | "subMenuOpenDelay" | "subMenuCloseDelay" | "triggerSubMenuAction">;
129
129
  $attrs: {
130
130
  [x: string]: unknown;
131
131
  };
@@ -742,10 +742,10 @@ declare const _sfc_main: import("vue").DefineComponent<{
742
742
  }, {
743
743
  type: string;
744
744
  mode: MenuMode;
745
- theme: import("@dt-frames/core").Theme;
746
- isHorizontal: boolean;
747
745
  inlineCollapsed: boolean;
746
+ theme: import("@dt-frames/core").Theme;
748
747
  inlineIndent: number;
748
+ isHorizontal: boolean;
749
749
  collapsedShowTitle: boolean;
750
750
  mixSider: boolean;
751
751
  }>;
@@ -64,7 +64,7 @@ declare const _sfc_main: import("vue").DefineComponent<{}, {
64
64
  'onUpdate:visible': {
65
65
  type: import("vue").PropType<(val: boolean) => void>;
66
66
  };
67
- }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "visible" | "overlayStyle" | "disabled" | "forceRender" | "arrow" | "minOverlayWidthMatchTrigger" | "destroyPopupOnHide">;
67
+ }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "visible" | "overlayStyle" | "disabled" | "arrow" | "forceRender" | "minOverlayWidthMatchTrigger" | "destroyPopupOnHide">;
68
68
  $attrs: {
69
69
  [x: string]: unknown;
70
70
  };
@@ -501,7 +501,7 @@ declare const _sfc_main: import("vue").DefineComponent<{}, {
501
501
  'onUpdate:openKeys': import("vue").PropType<(keys: import("ant-design-vue/lib/_util/type").Key[]) => void>;
502
502
  'onUpdate:selectedKeys': import("vue").PropType<(keys: import("ant-design-vue/lib/_util/type").Key[]) => void>;
503
503
  'onUpdate:activeKey': import("vue").PropType<(key: import("ant-design-vue/lib/_util/type").Key) => void>;
504
- }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "disabled" | "mode" | "theme" | "multiple" | "inlineCollapsed" | "disabledOverflow" | "forceSubMenuRender" | "selectable" | "inlineIndent" | "subMenuOpenDelay" | "subMenuCloseDelay" | "triggerSubMenuAction">;
504
+ }>> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "disabled" | "mode" | "multiple" | "selectable" | "inlineCollapsed" | "disabledOverflow" | "forceSubMenuRender" | "theme" | "inlineIndent" | "subMenuOpenDelay" | "subMenuCloseDelay" | "triggerSubMenuAction">;
505
505
  $attrs: {
506
506
  [x: string]: unknown;
507
507
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dt-frames/ui",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "keywords": [
5
5
  "ui",
6
6
  "dt-ui"
@@ -32,6 +32,7 @@
32
32
  "@vueuse/core": "^7.5.2",
33
33
  "lodash-es": "^4.17.21",
34
34
  "sortablejs": "^1.15.0",
35
+ "spark-md5": "^3.0.2",
35
36
  "vue": "^3.2.25",
36
37
  "vue-router": "^4.0.12",
37
38
  "xlsx": "^0.18.5"
@@ -16,7 +16,7 @@ export function useCurd(curdOpt: CrudOptType) {
16
16
  <DtModal
17
17
  { ...curdOpt }
18
18
  formsVal = { formsVal }
19
- formProps = { curdOpt.formProps }
19
+ formProps = { curdOpt.formProps as any }
20
20
  onRegister = { register }
21
21
  ></DtModal>
22
22
  </div>
@@ -2,7 +2,7 @@
2
2
  import { defineComponent, PropType, Ref, toRefs, unref, computed } from "vue"
3
3
  import { Col, Tooltip, Divider, Form, FormItem } from 'ant-design-vue'
4
4
  import { upperFirst, cloneDeep } from 'lodash-es'
5
- import { isFunction, isBoolean, isNull, Recordable, useSlots, useAppStore, isString, isArray } from "@dt-frames/core"
5
+ import { isFunction, isBoolean, isNull, Recordable, useSlots, useAppStore, isString, isArray, error } from "@dt-frames/core"
6
6
  import type { ValidationRule } from 'ant-design-vue/lib/form/Form'
7
7
 
8
8
  import { useLabelWidth } from "../hooks/useLabelWidth"
@@ -377,7 +377,7 @@
377
377
  * 3、否则通过属性去动态设置渲染条目
378
378
  */
379
379
  return () => {
380
- const { colSlot, renderCol, colProps } = props.schema
380
+ const { colSlot, renderCol, colProps, component, render } = props.schema as FormSchema
381
381
  const { colProps: gColProps, mode } = props.formProps as FormProps
382
382
 
383
383
  let _colProps = colProps
@@ -388,6 +388,19 @@
388
388
 
389
389
  const values = unref(getValues)
390
390
 
391
+ if( !component ) {
392
+ if( !render ) {
393
+ error('请配置render函数')
394
+ return
395
+ }
396
+
397
+ return (
398
+ <Col span={24}>
399
+ { render() }
400
+ </Col>
401
+ )
402
+ }
403
+
391
404
  const getContent = () => {
392
405
  return colSlot
393
406
  ? getSlot(slots, colSlot, values)
@@ -1,8 +1,9 @@
1
- import { dateFormat, deepMerge, isObject, isString, Recordable } from "@dt-frames/core"
1
+ import { deepMerge, isObject, isString, Recordable } from "@dt-frames/core"
2
2
  import { ComputedRef, nextTick, Ref, toRaw, unref } from "vue"
3
3
  import { uniqBy, cloneDeep } from 'lodash-es'
4
4
  import { FormActionType, FormProps, FormSchema } from "../types/form.type"
5
5
  import { handleInputNumberValue } from "./helper"
6
+ import dayjs from 'dayjs'
6
7
 
7
8
  /** =================================
8
9
  * 定义表单的事件
@@ -166,7 +167,7 @@ export function useFormEvents({
166
167
  if (Array.isArray(value)) {
167
168
  const arr: any[] = [];
168
169
  for (const ele of value) {
169
- arr.push(ele ? dateFormat(ele) : null);
170
+ arr.push(ele ? dayjs(ele) : null);
170
171
  }
171
172
  formModel[key] = arr;
172
173
  } else {
@@ -177,7 +178,7 @@ export function useFormEvents({
177
178
  if (typeof props === 'function') {
178
179
  _props = props({ formModel });
179
180
  }
180
- formModel[key] = value ? (_props?.valueFormat ? value : dateFormat(value)) : null
181
+ formModel[key] = value ? (_props?.valueFormat ? value : dayjs(value)) : null
181
182
  }
182
183
  } else {
183
184
  formModel[key] = value
@@ -57,7 +57,7 @@ export function useFormValues({
57
57
  * 设置初始化的formModel值
58
58
  */
59
59
  function initDefault() {
60
- const schema = unref( getSchema )
60
+ const schema = unref( getSchema ).filter(it => it.component )
61
61
  const obj: Recordable = {}
62
62
 
63
63
  schema.forEach( item => {
@@ -155,7 +155,7 @@ export type FormProps = {
155
155
  // 表单当个元素配置项
156
156
  export type FormSchema = {
157
157
  // 表单绑定的属性,亦作为name属性,用于后期自动化测试
158
- name: string | string[]
158
+ name?: string | string[]
159
159
  // 值发生变化触发的函数名
160
160
  changeEvent?: string
161
161
  // 绑定v-model的值
@@ -176,7 +176,7 @@ export type FormSchema = {
176
176
  // tooltip 配置信息
177
177
  toolTipProps?: ToolTipProps
178
178
  // 表单控件类型
179
- component: ComponentType
179
+ component?: ComponentType
180
180
  // 表单控件参数
181
181
  props?:
182
182
  | ((opt: {
@@ -205,7 +205,7 @@ export type FormSchema = {
205
205
  show?: boolean | ( ( parms: FormCallBackParams ) => boolean )
206
206
 
207
207
  // 渲染item
208
- render?: (parms: FormCallBackParams) => VNode | VNode[] | string
208
+ render?: (parms?: FormCallBackParams) => VNode | VNode[] | string
209
209
 
210
210
  // 渲染col
211
211
  renderCol?: (parms: FormCallBackParams) => VNode | VNode[] | string
@@ -8,7 +8,8 @@ import { useSource } from './source'
8
8
  import { useCurd } from './curd'
9
9
  import { export2Excel } from './excel'
10
10
  import { DtIframe } from './iframe'
11
- import { useDialog } from './dialog';
11
+ import { DtUpload, DtUploadModal } from './upload'
12
+ import { DtTree } from './tree'
12
13
 
13
14
  const dtComponents = [
14
15
  { name: 'dt-base-router', component: DtBaseRouter },
@@ -16,6 +17,9 @@ const dtComponents = [
16
17
  { name: 'dt-pick-icon', component: DtPickIcon },
17
18
  { name: 'dt-modal', component: DtModal },
18
19
  { name: 'dt-form', component: DtForm },
20
+ { name: 'dt-upload', component: DtUpload },
21
+ { name: 'dt-upload-modal', component: DtUploadModal },
22
+ { name: 'dt-tree', component: DtTree },
19
23
  ];
20
24
 
21
25
 
@@ -37,12 +41,14 @@ export {
37
41
  DtTable,
38
42
  FormButtons,
39
43
  DtIframe,
44
+ DtUpload,
45
+ DtUploadModal,
46
+ DtTree,
40
47
  useForm,
41
48
  useTable,
42
49
  useSource,
43
50
  useCurd,
44
51
  useModal,
45
52
  useModalOut,
46
- export2Excel,
47
- useDialog
53
+ export2Excel
48
54
  }
@@ -80,7 +80,7 @@
80
80
  }
81
81
 
82
82
  const { getWrapClassName, toggleFullScreen, fullScreenRef } = useFullScreen({
83
- wrapClassName: computed(() => (unref(propsRef) as any).wrapClassName),
83
+ wrapClassName: computed(() => (unref(propsRef) as any)?.wrapClassName),
84
84
  extHeightRef,
85
85
  modalWrapperRef
86
86
  });
@@ -8,16 +8,18 @@ export function useFetch(api: string | ApiType, baseUrl: string = '') {
8
8
  function fetch(params: Recordable = { }) {
9
9
  let type, header = { }, model = {}, _api = ''
10
10
  if(isString( api )) {
11
- _api = baseUrl + api
11
+ api = baseUrl + api
12
12
  } else {
13
13
  type = api.type
14
- _api = baseUrl + api.api
14
+ if( api.api.indexOf(baseUrl) === -1 ) {
15
+ api.api = `${baseUrl}${api.api}`
16
+ }
15
17
  header = api.header
16
18
  model = api.model
17
19
  }
18
20
 
19
21
  return new Promise(( resolve, reject ) => {
20
- http[type || 'post']( _api, Object.assign({}, model, params), {
22
+ http[type || 'post']( api, Object.assign({}, model, params), {
21
23
  ...header,
22
24
  ...{ onlyData: false }
23
25
  }).then(
@@ -19,11 +19,22 @@ export function useSource(opt: SourceType) {
19
19
 
20
20
  const { message } = useMessage()
21
21
  const apiFul: Recordable = {}
22
+ const apiPath: Recordable = {}
22
23
 
23
24
  // 定义加载状态
24
25
  for( let it in api ) {
25
26
  loading['on' + it.slice(0,1).toUpperCase() + it.slice(1).toLowerCase()] = ref(false)
26
- apiFul[it] = baseUrl + (isString(api[it]) ? api[it] : (api[it] as ApiType).api)
27
+
28
+ if( isString(api[it] )) {
29
+ apiFul[it] = baseUrl + api[it]
30
+ } else {
31
+ apiFul[it] = {
32
+ ...(api[it] as ApiType),
33
+ api: baseUrl + (api[it] as ApiType).api
34
+ }
35
+ }
36
+
37
+ apiPath[it] = baseUrl + (isString(api[it]) ? api[it] : (api[it] as ApiType).api)
27
38
  }
28
39
 
29
40
  // 定义分页数据
@@ -48,7 +59,7 @@ export function useSource(opt: SourceType) {
48
59
  /**
49
60
  * 分页查询
50
61
  */
51
- function onSearch(model: Recordable) {
62
+ function onSearch(model: Recordable = {}) {
52
63
  baseData.entityDTO = { ...model }
53
64
  baseData.pageDTO.pageNo = 0
54
65
  loading.onSearch.value = true
@@ -71,15 +82,23 @@ export function useSource(opt: SourceType) {
71
82
  * 如果为首次 则为数据初始化 不需要查询
72
83
  */
73
84
  function onTableChange( params: TableParamsType, needSearch: boolean = true ) {
74
- const { pagination, showBtnLoading, sort = [], filter } = params
85
+ const { pagination, showBtnLoading, sort, filter } = params
75
86
 
76
87
  baseData.pageDTO = {
77
88
  pageNo: pagination.current - 1,
78
89
  pageSize: pagination.pageSize
79
90
  }
80
91
 
81
- // baseData.orderDTOs = sort.length ?? null
82
- baseData.orderDTOs = []
92
+ const { field, order } = sort
93
+
94
+ if( field ) {
95
+ baseData.orderDTOs = [{
96
+ propertyName: field,
97
+ dir: order === 'ascend' ? 'asc' : 'desc'
98
+ }]
99
+ } else {
100
+ baseData.orderDTOs = []
101
+ }
83
102
 
84
103
  if( needSearch ) search()
85
104
  }
@@ -176,8 +195,8 @@ export function useSource(opt: SourceType) {
176
195
  }
177
196
 
178
197
  return {
179
- api,
180
- apiFul,
198
+ api: apiFul,
199
+ apiPath,
181
200
  form,
182
201
  table,
183
202
  curd,
@@ -188,6 +207,7 @@ export function useSource(opt: SourceType) {
188
207
  onUpdate,
189
208
  onTableChange,
190
209
  onDownload,
191
- onSearch
210
+ onSearch,
211
+
192
212
  }
193
213
  }
@@ -3,6 +3,6 @@ import { Recordable } from "@dt-frames/core";
3
3
  export type TableParamsType = {
4
4
  pagination: any,
5
5
  showBtnLoading: boolean,
6
- sort: Recordable[],
6
+ sort: Recordable,
7
7
  filter: any
8
8
  }
@@ -77,8 +77,8 @@
77
77
  display: inline-block;
78
78
  vertical-align: middle;
79
79
  cursor: pointer;
80
- svg{
81
- display: flex;
80
+ i{
81
+ color: @primary-color;
82
82
  }
83
83
  }
84
84
 
@@ -24,19 +24,6 @@ export function useDataSource(
24
24
  // 拷贝一份表格数据 然后再做数据处理
25
25
  const dataSourceRef = ref<Recordable[]>([])
26
26
 
27
- // const { defSort, onTableChange } = unref( propsRef )
28
- // const { appConf } = useAppStore()
29
-
30
- // onTableChange({
31
- // pagination: {
32
- // current: 1,
33
- // pageSize: appConf.ui.table.defaultPageSize
34
- // },
35
- // sort:defSort,
36
- // filter: null,
37
- // showBtnLoading: false
38
- // }, false)
39
-
40
27
  watch(
41
28
  () => unref(propsRef).dataSource,
42
29
  (dataSource) => {
@@ -0,0 +1,41 @@
1
+ .dt-tree{
2
+ display: flex;
3
+ flex-direction: column;
4
+ height: 100%;
5
+
6
+ .dt-tree-header{
7
+ .headerTitle{
8
+ text-align: center;
9
+ line-height: 32px;
10
+ font-weight: bolder;
11
+ }
12
+
13
+ .dt-tree-search{
14
+ display: flex;
15
+ padding: 0 0 10px 10px;
16
+ border-bottom: 1px solid #e7e7e7;
17
+ &>i{
18
+ width: 24px;
19
+ display: block;
20
+ text-align: center;
21
+ cursor: pointer;
22
+ }
23
+ .dt-tree-search-input{
24
+ flex: 1;
25
+ input{
26
+ font-size: 12px;
27
+ }
28
+ }
29
+ }
30
+ }
31
+
32
+ .ant-spin-nested-loading{
33
+ flex: 1;
34
+ overflow-y: auto;
35
+ padding: 10px 0;
36
+
37
+ .tree-title{
38
+ font-size: 12px;
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,5 @@
1
+ import DtTree from './src/index.vue'
2
+
3
+ export {
4
+ DtTree
5
+ }
@@ -0,0 +1,97 @@
1
+ <template>
2
+ <div class="dt-tree-header">
3
+ <slot name="headerTitle" v-if="slots.headerTitle"></slot>
4
+
5
+ <h4 v-if="!slots.headerTitle && title" class="headerTitle">{{ title }}</h4>
6
+
7
+ <div v-if="search || toolbar" class="dt-tree-search">
8
+ <div class="dt-tree-search-input" v-if="search">
9
+ <InputSearch size="small" allowClear v-model:value="searchValue" placeholder="搜索"/>
10
+ </div>
11
+
12
+ <Dropdown @click.prevent v-if="toolbar">
13
+ <i class="i ic:baseline-more-vert"></i>
14
+ <template #overlay>
15
+ <Menu @click="handleMenuClick">
16
+ <template v-for="item in toolbarList" :key="item.value">
17
+ <MenuItem v-bind="{ key: item.value }">
18
+ {{ item.label }}
19
+ </MenuItem>
20
+ <MenuDivider v-if="item.divider" />
21
+ </template>
22
+ </Menu>
23
+ </template>
24
+ </Dropdown>
25
+ </div>
26
+
27
+ </div>
28
+ </template>
29
+
30
+ <script lang="ts" setup>
31
+ import { useSlots, ref, watch, computed } from 'vue'
32
+ import { InputSearch, Dropdown, Menu, MenuItem, MenuDivider } from 'ant-design-vue'
33
+ import { useDebounceFn } from '@vueuse/core'
34
+ import { searchProps } from '../props'
35
+ import { ToolbarEnum } from '../type/tree'
36
+
37
+ const slots = useSlots()
38
+ const emits = defineEmits([
39
+ 'search',
40
+ 'strictly-change',
41
+ 'strictly-change'
42
+ ])
43
+ const props = defineProps( searchProps )
44
+
45
+ const searchValue = ref('')
46
+
47
+ function emitChange(value?: string){
48
+ emits('search', value)
49
+ }
50
+
51
+ function handleMenuClick(e) {
52
+ const { key } = e;
53
+ switch (key) {
54
+ case ToolbarEnum.SELECT_ALL: props.checkAll?.(true); break
55
+ case ToolbarEnum.UN_SELECT_ALL: props.checkAll?.(false); break
56
+ case ToolbarEnum.EXPAND_ALL: props.expandAll?.(true); break
57
+ case ToolbarEnum.UN_EXPAND_ALL: props.expandAll?.(false); break
58
+ case ToolbarEnum.CHECK_STRICTLY: emits('strictly-change', false); break
59
+ case ToolbarEnum.CHECK_UN_STRICTLY: emits('strictly-change', true); break
60
+ }
61
+ }
62
+
63
+ const toolbarList = computed(() => {
64
+ const { checkable } = props
65
+
66
+ const defaultToolbarList = [
67
+ { label: '展开全部', value: ToolbarEnum.EXPAND_ALL },
68
+ {
69
+ label: '折叠全部',
70
+ value: ToolbarEnum.UN_EXPAND_ALL,
71
+ divider: checkable,
72
+ },
73
+ ];
74
+
75
+ return checkable
76
+ ? [
77
+ { label: '选择全部', value: ToolbarEnum.SELECT_ALL },
78
+ {
79
+ label: '取消选择',
80
+ value: ToolbarEnum.UN_SELECT_ALL,
81
+ divider: checkable,
82
+ },
83
+ ...defaultToolbarList,
84
+ { label: '层级关联', value: ToolbarEnum.CHECK_STRICTLY },
85
+ { label: '层级独立', value: ToolbarEnum.CHECK_UN_STRICTLY },
86
+ ]
87
+ : defaultToolbarList;
88
+ })
89
+
90
+ const debounceEmitChange = useDebounceFn(emitChange, 200)
91
+ watch(
92
+ () => searchValue.value,
93
+ (v) => {
94
+ debounceEmitChange(v);
95
+ },
96
+ )
97
+ </script>