@neatui/nuxt 0.1.0 → 1.0.1

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 (85) hide show
  1. package/BUILD.md +128 -0
  2. package/IMPORT_GUIDE.md +142 -0
  3. package/README.md +98 -1
  4. package/SSR_COMPATIBILITY.md +201 -0
  5. package/USAGE.md +291 -0
  6. package/nuxt.config.example.ts +37 -0
  7. package/package.json +34 -11
  8. package/src/components/basic/IDraggable.vue +87 -65
  9. package/src/components/basic/IFollowView.vue +32 -23
  10. package/src/components/basic/IRouterView.vue +38 -23
  11. package/src/components/basic/IScrollView.vue +11 -7
  12. package/src/components/basic/Icon.vue +17 -17
  13. package/src/components/basic/LayerView/Layer.vue +33 -106
  14. package/src/components/basic/follow.ts +133 -0
  15. package/src/components/display/Calendar.vue +14 -14
  16. package/src/components/display/CalendarReg.vue +14 -14
  17. package/src/components/display/Image.vue +8 -8
  18. package/src/components/display/PhotoEditor.vue +36 -36
  19. package/src/components/display/PhotoViewer.vue +8 -8
  20. package/src/components/display/Tree.vue +6 -6
  21. package/src/components/display/TreeView.vue +4 -4
  22. package/src/components/display/index.ts +2 -2
  23. package/src/components/form/Cascader.vue +19 -19
  24. package/src/components/form/Checkbox.vue +64 -0
  25. package/src/components/form/DatePicker.vue +6 -7
  26. package/src/components/form/DateRangePicker@v3.vue +4 -4
  27. package/src/components/form/DateRangeView@v3.vue +18 -19
  28. package/src/components/form/DateView.vue +14 -14
  29. package/src/components/form/DateView@v2.vue +14 -14
  30. package/src/components/form/DateView@v3.vue +331 -318
  31. package/src/components/form/ImgUpload.vue +7 -7
  32. package/src/components/form/Input@v3.vue +11 -11
  33. package/src/components/form/MoreSelect@v3.vue +87 -17
  34. package/src/components/form/MoreSelectList.vue +8 -8
  35. package/src/components/form/MoreSelectPanel@v3.vue +3 -3
  36. package/src/components/form/MoreSelectPicker.vue +7 -7
  37. package/src/components/form/MoreSelectTags.vue +8 -8
  38. package/src/components/form/PageMoreSelect.vue +14 -14
  39. package/src/components/form/PageSelect.vue +16 -16
  40. package/src/components/form/SearchMoreSelect.vue +12 -12
  41. package/src/components/form/SearchSelect@v3.vue +3 -3
  42. package/src/components/form/Select@v3.vue +229 -23
  43. package/src/components/form/SelectList.vue +8 -8
  44. package/src/components/form/SelectPicker.vue +6 -6
  45. package/src/components/form/SelectTags.vue +7 -7
  46. package/src/components/form/SelectTree/SelectTree@v1.vue +5 -5
  47. package/src/components/form/Switch.vue +38 -103
  48. package/src/components/form/TextArea.vue +18 -18
  49. package/src/components/form/Textarea@v2.vue +275 -0
  50. package/src/components/form/TimeView.vue +14 -14
  51. package/src/components/form/Upload.vue +806 -297
  52. package/src/components/form/date.ts +321 -0
  53. package/src/components/form/index.ts +7 -5
  54. package/src/components/form/number.ts +3 -0
  55. package/src/components/form/type.ts +224 -0
  56. package/src/components/icon/OrderIcon.vue +113 -0
  57. package/src/components/loader/FormLoader/FormLoader@v2.vue +193 -195
  58. package/src/components/loader/FormLoader/FormLoader@v3.vue.backup +372 -291
  59. package/src/components/loader/FormLoader/FormRender@v3.vue.backup +4 -0
  60. package/src/components/loader/FormLoader/NodeLoader.vue +85 -0
  61. package/src/components/loader/FormLoader@v1/FormLoader.vue +1 -1
  62. package/src/components/loader/FormLoader@v1/FormRender.vue +49 -24
  63. package/src/components/loader/LayerLoader/LayerLoader.vue +318 -0
  64. package/src/components/loader/LayerLoader/index.ts +2 -0
  65. package/src/components/loader/LayerLoader/style.scss +77 -0
  66. package/src/components/loader/LimitLoader/LimitLoader@v3.vue +39 -28
  67. package/src/components/loader/MoveLoader/MoveLoader.vue +628 -0
  68. package/src/components/loader/MoveLoader/index.ts +2 -0
  69. package/src/components/loader/MoveLoader/style.scss +77 -0
  70. package/src/components/loader/TableLoader/TableLoader.vue +227 -195
  71. package/src/components/loader/TableLoader/TableRender.vue +141 -0
  72. package/src/components/loader/TableLoader/index.ts +47 -0
  73. package/src/components/loader/index.ts +3 -2
  74. package/src/components/tools/Pagination@a.vue +17 -18
  75. package/src/components/tools/Pagination@b.vue +16 -16
  76. package/src/index.ts +2 -1
  77. package/src/module.ts +169 -0
  78. package/src/runtime/types.d.ts +36 -0
  79. package/src/store/{myui.ts → frame.ts} +4 -4
  80. package/src/utils/theme.ts +14 -0
  81. package/tsconfig.json +1 -1
  82. package/src/components/loader/FormLoader/index.ts +0 -2
  83. package/src/components/loader/LimitLoader/LimitLoader.vue.backup +0 -131
  84. package/src/components/loader/LimitLoader/LimitLoader@v2.vue.backup +0 -174
  85. package/src/components/loader/TableLoader/TableColView.vue +0 -115
@@ -1,80 +1,70 @@
1
1
  <template>
2
2
  <div class="full" ui-scroll=":x :y">
3
3
  <!-- 桌面端 -->
4
- <table ui-hide="<pad" ui-table="@b sz:l" ref="tableRef">
4
+ <table ui-hide="<pad" :ui-table="theme" ref="tableRef">
5
5
  <thead class="table-head-fixed">
6
6
  <tr>
7
- <th v-if="showSelectAll" col-fixed="1" min-width>
8
- <label class="mb-ss" ui-form="@a type:checkbox"><input type="checkbox" :checked="state.isAllSelect" @change="fSelectAll" /><span></span></label>
7
+ <th v-if="selected" min-width col-fixed="1">
8
+ <label class="mb-ss" ui-form="@a type:checkbox"><input type="checkbox" v-model="all" /><span></span></label>
9
9
  </th>
10
10
  <template v-for="(col, idx) in state.table" :key="idx">
11
- <th v-if="!col._close" class="fs-xs nowrap" :min-width="col.fixed" :col-fixed="col.fixed" :col-fixed-side="col.fixed || 'l'" :data-field="col.field">
12
- <div :ui-flex="`row ${!slots.operate && idx === state._last ? 'rm' : 'lm'}`">
13
- <span class="nl-xs" v-if="col.sort" :ui-sort="0" @click="emits('onsort', col)">{{ col.label }}</span>
14
- <span class="nl-xs" v-else>{{ col.label }}</span>
15
- <IFollowView v-if="!slots.operate && idx === state._last" tipBoxClass="n-no">
16
- <button :ui-btn="`@a none s :square`">
17
- <Icon name="tableloader-setting" class="co-read"></Icon>
18
- </button>
19
- <template #tips>
20
- <div class="w-mm h-ls n-sl" ui-scroll="x:hidden :y">
21
- <draggable
22
- v-model="state.table"
23
- :force-fallback="false"
24
- item-key="name"
25
- chosen-class="chosen"
26
- animation="200"
27
- filter=".forbid"
28
- :move="(e: any) => !e.relatedContext.element.fixed"
29
- >
30
- <template #item="{ element, index }">
31
- <div :class="`item ux-hover nowrap r-ss ${element.fixed ? 'forbid' : 'element'}`" :key="index">
32
- <label ui-form="@a type:checkbox" class="ny-xs nx-sl">
33
- <input type="checkbox" :checked="!element._close" @change="element._close = element._close ? 0 : 1" />
34
- <span>
35
- {{ element.label }}
36
- <i v-if="element.fixed" class="icon icon-fixed fs-xs"></i>
37
- </span>
38
- </label>
39
- </div>
40
- </template>
41
- </draggable>
42
- </div>
43
- </template>
44
- </IFollowView>
45
- </div>
11
+ <th v-if="!col.__close" :min-width="col.fixed" :col-fixed="col.fixed" :col-fixed-side="col.fixed || 'l'" :data-field="col.field">
12
+ <slot :name="`thead-${col.field}`" :col="col" :idx="idx">
13
+ <div :class="!slots.operate && idx === state.__last ? 'ar' : ''" v-bind="col.thead">
14
+ <span class="ux-none" ui-flex="row rm" v-if="col.order === 0 || col.order === 1 || col.order === 2" @click="fSetOrder(col)">
15
+ <span>{{ col.label }}</span>
16
+ <span ui-btn="@a none xs :square" :ui-order="`@a ${col.__order}`"></span>
17
+ </span>
18
+ <span v-else>{{ col.label }}</span>
19
+ <!-- 设置 -->
20
+ <IFollowView v-if="!slots.operate && idx === state.__last" tipBoxClass="n-no">
21
+ <button :ui-btn="`@a none xs :square`">
22
+ <Icon name="tableloader-setting" class="co-read"></Icon>
23
+ </button>
24
+ <template #tips>
25
+ <div class="w-mm h-ml+ n-sl" ui-scroll="x:hidden :y">
26
+ <IDraggable v-model:lists="state.table">
27
+ <template #default="{ item: element, idx: index }">
28
+ <div :class="`item ux-hover nowrap r-ss ${element.fixed ? 'forbid' : 'element'}`" :key="index">
29
+ <label ui-form="@a type:checkbox" class="ny-xs nx-sl">
30
+ <input type="checkbox" :checked="!element.__close" @change="element.__close = element.__close ? 0 : 1" />
31
+ <span>
32
+ {{ element.label }}
33
+ <i v-if="element.fixed" class="icon icon-fixed"></i>
34
+ </span>
35
+ </label>
36
+ </div>
37
+ </template>
38
+ </IDraggable>
39
+ </div>
40
+ </template>
41
+ </IFollowView>
42
+ </div>
43
+ </slot>
46
44
  </th>
47
45
  </template>
48
- <th v-if="slots.operate" col-fixed="r" class="fs-xs nowrap ar">
46
+ <th v-if="slots.operate" col-fixed="r" class="fs-ss nowrap ar">
49
47
  <div ui-flex="row rm">
50
- <span class="mr-sm">{{ words['operate'] || '操作' }}</span>
51
- <IFollowView tipBoxClass="n-no">
52
- <button :ui-btn="`@a none s :square`">
53
- <Icon name="tableloader-setting" class="co-read"></Icon>
48
+ <span>{{ words['operate'] || '操作' }}</span>
49
+ <IFollowView v-if="tools" class="lh-xs" tipBoxClass="n-no">
50
+ <button :ui-btn="`@a none xs :square`">
51
+ <Icon name="tableloader-setting" class="co-auto o-ls fs-xs"></Icon>
54
52
  </button>
55
53
  <template #tips>
56
- <div class="w-mm h-ls n-sl" ui-scroll="x:hidden :y">
57
- <draggable
58
- v-model="state.table"
59
- :force-fallback="false"
60
- item-key="name"
61
- chosen-class="chosen"
62
- animation="200"
63
- filter=".forbid"
64
- :move="(e: any) => !e.relatedContext.element.fixed"
65
- >
66
- <template #item="{ element, index }">
54
+ <div class="w-mm h-ml+ n-sl" ui-scroll="x:hidden :y">
55
+ <IDraggable v-model:lists="state.table">
56
+ <template #default="{ item: element, idx: index }">
67
57
  <div :class="`item ux-hover nowrap r-ss ${element.fixed ? 'forbid' : 'element'}`" :key="index">
68
58
  <label ui-form="@a type:checkbox" class="ny-xs nx-sl">
69
- <input type="checkbox" :checked="!element._close" @change="element._close = element._close ? 0 : 1" />
59
+ <input type="checkbox" :checked="!element.__close" @change="element.__close = element.__close ? 0 : 1" />
70
60
  <span>
71
61
  {{ element.label }}
72
- <i v-if="element.fixed" class="icon icon-fixed fs-xs"></i>
62
+ <i v-if="element.fixed" class="icon icon-fixed"></i>
73
63
  </span>
74
64
  </label>
75
65
  </div>
76
66
  </template>
77
- </draggable>
67
+ </IDraggable>
78
68
  </div>
79
69
  </template>
80
70
  </IFollowView>
@@ -85,20 +75,19 @@
85
75
  <tbody :ui-tbody-load="state.load">
86
76
  <template v-if="lists.length">
87
77
  <tr v-for="(item, idx) in lists" :key="idx" v-bind="rows.attrs" v-on="event(rows.event, item, 'td')">
88
- <td v-if="showSelectAll" col-fixed="1" min-width>
78
+ <td v-if="selected" col-fixed="1" min-width>
89
79
  <label class="mb-ss" ui-form="@a type:checkbox"><input type="checkbox" v-model="item.__selected" /><span></span></label>
90
80
  </td>
91
- <template v-for="(col, idx) in state.table" :key="idx">
81
+ <template v-for="(col, cid) in state.table" :key="cid">
92
82
  <td
93
- v-if="!col._close"
94
- :class="`${!slots.operate && idx === state._last ? 'ar' : ''}`"
83
+ v-if="!col.__close"
84
+ :class="`${!slots.operate && cid === state.__last ? 'ar' : ''}`"
95
85
  :min-width="col.fixed"
96
86
  :col-fixed="col.fixed"
97
87
  :col-fixed-side="col.fixed || 'l'"
98
88
  :data-field="col.field"
99
89
  >
100
- <slot v-if="slots[col.field]" :name="col.field"></slot>
101
- <TableColView v-else :col="col" :data="item" />
90
+ <slot :name="col.field" :col="col" :item="item" :idx="idx"><TableRender :node="col" :data="item" /></slot>
102
91
  </td>
103
92
  </template>
104
93
  <td v-if="slots.operate" col-fixed="r" class="ar"><slot name="operate" :item="item" :idx="idx"></slot></td>
@@ -108,51 +97,45 @@
108
97
  </table>
109
98
  <!-- 移动端 -->
110
99
  <div ui-hide=">mob">
111
- <table class="n-sl" ui-table="@a">
112
- <thead class="table-head-fixed">
113
- <tr>
114
- <th class="fs-xs ar ps nr-no">
115
- <div ui-flex="row xm">
116
- <span class="fs-xs bold">信息</span>
117
- <IFollowView>
118
- <button :ui-btn="`@a none s :square`"><Icon name="tableloader-setting" class="co-read"></Icon></button>
119
- <template #tips>
120
- <draggable :list="state.table" :force-fallback="false" item-key="name" chosen-class="chosen" animation="200">
121
- <template #item="{ element, index }">
122
- <div class="item ux-hover nowrap r-ss" :key="index">
123
- <label ui-form="@a type:checkbox" class="ny-xs nx-sl">
124
- <input type="checkbox" :checked="!element._close" @change="element._close = element._close ? 0 : 1" />
125
- <span>{{ element.label }}</span>
126
- </label>
127
- </div>
128
- </template>
129
- </draggable>
100
+ <ul>
101
+ <li class="bg-fore r-sm my-sl nx-ms ny-sl" ui-flex="row xm">
102
+ <div>
103
+ <label class="mb-ss" ui-form="@a type:checkbox"><input type="checkbox" v-model="all" /><span>全选</span></label>
104
+ </div>
105
+ <div>
106
+ <IFollowView>
107
+ <button :ui-btn="`@a none s :square`"><Icon name="tableloader-setting" class="co-read"></Icon></button>
108
+ <template #tips>
109
+ <IDraggable v-model:lists="state.table">
110
+ <template #default="{ item: element, idx: index }">
111
+ <div class="item ux-hover nowrap r-ss" :key="index">
112
+ <label ui-form="@a type:checkbox" class="ny-xs nx-sl">
113
+ <input type="checkbox" :checked="!element.__close" @change="element.__close = element.__close ? 0 : 1" />
114
+ <span>{{ element.label }}</span>
115
+ </label>
116
+ </div>
130
117
  </template>
131
- </IFollowView>
132
- </div>
133
- </th>
134
- </tr>
135
- </thead>
136
- <tbody :ui-tbody-load="state.load">
137
- <template v-if="lists.length">
138
- <tr v-for="(item, idx) in lists" :key="idx" v-bind="rows.attrs" v-on="event(rows.event, item)">
139
- <td ui-card="@a bk:line" class="mb-sl">
140
- <div ui-card-body="" class="n-ss">
141
- <ul>
142
- <template v-for="(col, idx) in state.table" :key="idx">
143
- <li v-if="!col._close" :class="`${col.fixed ? 'ps z-sm' : ''}`" ui-flex="row lm">
144
- <div class="w-sl">{{ col.label }}:</div>
145
- <TableColView :col="col" :data="item" />
146
- </li>
147
- </template>
148
- <li v-if="slots.operate"><slot name="operate" :item="item" :idx="idx"></slot></li>
149
- </ul>
150
- </div>
151
- </td>
152
- </tr>
153
- </template>
154
- </tbody>
155
- </table>
118
+ </IDraggable>
119
+ </template>
120
+ </IFollowView>
121
+ </div>
122
+ </li>
123
+ <li v-for="(item, idx) in lists" :key="idx" class="bg-fore r-sm my-sl n-ms">
124
+ <table>
125
+ <tbody>
126
+ <template v-for="(col, idx) in state.table" :key="idx">
127
+ <tr v-if="!col.__close">
128
+ <td class="nowrap vt n-ss">{{ col.label }}:</td>
129
+ <td class="n-ss">
130
+ <TableRender :node="col" :data="item" />
131
+ </td>
132
+ </tr>
133
+ </template>
134
+ </tbody>
135
+ </table>
136
+ <div v-if="slots.operate"><slot name="operate" :item="item" :idx="idx"></slot></div>
137
+ </li>
138
+ </ul>
156
139
  </div>
157
140
  <div v-if="!lists.length" class="ny-ls o-mm" ui-flex="col cm">
158
141
  <div class="ac">
@@ -165,122 +148,167 @@
165
148
  <script setup lang="ts">
166
149
  import { computed, onMounted, reactive, watch, ref, nextTick, onUnmounted, useSlots } from 'vue';
167
150
  import { useRoute, useRouter } from 'vue-router';
168
- import draggable from 'vuedraggable';
151
+ import IDraggable from '../../basic/IDraggable.vue';
169
152
  import { IFollowView, Icon } from '../../basic';
170
153
  import { itable } from '@fekit/itable';
171
- import TableColView from './TableColView.vue';
172
- import { isFunction, isObject, deepcopy } from '@fekit/utils';
154
+ import TableRender from './TableRender.vue';
155
+ import { isFunction, isObject, hasOwnProp, deepcopy } from '@fekit/utils';
156
+
173
157
  const route = useRoute();
174
158
  const router = useRouter();
175
159
  // 外部插槽
176
160
  const slots: any = useSlots();
177
161
  // 外部方法
178
- const emits = defineEmits(['update:table', 'onsort', 'refresh']);
162
+ const emits = defineEmits(['update:allSelected', 'order', 'refresh']);
179
163
 
180
164
  // 类型定义
181
165
  interface JSONRules {
182
166
  label: string | (() => string);
183
167
  field: string | (() => string);
184
- paths: string | (() => string);
185
- model?: string | Array<any> | (() => string | Array<any>);
186
- enums?: Array<any> | (() => string | Array<any>);
187
- rules?: Array<any> | (() => string | Array<any>);
188
- event?: Array<any> | (() => string | Array<any>);
189
- attrs?: Array<any> | (() => string | Array<any>);
168
+ width?: string | (() => string);
169
+ fixed?: string | (() => string);
170
+ paths?: string | (() => string);
171
+ thead?: Record<string, any> | ((data: any) => Record<string, any>);
172
+ tbody?: Record<string, any> | ((data: any) => Record<string, any>);
173
+ model?: string | any[] | ((data: any) => string | any[]);
174
+ enums?: any[] | ((data: any) => any[]);
175
+ rules?: any[] | ((data: any) => any[]);
176
+ event?: Record<string, any> | ((data: any) => Record<string, any>);
177
+ attrs?: Record<string, any> | ((data: any) => Record<string, any>);
190
178
  value?: any | (() => any);
191
179
  clear?: boolean | (() => boolean);
192
- sort?: boolean | (() => boolean);
180
+ order?: 0 | 1 | 2 | number | (() => 0 | 1 | 2 | number);
193
181
  }
182
+ // 表格列(在 JSONRules 基础上的运行时扩展字段)
183
+ type TableColumn = JSONRules & {
184
+ __close?: number | boolean;
185
+ __order?: 0 | 1 | 2 | number;
186
+ __sort?: number;
187
+ close?: boolean | number | 'always';
188
+ fixed?: string | number;
189
+ thead?: any;
190
+ field: any;
191
+ label: any;
192
+ };
194
193
  interface Props {
195
194
  words?: { [key: string]: any };
196
195
  table: Array<JSONRules>;
197
196
  lists: Array<any>;
198
- showSelectAll?: boolean;
197
+ selected?: boolean;
198
+ tools?: boolean;
199
+ theme?: string;
199
200
  rows?: {
200
201
  attrs?: { [key: string]: any };
201
202
  event?: { [key: string]: any };
202
203
  };
204
+ allSelected?: boolean;
203
205
  }
204
206
  // 外部入参
205
207
  const props: any = withDefaults(defineProps<Props>(), {
206
208
  words: () => ({}),
207
209
  table: () => [],
208
210
  lists: () => [],
209
- showSelectAll: true,
210
- rows: () => ({ attrs: {}, event: {} })
211
+ selected: true,
212
+ tools: true,
213
+ rows: () => ({ attrs: {}, event: {} }),
214
+ theme: '@b sz:l',
215
+ allSelected: false,
211
216
  });
212
217
 
213
218
  // 内部数据
214
- const state: any = reactive({
215
- name: computed(() => 'confs' + route.path?.replace(/\//g, '_')),
219
+ const state = reactive<{
220
+ load: number;
221
+ tool: number;
222
+ table: TableColumn[];
223
+ param: Record<string, any>;
224
+ __last: number;
225
+ }>({
216
226
  load: 0,
217
227
  tool: 1,
218
- mode: 0,
219
- id: 0,
220
- limit: computed(() => {
221
- const _cache = JSON.parse(localStorage.getItem(`${state.name}_limit`) || '{}');
222
- return (props.limit || [])?.map((item: any) => {
223
- if (_cache[item.field] && Object.prototype.hasOwnProperty.call(_cache[item.field], '_close')) {
224
- item._close = _cache[item.field]?._close;
225
- } else {
226
- if (item.close === true || item.close === 1 || item.close === 'always') {
227
- item._close = 1;
228
- }
229
- }
230
- return item;
231
- });
232
- }),
233
- table: [],
228
+ table: [] as TableColumn[],
234
229
  param: {},
235
- // 列表是否全选
236
- isAllSelect: computed(() => {
237
- return (
238
- props.lists.length &&
239
- props.lists.every((item: any) => {
240
- return item.__selected;
241
- })
242
- );
243
- }),
244
- // 列表是否有在选行
245
- isHasSelect: computed(() => {
246
- return props.lists.filter((item: any) => {
247
- return item.__selected;
248
- });
249
- }),
250
- bulk: computed(() => {
251
- return props.isHasSelect.map((item: any) => {
252
- return item.customerId;
230
+ __last: 0,
231
+ });
232
+
233
+ const name = computed(() => 'confs' + route.path?.replace(/\//g, '_')) || '';
234
+
235
+ // 全选状态
236
+ const all = computed({
237
+ get() {
238
+ return props.lists.every((item: any) => item.__selected === true);
239
+ },
240
+ set(value: boolean) {
241
+ props.lists.forEach((item: any) => {
242
+ item.__selected = value;
253
243
  });
254
- }),
255
- // 最后一列可见列
256
- last: 0
244
+ },
257
245
  });
258
246
 
247
+ // 向内同步
248
+ watch(
249
+ () => props.allSelected,
250
+ (v) => {
251
+ all.value = v;
252
+ },
253
+ { immediate: true },
254
+ );
255
+ // 向外同步
256
+ watch(
257
+ () => all.value,
258
+ (v) => {
259
+ emits('update:allSelected', v);
260
+ },
261
+ );
262
+
263
+ // 前置处理
259
264
  watch(
260
265
  () => props.table,
261
266
  () => {
262
- const _cache = JSON.parse(localStorage.getItem(`${state.name}_table`) || '{}');
263
- state._last = 0;
267
+ const _cache = JSON.parse(localStorage.getItem(`${name}_table`) || '{}');
268
+ state.__last = 0;
264
269
  state.table = deepcopy(props.table || [])
265
- ?.map((item: any, idx: number) => {
270
+ ?.map((col: TableColumn, idx: number) => {
271
+ // 标题处理
272
+ if (isFunction(col.label)) {
273
+ col.label = col.label(props.lists);
274
+ }
275
+
276
+ // 表头属性处理
277
+ col.thead ??= {};
278
+ col.thead.class = (col.thead.class || '').split(/\s+/);
279
+ if (!col.thead.class.some((c: any) => c === 'wrap' || c === 'nowrap')) {
280
+ col.thead.class.push('nowrap');
281
+ }
282
+ // 如果没有以 fs- 开头的类,就加 fs-ss
283
+ if (!col.thead.class.some((c: string) => /^fs-/.test(c))) {
284
+ col.thead.class.push('fs-ss');
285
+ }
286
+
266
287
  // 缓存的显示信息
267
- if (_cache[item.field] && Object.prototype.hasOwnProperty.call(_cache[item.field], '_close')) {
268
- item._close = _cache[item.field]?._close;
288
+ if (_cache[col.field] && hasOwnProp(_cache[col.field], '__close')) {
289
+ col.__close = _cache[col.field]?.__close;
269
290
  } else {
270
- if (item.close === true || item.close === 1 || item.close === 'always') {
271
- item._close = 1;
291
+ if (col.close === true || col.close === 1 || col.close === 'always') {
292
+ col.__close = 1;
272
293
  }
273
294
  }
274
- // 缓存的排序信息
275
- if (_cache[item.field] && Object.prototype.hasOwnProperty.call(_cache[item.field], '_sort')) {
276
- item._sort = _cache[item.field]?._sort;
295
+ // 获取缓存的表格列顺序(注意不是数据记录的排序)
296
+ if (_cache[col.field] && hasOwnProp(_cache[col.field], '__sort')) {
297
+ col.__sort = _cache[col.field]?.__sort;
277
298
  }
278
- if (!item._close) {
279
- state._last = idx;
299
+
300
+ // 获取本地存储的字段升降序(注意不是表格列的顺序)
301
+ if (col.order === 0 || col.order === 1 || col.order === 2 || (_cache[col.field] && hasOwnProp(_cache[col.field], '__order'))) {
302
+ col.__order = _cache[col.field]?.__order || col.order;
303
+ }
304
+
305
+ // 最后一列可见列
306
+ if (!col.__close) {
307
+ state.__last = idx;
280
308
  }
281
- return item;
309
+ return col;
282
310
  })
283
- .sort((a: any, b: any) => a._sort - b._sort)
311
+ .sort((a: any, b: any) => a.__sort - b.__sort)
284
312
  .sort((a: any, b: any) => {
285
313
  const fixedOrder: any = { 1: -1, l: -1, r: 1 };
286
314
  const aFixed = a.fixed || '';
@@ -290,35 +318,33 @@
290
318
  },
291
319
  {
292
320
  deep: true,
293
- immediate: true
294
- }
321
+ immediate: true,
322
+ },
295
323
  );
324
+
325
+ // 缓存配置
296
326
  watch(
297
327
  [() => state.table],
298
328
  () => {
299
329
  const _table: any = {};
300
- state._last = 0;
301
- state.table.forEach((item: any, idx: number) => {
302
- _table[item.field] = { _sort: idx };
303
- if (Object.prototype.hasOwnProperty.call(item, '_close')) {
304
- _table[item.field]._close = item._close ? 1 : 0;
330
+ state.__last = 0;
331
+ state.table.forEach((col: any, idx: number) => {
332
+ _table[col.field] = { __sort: idx };
333
+ if (hasOwnProp(col, '__close')) {
334
+ _table[col.field].__close = col.__close ? 1 : 0;
335
+ }
336
+ if (hasOwnProp(col, '__order')) {
337
+ _table[col.field].__order = col.__order;
305
338
  }
306
- if (!item._close) {
307
- state._last = idx;
339
+ if (!col.__close) {
340
+ state.__last = idx;
308
341
  }
309
342
  });
310
- console.log(338);
311
- localStorage.setItem(`${state.name}_table`, JSON.stringify(_table));
343
+ localStorage.setItem(`${name}_table`, JSON.stringify(_table));
312
344
  },
313
- { deep: true }
345
+ { deep: true },
314
346
  );
315
347
 
316
- // 全选
317
- const fSelectAll = ({ target = {} }: any = {}) => {
318
- props.lists.map((item: any = {}) => {
319
- item.__selected = target.checked;
320
- });
321
- };
322
348
  const tableRef: any = ref(null);
323
349
  onMounted(() => {
324
350
  nextTick(() => {
@@ -334,14 +360,20 @@
334
360
  itable.listen(tableRef.value);
335
361
  });
336
362
  },
337
- {
338
- deep: true
339
- }
363
+ { deep: true },
340
364
  );
341
365
  onUnmounted(() => {
342
366
  itable.remove();
343
367
  });
344
368
 
369
+ // 设置字段升降序
370
+ const fSetOrder = (col: any) => {
371
+ const all = state.table.filter((i: any) => i.__order && i.field !== col.field).map((i: any) => ({ field: i.field, order: i.__order }));
372
+ col.__order = col.__order = (col.__order + 1) % 3;
373
+ all.unshift({ field: col.field, order: col.__order });
374
+ emits('order', { field: col.field, order: col.__order }, all);
375
+ };
376
+
345
377
  // 事件处理
346
378
  const event: any = (event: any, data: any): object => {
347
379
  const _event: any = {};