@netang/quasar 0.2.30 → 0.2.32

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 (289) hide show
  1. package/.editorconfig +12 -12
  2. package/_docs/docs/components/field-table.md +58 -58
  3. package/_docs/docs/components/field-tree.md +21 -21
  4. package/_docs/docs/components/table.md +24 -24
  5. package/_docs/docs/utils/table.md +196 -196
  6. package/components/column-title/index.vue +38 -38
  7. package/components/data/index.vue +20 -20
  8. package/components/dialog/img-viewer/index.vue +697 -697
  9. package/components/dialog/index.vue +387 -387
  10. package/components/dragger/index.vue +203 -203
  11. package/components/drawer/index.vue +303 -303
  12. package/components/editor-code/index.vue +328 -328
  13. package/components/empty/index.vue +82 -82
  14. package/components/field-date/index.vue +860 -860
  15. package/components/field-date/methods.js +100 -100
  16. package/components/field-table/index.vue +1483 -1483
  17. package/components/field-text/index.vue +166 -166
  18. package/components/field-tree/index.vue +755 -755
  19. package/components/img/index.vue +279 -279
  20. package/components/input-number/index.vue +560 -560
  21. package/components/list-menu/index.vue +149 -149
  22. package/components/list-menu-item/index.vue +79 -79
  23. package/components/mixed-table/index.vue +532 -532
  24. package/components/mixed-table-splitter/index.vue +377 -377
  25. package/components/power-page/index.vue +96 -96
  26. package/components/price/index.vue +188 -188
  27. package/components/private/components/index.js +11 -11
  28. package/components/private/components/move-to-tree/index.vue +154 -154
  29. package/components/private/edit-power-data/index.vue +846 -846
  30. package/components/private/table-visible-columns-button/index.vue +114 -114
  31. package/components/render/index.vue +123 -123
  32. package/components/search/index.vue +231 -231
  33. package/components/search-item/index.vue +210 -210
  34. package/components/select/index.vue +177 -177
  35. package/components/splitter/index.vue +422 -422
  36. package/components/table/index.vue +513 -513
  37. package/components/table-column-fixed/index.vue +110 -110
  38. package/components/table-pagination/index.vue +192 -192
  39. package/components/table-summary/index.vue +107 -107
  40. package/components/thumbnail/index.vue +72 -72
  41. package/components/toolbar/index.vue +150 -150
  42. package/components/tree/index.vue +1728 -1728
  43. package/components/tree/virtual-scroll.vue +41 -41
  44. package/components/uploader/index.vue +196 -196
  45. package/components/uploader-query/index.vue +945 -945
  46. package/components/value-format/index.vue +274 -274
  47. package/components/virtual-scroll/index.vue +136 -136
  48. package/configs/area3.js +1 -1
  49. package/docs/404.html +33 -33
  50. package/docs/assets/404.html-60b35caa.js +1 -1
  51. package/docs/assets/404.html-d1e63d77.js +1 -1
  52. package/docs/assets/alert.html-b2a2a72f.js +5 -5
  53. package/docs/assets/alert.html-ba46d137.js +1 -1
  54. package/docs/assets/app-9f30aa4b.js +6 -6
  55. package/docs/assets/area.html-01b9b58d.js +42 -42
  56. package/docs/assets/area.html-9a4fce6a.js +1 -1
  57. package/docs/assets/arr.html-145d27e7.js +1 -1
  58. package/docs/assets/arr.html-674e65ab.js +11 -11
  59. package/docs/assets/auth.html-579fa830.js +1 -1
  60. package/docs/assets/auth.html-8544ed95.js +8 -8
  61. package/docs/assets/bus.html-c71254aa.js +1 -1
  62. package/docs/assets/bus.html-dc7d3d19.js +6 -6
  63. package/docs/assets/column-title.html-c735cb5a.js +3 -3
  64. package/docs/assets/column-title.html-e9316762.js +1 -1
  65. package/docs/assets/confirm.html-ddfdc27f.js +10 -10
  66. package/docs/assets/confirm.html-ef3e2bef.js +1 -1
  67. package/docs/assets/copy.html-d20345b6.js +1 -1
  68. package/docs/assets/copy.html-ef8c8571.js +13 -13
  69. package/docs/assets/data.html-6432175d.js +30 -30
  70. package/docs/assets/data.html-a3b05d5b.js +1 -1
  71. package/docs/assets/dialog.html-1f698e5a.js +1 -1
  72. package/docs/assets/dialog.html-62902b83.js +68 -68
  73. package/docs/assets/dialog.html-baea77c9.js +1 -1
  74. package/docs/assets/dialog.html-bb082fc4.js +1 -1
  75. package/docs/assets/dict.html-1311da3d.js +23 -23
  76. package/docs/assets/dict.html-b96fbf0c.js +1 -1
  77. package/docs/assets/dictOptions.html-7c4f40a5.js +1 -1
  78. package/docs/assets/dictOptions.html-fb99d175.js +5 -5
  79. package/docs/assets/dragger.html-668d3efa.js +1 -1
  80. package/docs/assets/dragger.html-749d585a.js +1 -1
  81. package/docs/assets/editor-code.html-6ab26ea9.js +1 -1
  82. package/docs/assets/editor-code.html-d196205d.js +1 -1
  83. package/docs/assets/empty.html-1c139131.js +1 -1
  84. package/docs/assets/empty.html-1e9c441d.js +1 -1
  85. package/docs/assets/field-date.html-069fdb13.js +1 -1
  86. package/docs/assets/field-date.html-ad204aa9.js +1 -1
  87. package/docs/assets/field-table.html-ce480f03.js +1 -1
  88. package/docs/assets/field-table.html-d9236160.js +1 -1
  89. package/docs/assets/field-text.html-7277c62f.js +1 -1
  90. package/docs/assets/field-text.html-ccb4cecf.js +1 -1
  91. package/docs/assets/field-tree.html-519bfb45.js +1 -1
  92. package/docs/assets/field-tree.html-fdc748d6.js +1 -1
  93. package/docs/assets/form.html-2b562c37.js +2 -2
  94. package/docs/assets/form.html-75104cd5.js +1 -1
  95. package/docs/assets/framework-204010b2.js +5 -5
  96. package/docs/assets/getData.html-990e3787.js +1 -1
  97. package/docs/assets/getData.html-bb72025f.js +34 -34
  98. package/docs/assets/getFile.html-42368004.js +1 -1
  99. package/docs/assets/getFile.html-99abd054.js +3 -3
  100. package/docs/assets/getImage.html-3429c5a1.js +1 -1
  101. package/docs/assets/getImage.html-4d886d83.js +3 -3
  102. package/docs/assets/getTime.html-7435f922.js +1 -1
  103. package/docs/assets/getTime.html-b37f49eb.js +20 -20
  104. package/docs/assets/img.html-7d1da657.js +1 -1
  105. package/docs/assets/img.html-fbea1105.js +1 -1
  106. package/docs/assets/index.html-1695dd7c.js +1 -1
  107. package/docs/assets/index.html-65a4aa67.js +1 -1
  108. package/docs/assets/index.html-7b98d5bd.js +1 -1
  109. package/docs/assets/index.html-c01f2648.js +1 -1
  110. package/docs/assets/input-number.html-0b250d2a.js +1 -1
  111. package/docs/assets/input-number.html-a8eb0378.js +1 -1
  112. package/docs/assets/list-menu-item.html-7f1b4611.js +1 -1
  113. package/docs/assets/list-menu-item.html-84ed5ab8.js +1 -1
  114. package/docs/assets/list-menu.html-28b4163f.js +1 -1
  115. package/docs/assets/list-menu.html-cb6ba95b.js +1 -1
  116. package/docs/assets/loading.html-dae9e39d.js +6 -6
  117. package/docs/assets/loading.html-dc74c9e6.js +1 -1
  118. package/docs/assets/notify.html-e6c4c514.js +1 -1
  119. package/docs/assets/notify.html-f2c4d914.js +8 -8
  120. package/docs/assets/power-page.html-32e02f82.js +1 -1
  121. package/docs/assets/power-page.html-485e77da.js +1 -1
  122. package/docs/assets/power.html-d258cc19.js +93 -93
  123. package/docs/assets/power.html-e490bd32.js +1 -1
  124. package/docs/assets/previewImage.html-6a6b4245.js +1 -1
  125. package/docs/assets/previewImage.html-c5b7e945.js +2 -2
  126. package/docs/assets/price.html-1882c548.js +19 -19
  127. package/docs/assets/price.html-94d3f5be.js +1 -1
  128. package/docs/assets/price.html-d213df0f.js +1 -1
  129. package/docs/assets/price.html-deaf880f.js +1 -1
  130. package/docs/assets/render.html-8efcbdd4.js +1 -1
  131. package/docs/assets/render.html-df228e38.js +1 -1
  132. package/docs/assets/rule.html-2cd57fc2.js +13 -13
  133. package/docs/assets/rule.html-61662001.js +1 -1
  134. package/docs/assets/ruleValid.html-04fe2552.js +1 -1
  135. package/docs/assets/ruleValid.html-e0a776af.js +14 -14
  136. package/docs/assets/search-0782d0d1.svg +1 -1
  137. package/docs/assets/search-item.html-3f75394c.js +1 -1
  138. package/docs/assets/search-item.html-4e942ecd.js +1 -1
  139. package/docs/assets/search.html-2807043e.js +1 -1
  140. package/docs/assets/search.html-c24f8806.js +1 -1
  141. package/docs/assets/select.html-00d0607c.js +1 -1
  142. package/docs/assets/select.html-de7731f5.js +1 -1
  143. package/docs/assets/splitter.html-56f51a70.js +1 -1
  144. package/docs/assets/splitter.html-f5c836d7.js +1 -1
  145. package/docs/assets/style-161e43ab.css +1 -1
  146. package/docs/assets/symbols.html-a6aea4bf.js +1 -1
  147. package/docs/assets/symbols.html-b1f65bad.js +21 -21
  148. package/docs/assets/table-column-fixed.html-3a69e7b2.js +1 -1
  149. package/docs/assets/table-column-fixed.html-e763c38b.js +1 -1
  150. package/docs/assets/table-pagination.html-236934d3.js +1 -1
  151. package/docs/assets/table-pagination.html-c37ee2ac.js +1 -1
  152. package/docs/assets/table-splitter.html-07eab15c.js +1 -1
  153. package/docs/assets/table-splitter.html-7670ee65.js +1 -1
  154. package/docs/assets/table-summary.html-04db434f.js +1 -1
  155. package/docs/assets/table-summary.html-943c65a0.js +1 -1
  156. package/docs/assets/table.html-36253ad7.js +1 -1
  157. package/docs/assets/table.html-7f9c5d1b.js +38 -38
  158. package/docs/assets/table.html-93d53dc8.js +1 -1
  159. package/docs/assets/table.html-ac99b9cb.js +1 -1
  160. package/docs/assets/thumbnail.html-bab1976b.js +1 -1
  161. package/docs/assets/thumbnail.html-eb64e5e8.js +1 -1
  162. package/docs/assets/timestamp.html-4e54f79b.js +13 -13
  163. package/docs/assets/timestamp.html-d0e1b88a.js +1 -1
  164. package/docs/assets/toast.html-58ecbe21.js +1 -1
  165. package/docs/assets/toast.html-c9b9d36b.js +6 -6
  166. package/docs/assets/toolbar.html-83d9f97c.js +1 -1
  167. package/docs/assets/toolbar.html-ff7b8c92.js +1 -1
  168. package/docs/assets/tree.html-d07cbe79.js +23 -23
  169. package/docs/assets/tree.html-ea04193e.js +1 -1
  170. package/docs/assets/uploader-query.html-05590718.js +1 -1
  171. package/docs/assets/uploader-query.html-3175bac5.js +1 -1
  172. package/docs/assets/uploader.html-36da4394.js +2 -2
  173. package/docs/assets/uploader.html-6b5f3079.js +1 -1
  174. package/docs/assets/uploader.html-b9340b57.js +1 -1
  175. package/docs/assets/uploader.html-bc1c22e3.js +1 -1
  176. package/docs/assets/value-format.html-8ae3d47d.js +1 -1
  177. package/docs/assets/value-format.html-afa99b3d.js +1 -1
  178. package/docs/components/column-title.html +35 -35
  179. package/docs/components/data.html +62 -62
  180. package/docs/components/dialog.html +33 -33
  181. package/docs/components/dragger.html +33 -33
  182. package/docs/components/editor-code.html +33 -33
  183. package/docs/components/empty.html +33 -33
  184. package/docs/components/field-date.html +33 -33
  185. package/docs/components/field-table.html +33 -33
  186. package/docs/components/field-text.html +33 -33
  187. package/docs/components/field-tree.html +33 -33
  188. package/docs/components/img.html +33 -33
  189. package/docs/components/input-number.html +33 -33
  190. package/docs/components/list-menu-item.html +33 -33
  191. package/docs/components/list-menu.html +33 -33
  192. package/docs/components/power-page.html +33 -33
  193. package/docs/components/price.html +33 -33
  194. package/docs/components/render.html +33 -33
  195. package/docs/components/search-item.html +33 -33
  196. package/docs/components/search.html +33 -33
  197. package/docs/components/select.html +33 -33
  198. package/docs/components/splitter.html +33 -33
  199. package/docs/components/table-column-fixed.html +33 -33
  200. package/docs/components/table-pagination.html +33 -33
  201. package/docs/components/table-splitter.html +33 -33
  202. package/docs/components/table-summary.html +33 -33
  203. package/docs/components/table.html +33 -33
  204. package/docs/components/thumbnail.html +33 -33
  205. package/docs/components/toolbar.html +33 -33
  206. package/docs/components/uploader-query.html +33 -33
  207. package/docs/components/uploader.html +33 -33
  208. package/docs/components/value-format.html +33 -33
  209. package/docs/css/index.css +3 -3
  210. package/docs/index.html +33 -33
  211. package/docs/utils/alert.html +37 -37
  212. package/docs/utils/area.html +74 -74
  213. package/docs/utils/arr.html +43 -43
  214. package/docs/utils/auth.html +40 -40
  215. package/docs/utils/bus.html +38 -38
  216. package/docs/utils/confirm.html +42 -42
  217. package/docs/utils/copy.html +45 -45
  218. package/docs/utils/dialog.html +100 -100
  219. package/docs/utils/dict.html +55 -55
  220. package/docs/utils/dictOptions.html +37 -37
  221. package/docs/utils/form.html +34 -34
  222. package/docs/utils/getData.html +66 -66
  223. package/docs/utils/getFile.html +35 -35
  224. package/docs/utils/getImage.html +35 -35
  225. package/docs/utils/getTime.html +52 -52
  226. package/docs/utils/index.html +33 -33
  227. package/docs/utils/loading.html +38 -38
  228. package/docs/utils/notify.html +40 -40
  229. package/docs/utils/power.html +125 -125
  230. package/docs/utils/previewImage.html +34 -34
  231. package/docs/utils/price.html +51 -51
  232. package/docs/utils/rule.html +45 -45
  233. package/docs/utils/ruleValid.html +46 -46
  234. package/docs/utils/symbols.html +53 -53
  235. package/docs/utils/table.html +70 -70
  236. package/docs/utils/timestamp.html +45 -45
  237. package/docs/utils/toast.html +38 -38
  238. package/docs/utils/tree.html +55 -55
  239. package/docs/utils/uploader.html +34 -34
  240. package/package.json +25 -25
  241. package/sass/common.scss +184 -184
  242. package/sass/index.scss +12 -12
  243. package/sass/line.scss +39 -39
  244. package/sass/quasar/btn.scss +46 -46
  245. package/sass/quasar/common.scss +3 -3
  246. package/sass/quasar/drawer.scss +6 -6
  247. package/sass/quasar/field.scss +259 -259
  248. package/sass/quasar/loading.scss +6 -6
  249. package/sass/quasar/table.scss +168 -168
  250. package/sass/quasar/toolbar.scss +22 -22
  251. package/sass/variables.scss +140 -140
  252. package/store/index.js +29 -29
  253. package/utils/$auth.js +128 -128
  254. package/utils/$form.js +72 -72
  255. package/utils/$power.js +1494 -1492
  256. package/utils/$render.js +75 -75
  257. package/utils/$rule.js +13 -13
  258. package/utils/$ruleValid.js +10 -10
  259. package/utils/$search.js +416 -416
  260. package/utils/$table.js +1348 -1276
  261. package/utils/$tree.js +682 -682
  262. package/utils/alert.js +12 -12
  263. package/utils/area.js +400 -400
  264. package/utils/arr.js +51 -51
  265. package/utils/bus.js +6 -6
  266. package/utils/config.js +66 -66
  267. package/utils/confirm.js +11 -11
  268. package/utils/copy.js +30 -30
  269. package/utils/dialog.js +36 -36
  270. package/utils/dict.js +21 -21
  271. package/utils/dictOptions.js +28 -28
  272. package/utils/getData.js +88 -88
  273. package/utils/getFile.js +67 -67
  274. package/utils/getImage.js +276 -276
  275. package/utils/getTime.js +113 -113
  276. package/utils/index.js +67 -67
  277. package/utils/loading.js +15 -15
  278. package/utils/notify.js +13 -13
  279. package/utils/play.js +40 -40
  280. package/utils/previewImage.js +14 -14
  281. package/utils/price.js +18 -18
  282. package/utils/symbols.js +18 -18
  283. package/utils/timestamp.js +18 -18
  284. package/utils/toast.js +13 -13
  285. package/utils/uploader.js +2114 -2114
  286. package/utils/useAuth.js +30 -30
  287. package/utils/useFileUrl.js +26 -26
  288. package/utils/useRouter.js +47 -47
  289. package/utils/useSearch.js +562 -562
@@ -1,513 +1,513 @@
1
- <template>
2
- <q-table
3
- class="n-table"
4
- :columns="columns"
5
- :rows="currentRows"
6
- :virtual-scroll-slice-size="virtualScrollItemSize"
7
- v-bind="$attrs"
8
- >
9
- <!-- 展开子数据插槽 -->
10
- <template
11
- v-slot:[slotNames.expandName]="props"
12
- v-if="hasChildren"
13
- >
14
- <q-td
15
- class="row no-wrap items-center "
16
- :style="{ paddingLeft: (meta[props.key].level * 16) + 'px' }"
17
- :props="props"
18
- >
19
- <!-- 旋转器 -->
20
- <q-spinner
21
- class="q-tree__spinner q-ml-sm"
22
- :color="iconColor"
23
- v-if="meta[props.key].lazy === 'loading'"
24
- />
25
-
26
- <!-- 箭头 -->
27
- <template v-else>
28
- <q-icon
29
- class="q-tree__arrow q-ml-sm"
30
- :name="computedIcon"
31
- :color="iconColor"
32
- :class="`${meta[props.key].expanded ? 'q-tree__arrow--rotate' : ''}`"
33
- @click="onExpandClick(props, $event)"
34
- v-if="meta[props.key].isParent || meta[props.key].lazy === true"
35
- />
36
- <span class="q-icon n-table__arrow-noop q-ml-sm" v-else></span>
37
- </template>
38
-
39
- <!-- 如果有插槽 -->
40
- <slot
41
- :name="slotNames.expandName"
42
- v-bind="props"
43
- v-if="slotNames.hasExpandSlot"
44
- />
45
- <!-- 否则显示值 -->
46
- <span v-else>{{getCellValue(props.col, props.row)}}</span>
47
- </q-td>
48
- </template>
49
-
50
- <!-- 单元格插槽 -->
51
- <template
52
- v-for="slotName in slotNames.bodyCell"
53
- v-slot:[slotName]="props"
54
- >
55
- <q-td :props="props">
56
- <slot
57
- :name="slotName"
58
- v-bind="props"
59
- />
60
- </q-td>
61
- </template>
62
-
63
- <!-- 其他插槽 -->
64
- <template
65
- v-for="slotName in slotNames.other"
66
- v-slot:[slotName]="props"
67
- >
68
- <slot
69
- :name="slotName"
70
- v-bind="props"
71
- />
72
- </template>
73
-
74
- </q-table>
75
- </template>
76
-
77
- <script>
78
- import { ref, watch, computed, getCurrentInstance, nextTick } from 'vue'
79
- import { stopAndPrevent } from 'quasar/src/utils/event'
80
-
81
- import $n_has from 'lodash/has'
82
-
83
- import $n_isValidArray from '@netang/utils/isValidArray'
84
- import $n_indexOf from '@netang/utils/indexOf'
85
- import $n_forIn from '@netang/utils/forIn'
86
-
87
- export default {
88
-
89
- /**
90
- * 标识
91
- */
92
- name: 'NTable',
93
-
94
- /**
95
- * 声明属性
96
- */
97
- props: {
98
- // 行数据
99
- rows: {
100
- type: Array,
101
- default: () => []
102
- },
103
- // 定义每一行的唯一键的每一行属性
104
- rowKey: {
105
- type: [ String, Function ],
106
- default: 'id'
107
- },
108
- // 头部列数据
109
- columns: Array,
110
- // 已展开数据数组
111
- expanded: Array, // v-model:expanded
112
- // 以像素为单位的默认行大小
113
- virtualScrollItemSize: {
114
- type: [ Number, String ],
115
- default: 50,
116
- },
117
-
118
- // 【覆盖声明】-------------------------------------------------------
119
-
120
- // 是否默认展开所有行, 当 Table 包含展开行存在或者为树形表格时有效
121
- defaultExpandAll: Boolean,
122
- // 子数据属性名称
123
- childrenKey: {
124
- type: String,
125
- default: 'children'
126
- },
127
- icon: String,
128
- iconColor: {
129
- type: String,
130
- default: 'grey'
131
- },
132
- },
133
-
134
- /**
135
- * 组合式
136
- */
137
- setup(props, { slots, emit }) {
138
-
139
- const { proxy } = getCurrentInstance()
140
- const { $q } = proxy
141
-
142
- // 懒加载
143
- const lazy = ref({})
144
- // 已展开节点数组
145
- const innerExpanded = ref(props.expanded || [])
146
-
147
- // ==========【计算属性】==========================================================================================
148
-
149
- /**
150
- * 获取每一行的唯一键的每一行属性
151
- */
152
- const getRowKey = computed(() => (
153
- typeof props.rowKey === 'function'
154
- ? props.rowKey
155
- : row => row[ props.rowKey ]
156
- ))
157
-
158
- /**
159
- * 图标
160
- */
161
- const computedIcon = computed(() => props.icon || $q.iconSet.tree.icon)
162
-
163
- /**
164
- * 是否有子数据
165
- */
166
- const hasChildren = computed(function() {
167
- if (
168
- $n_isValidArray(props.rows)
169
- && $n_isValidArray(props.columns)
170
- && props.columns[0].name
171
- ) {
172
- for (const item of props.rows) {
173
- // 如果有子数据
174
- if (
175
- $n_has(item, props.childrenKey)
176
- && $n_isValidArray(item[props.childrenKey])
177
- ) {
178
- return true
179
- }
180
- }
181
- }
182
- return false
183
- })
184
-
185
- /**
186
- * meta
187
- */
188
- const meta = computed(function () {
189
-
190
- const meta = {}
191
-
192
- function travel(row, level, parent) {
193
-
194
- // 唯一键值
195
- const key = getRowKey.value(row)
196
- // 是否为父级
197
- const isParent = $n_has(row, props.childrenKey) && $n_isValidArray(row[props.childrenKey])
198
- // 是否可展开
199
- // const expandable = row.expandable !== false
200
-
201
- // 懒加载
202
- let localLazy = row.lazy
203
- if (
204
- localLazy === true
205
- && lazy.value[ key ] !== void 0
206
- && Array.isArray(row[ props.childrenKey ]) === true
207
- ) {
208
- localLazy = lazy.value[ key ]
209
- }
210
-
211
- const m = {
212
- key,
213
- level,
214
- parent,
215
- isParent,
216
- lazy: localLazy,
217
- // link: row.disabled !== true && (selectable === true || (expandable === true && (isParent === true || localLazy === true))),
218
- children: [],
219
- // matchesFilter: props.filter ? computedFilterMethod.value(row, props.filter) : true,
220
-
221
- // 是否已展开
222
- expanded: isParent ? innerExpanded.value.includes(key) : false,
223
- // expandable,
224
- }
225
-
226
- meta[ key ] = m
227
-
228
- // 如果为父级
229
- if (isParent) {
230
- // m.childrens = row[ props.childrenKey ]
231
- m.children = row[ props.childrenKey ].map(n => travel(n, level + 1, m))
232
- }
233
-
234
- return m
235
- }
236
-
237
- props.rows.forEach(row => travel(row, 0, null))
238
- return meta
239
- })
240
-
241
- /**
242
- * 当前行数据
243
- */
244
- const currentRows = computed(function() {
245
-
246
- // 如果有子数据
247
- if (hasChildren.value) {
248
- return getRows(props.rows, 0, 0)
249
- }
250
-
251
- // 否则返回原始行数据
252
- return props.rows
253
- })
254
-
255
- /**
256
- * 插槽标识
257
- */
258
- const slotNames = computed(function() {
259
-
260
- // 展开插槽标识
261
- let expandName = hasChildren.value ? `body-cell-${props.columns[0].name}` : ''
262
- // 是否存在展开插槽
263
- let hasExpandSlot = expandName && $n_has(slots, expandName)
264
- // 单元格插槽标识
265
- const bodyCell = []
266
- // 其他插槽标识
267
- const other = []
268
-
269
- $n_forIn(slots, function (value, key) {
270
- if (key.startsWith('body-cell-')) {
271
- if (! hasExpandSlot || key !== expandName) {
272
- bodyCell.push(key)
273
- }
274
- } else {
275
- other.push(key)
276
- }
277
- })
278
-
279
- return {
280
- // 展开插槽标识
281
- expandName,
282
- // 是否存在展开插槽
283
- hasExpandSlot,
284
- // 单元格插槽标识
285
- bodyCell,
286
- // 其他插槽标识
287
- other,
288
- }
289
- })
290
-
291
- // ==========【监听数据】=========================================================================================
292
-
293
- /**
294
- * 监听已展开节点数据
295
- */
296
- watch(() => props.expanded, val => {
297
- innerExpanded.value = val
298
- })
299
-
300
- /**
301
- * 监听行数据
302
- */
303
- watch(()=>props.rows, () => {
304
- if (props.defaultExpandAll) {
305
- expandAll()
306
- }
307
- }, {
308
- // 深度监听
309
- deep: true,
310
- // 立即执行
311
- immediate: true,
312
- })
313
-
314
- // ==========【方法】=============================================================================================
315
-
316
- /**
317
- * 获取行数据
318
- */
319
- function getRows(rows, __level, __parentKey) {
320
-
321
- const lists = []
322
-
323
- for (const row of rows) {
324
-
325
- lists.push(row)
326
-
327
- const key = getRowKey.value(row)
328
- const m = meta.value[ key ]
329
-
330
- // 如果有子数据
331
- if (
332
- m.isParent
333
- && $n_indexOf(innerExpanded.value, key) > -1
334
- ) {
335
- const childRows = getRows(row[ props.childrenKey ])
336
- if (childRows.length) {
337
- lists.push(...childRows)
338
- }
339
- }
340
- }
341
-
342
- return lists
343
- }
344
-
345
- /**
346
- * 展开点击
347
- */
348
- function onExpandClick (props, e) {
349
- if (e !== void 0) {
350
- stopAndPrevent(e)
351
- }
352
-
353
- const m = meta.value[props.key]
354
-
355
- // keyboard !== true && meta.selectable !== false && blur(meta.key)
356
- setExpanded(props.key, ! m.expanded, props.row, m)
357
- }
358
-
359
- /**
360
- * 在给定键的节点处展开树
361
- */
362
- function setExpanded (key, state, row, m) {
363
-
364
- if (m.lazy && m.lazy !== 'loaded') {
365
- if (m.lazy === 'loading') {
366
- return
367
- }
368
-
369
- lazy.value[ key ] = 'loading'
370
- if (Array.isArray(row[ props.childrenKey ]) !== true) {
371
- row[ props.childrenKey ] = []
372
- }
373
- emit('lazyLoad', {
374
- row,
375
- key,
376
- done: children => {
377
- lazy.value[ key ] = 'loaded'
378
- row[ props.childrenKey ] = Array.isArray(children) === true ? children : []
379
- nextTick(() => {
380
- const localMeta = meta.value[ key ]
381
- if (localMeta && localMeta.isParent === true) {
382
- localSetExpanded(key, true)
383
- }
384
- })
385
- },
386
- fail: () => {
387
- delete lazy.value[ key ]
388
- if (row[ props.childrenKey ].length === 0) {
389
- delete row[ props.childrenKey ]
390
- }
391
- }
392
- })
393
-
394
- } else if (m.isParent === true) {
395
- localSetExpanded(key, state)
396
- }
397
- }
398
-
399
- function localSetExpanded (key, state) {
400
- let target = innerExpanded.value
401
- const shouldEmit = props.expanded !== void 0
402
-
403
- if (shouldEmit === true) {
404
- target = target.slice()
405
- }
406
-
407
- if (state) {
408
- // if (props.accordion) {
409
- // if (meta.value[ key ]) {
410
- // const collapse = []
411
- // if (meta.value[ key ].parent) {
412
- // meta.value[ key ].parent.children.forEach(m => {
413
- // if (m.key !== key && m.expandable === true) {
414
- // collapse.push(m.key)
415
- // }
416
- // })
417
- // }
418
- // else {
419
- // props.nodes.forEach(node => {
420
- // const k = node[ props.nodeKey ]
421
- // if (k !== key) {
422
- // collapse.push(k)
423
- // }
424
- // })
425
- // }
426
- // if (collapse.length > 0) {
427
- // target = target.filter(k => collapse.includes(k) === false)
428
- // }
429
- // }
430
- // }
431
-
432
- target = target.concat([ key ])
433
- .filter((key, index, self) => self.indexOf(key) === index)
434
- }
435
- else {
436
- target = target.filter(k => k !== key)
437
- }
438
-
439
- if (shouldEmit === true) {
440
- emit('update:expanded', target)
441
- }
442
- else {
443
- innerExpanded.value = target
444
- }
445
- }
446
-
447
- function getCellValue (col, row) {
448
- const val = typeof col.field === 'function' ? col.field(row) : row[ col.field ]
449
- return col.format !== void 0 ? col.format(val, row) : val
450
- }
451
-
452
- /**
453
- * 用于折叠所有分支
454
- */
455
- function collapseAll () {
456
- if (props.expanded !== void 0) {
457
- emit('update:expanded', [])
458
- }
459
- else {
460
- innerExpanded.value = []
461
- }
462
- }
463
-
464
- /**
465
- * 用于展开所有分支
466
- */
467
- function expandAll () {
468
-
469
- if (! hasChildren.value) {
470
- return
471
- }
472
-
473
- const expanded = innerExpanded.value
474
-
475
- const travel = row => {
476
- if (
477
- $n_has(row, props.childrenKey)
478
- && $n_isValidArray(row[props.childrenKey])
479
- ) {
480
- expanded.push(row[ props.rowKey ])
481
- row[ props.childrenKey ].forEach(travel)
482
- }
483
- }
484
-
485
- props.rows.forEach(travel)
486
-
487
- if (props.expanded !== void 0) {
488
- emit('update:expanded', expanded)
489
-
490
- } else {
491
- innerExpanded.value = expanded
492
- }
493
- }
494
-
495
- // ==========【返回】=============================================================================================
496
-
497
- return {
498
- // 当前行数据
499
- currentRows,
500
- hasChildren,
501
- // 插槽标识
502
- slotNames,
503
- computedIcon,
504
- meta,
505
-
506
- onExpandClick,
507
- expandAll,
508
- collapseAll,
509
- getCellValue,
510
- }
511
- },
512
- }
513
- </script>
1
+ <template>
2
+ <q-table
3
+ class="n-table"
4
+ :columns="columns"
5
+ :rows="currentRows"
6
+ :virtual-scroll-slice-size="virtualScrollItemSize"
7
+ v-bind="$attrs"
8
+ >
9
+ <!-- 展开子数据插槽 -->
10
+ <template
11
+ v-slot:[slotNames.expandName]="props"
12
+ v-if="hasChildren"
13
+ >
14
+ <q-td
15
+ class="row no-wrap items-center "
16
+ :style="{ paddingLeft: (meta[props.key].level * 16) + 'px' }"
17
+ :props="props"
18
+ >
19
+ <!-- 旋转器 -->
20
+ <q-spinner
21
+ class="q-tree__spinner q-ml-sm"
22
+ :color="iconColor"
23
+ v-if="meta[props.key].lazy === 'loading'"
24
+ />
25
+
26
+ <!-- 箭头 -->
27
+ <template v-else>
28
+ <q-icon
29
+ class="q-tree__arrow q-ml-sm"
30
+ :name="computedIcon"
31
+ :color="iconColor"
32
+ :class="`${meta[props.key].expanded ? 'q-tree__arrow--rotate' : ''}`"
33
+ @click="onExpandClick(props, $event)"
34
+ v-if="meta[props.key].isParent || meta[props.key].lazy === true"
35
+ />
36
+ <span class="q-icon n-table__arrow-noop q-ml-sm" v-else></span>
37
+ </template>
38
+
39
+ <!-- 如果有插槽 -->
40
+ <slot
41
+ :name="slotNames.expandName"
42
+ v-bind="props"
43
+ v-if="slotNames.hasExpandSlot"
44
+ />
45
+ <!-- 否则显示值 -->
46
+ <span v-else>{{getCellValue(props.col, props.row)}}</span>
47
+ </q-td>
48
+ </template>
49
+
50
+ <!-- 单元格插槽 -->
51
+ <template
52
+ v-for="slotName in slotNames.bodyCell"
53
+ v-slot:[slotName]="props"
54
+ >
55
+ <q-td :props="props">
56
+ <slot
57
+ :name="slotName"
58
+ v-bind="props"
59
+ />
60
+ </q-td>
61
+ </template>
62
+
63
+ <!-- 其他插槽 -->
64
+ <template
65
+ v-for="slotName in slotNames.other"
66
+ v-slot:[slotName]="props"
67
+ >
68
+ <slot
69
+ :name="slotName"
70
+ v-bind="props"
71
+ />
72
+ </template>
73
+
74
+ </q-table>
75
+ </template>
76
+
77
+ <script>
78
+ import { ref, watch, computed, getCurrentInstance, nextTick } from 'vue'
79
+ import { stopAndPrevent } from 'quasar/src/utils/event'
80
+
81
+ import $n_has from 'lodash/has'
82
+
83
+ import $n_isValidArray from '@netang/utils/isValidArray'
84
+ import $n_indexOf from '@netang/utils/indexOf'
85
+ import $n_forIn from '@netang/utils/forIn'
86
+
87
+ export default {
88
+
89
+ /**
90
+ * 标识
91
+ */
92
+ name: 'NTable',
93
+
94
+ /**
95
+ * 声明属性
96
+ */
97
+ props: {
98
+ // 行数据
99
+ rows: {
100
+ type: Array,
101
+ default: () => []
102
+ },
103
+ // 定义每一行的唯一键的每一行属性
104
+ rowKey: {
105
+ type: [ String, Function ],
106
+ default: 'id'
107
+ },
108
+ // 头部列数据
109
+ columns: Array,
110
+ // 已展开数据数组
111
+ expanded: Array, // v-model:expanded
112
+ // 以像素为单位的默认行大小
113
+ virtualScrollItemSize: {
114
+ type: [ Number, String ],
115
+ default: 50,
116
+ },
117
+
118
+ // 【覆盖声明】-------------------------------------------------------
119
+
120
+ // 是否默认展开所有行, 当 Table 包含展开行存在或者为树形表格时有效
121
+ defaultExpandAll: Boolean,
122
+ // 子数据属性名称
123
+ childrenKey: {
124
+ type: String,
125
+ default: 'children'
126
+ },
127
+ icon: String,
128
+ iconColor: {
129
+ type: String,
130
+ default: 'grey'
131
+ },
132
+ },
133
+
134
+ /**
135
+ * 组合式
136
+ */
137
+ setup(props, { slots, emit }) {
138
+
139
+ const { proxy } = getCurrentInstance()
140
+ const { $q } = proxy
141
+
142
+ // 懒加载
143
+ const lazy = ref({})
144
+ // 已展开节点数组
145
+ const innerExpanded = ref(props.expanded || [])
146
+
147
+ // ==========【计算属性】==========================================================================================
148
+
149
+ /**
150
+ * 获取每一行的唯一键的每一行属性
151
+ */
152
+ const getRowKey = computed(() => (
153
+ typeof props.rowKey === 'function'
154
+ ? props.rowKey
155
+ : row => row[ props.rowKey ]
156
+ ))
157
+
158
+ /**
159
+ * 图标
160
+ */
161
+ const computedIcon = computed(() => props.icon || $q.iconSet.tree.icon)
162
+
163
+ /**
164
+ * 是否有子数据
165
+ */
166
+ const hasChildren = computed(function() {
167
+ if (
168
+ $n_isValidArray(props.rows)
169
+ && $n_isValidArray(props.columns)
170
+ && props.columns[0].name
171
+ ) {
172
+ for (const item of props.rows) {
173
+ // 如果有子数据
174
+ if (
175
+ $n_has(item, props.childrenKey)
176
+ && $n_isValidArray(item[props.childrenKey])
177
+ ) {
178
+ return true
179
+ }
180
+ }
181
+ }
182
+ return false
183
+ })
184
+
185
+ /**
186
+ * meta
187
+ */
188
+ const meta = computed(function () {
189
+
190
+ const meta = {}
191
+
192
+ function travel(row, level, parent) {
193
+
194
+ // 唯一键值
195
+ const key = getRowKey.value(row)
196
+ // 是否为父级
197
+ const isParent = $n_has(row, props.childrenKey) && $n_isValidArray(row[props.childrenKey])
198
+ // 是否可展开
199
+ // const expandable = row.expandable !== false
200
+
201
+ // 懒加载
202
+ let localLazy = row.lazy
203
+ if (
204
+ localLazy === true
205
+ && lazy.value[ key ] !== void 0
206
+ && Array.isArray(row[ props.childrenKey ]) === true
207
+ ) {
208
+ localLazy = lazy.value[ key ]
209
+ }
210
+
211
+ const m = {
212
+ key,
213
+ level,
214
+ parent,
215
+ isParent,
216
+ lazy: localLazy,
217
+ // link: row.disabled !== true && (selectable === true || (expandable === true && (isParent === true || localLazy === true))),
218
+ children: [],
219
+ // matchesFilter: props.filter ? computedFilterMethod.value(row, props.filter) : true,
220
+
221
+ // 是否已展开
222
+ expanded: isParent ? innerExpanded.value.includes(key) : false,
223
+ // expandable,
224
+ }
225
+
226
+ meta[ key ] = m
227
+
228
+ // 如果为父级
229
+ if (isParent) {
230
+ // m.childrens = row[ props.childrenKey ]
231
+ m.children = row[ props.childrenKey ].map(n => travel(n, level + 1, m))
232
+ }
233
+
234
+ return m
235
+ }
236
+
237
+ props.rows.forEach(row => travel(row, 0, null))
238
+ return meta
239
+ })
240
+
241
+ /**
242
+ * 当前行数据
243
+ */
244
+ const currentRows = computed(function() {
245
+
246
+ // 如果有子数据
247
+ if (hasChildren.value) {
248
+ return getRows(props.rows, 0, 0)
249
+ }
250
+
251
+ // 否则返回原始行数据
252
+ return props.rows
253
+ })
254
+
255
+ /**
256
+ * 插槽标识
257
+ */
258
+ const slotNames = computed(function() {
259
+
260
+ // 展开插槽标识
261
+ let expandName = hasChildren.value ? `body-cell-${props.columns[0].name}` : ''
262
+ // 是否存在展开插槽
263
+ let hasExpandSlot = expandName && $n_has(slots, expandName)
264
+ // 单元格插槽标识
265
+ const bodyCell = []
266
+ // 其他插槽标识
267
+ const other = []
268
+
269
+ $n_forIn(slots, function (value, key) {
270
+ if (key.startsWith('body-cell-')) {
271
+ if (! hasExpandSlot || key !== expandName) {
272
+ bodyCell.push(key)
273
+ }
274
+ } else {
275
+ other.push(key)
276
+ }
277
+ })
278
+
279
+ return {
280
+ // 展开插槽标识
281
+ expandName,
282
+ // 是否存在展开插槽
283
+ hasExpandSlot,
284
+ // 单元格插槽标识
285
+ bodyCell,
286
+ // 其他插槽标识
287
+ other,
288
+ }
289
+ })
290
+
291
+ // ==========【监听数据】=========================================================================================
292
+
293
+ /**
294
+ * 监听已展开节点数据
295
+ */
296
+ watch(() => props.expanded, val => {
297
+ innerExpanded.value = val
298
+ })
299
+
300
+ /**
301
+ * 监听行数据
302
+ */
303
+ watch(()=>props.rows, () => {
304
+ if (props.defaultExpandAll) {
305
+ expandAll()
306
+ }
307
+ }, {
308
+ // 深度监听
309
+ deep: true,
310
+ // 立即执行
311
+ immediate: true,
312
+ })
313
+
314
+ // ==========【方法】=============================================================================================
315
+
316
+ /**
317
+ * 获取行数据
318
+ */
319
+ function getRows(rows, __level, __parentKey) {
320
+
321
+ const lists = []
322
+
323
+ for (const row of rows) {
324
+
325
+ lists.push(row)
326
+
327
+ const key = getRowKey.value(row)
328
+ const m = meta.value[ key ]
329
+
330
+ // 如果有子数据
331
+ if (
332
+ m.isParent
333
+ && $n_indexOf(innerExpanded.value, key) > -1
334
+ ) {
335
+ const childRows = getRows(row[ props.childrenKey ])
336
+ if (childRows.length) {
337
+ lists.push(...childRows)
338
+ }
339
+ }
340
+ }
341
+
342
+ return lists
343
+ }
344
+
345
+ /**
346
+ * 展开点击
347
+ */
348
+ function onExpandClick (props, e) {
349
+ if (e !== void 0) {
350
+ stopAndPrevent(e)
351
+ }
352
+
353
+ const m = meta.value[props.key]
354
+
355
+ // keyboard !== true && meta.selectable !== false && blur(meta.key)
356
+ setExpanded(props.key, ! m.expanded, props.row, m)
357
+ }
358
+
359
+ /**
360
+ * 在给定键的节点处展开树
361
+ */
362
+ function setExpanded (key, state, row, m) {
363
+
364
+ if (m.lazy && m.lazy !== 'loaded') {
365
+ if (m.lazy === 'loading') {
366
+ return
367
+ }
368
+
369
+ lazy.value[ key ] = 'loading'
370
+ if (Array.isArray(row[ props.childrenKey ]) !== true) {
371
+ row[ props.childrenKey ] = []
372
+ }
373
+ emit('lazyLoad', {
374
+ row,
375
+ key,
376
+ done: children => {
377
+ lazy.value[ key ] = 'loaded'
378
+ row[ props.childrenKey ] = Array.isArray(children) === true ? children : []
379
+ nextTick(() => {
380
+ const localMeta = meta.value[ key ]
381
+ if (localMeta && localMeta.isParent === true) {
382
+ localSetExpanded(key, true)
383
+ }
384
+ })
385
+ },
386
+ fail: () => {
387
+ delete lazy.value[ key ]
388
+ if (row[ props.childrenKey ].length === 0) {
389
+ delete row[ props.childrenKey ]
390
+ }
391
+ }
392
+ })
393
+
394
+ } else if (m.isParent === true) {
395
+ localSetExpanded(key, state)
396
+ }
397
+ }
398
+
399
+ function localSetExpanded (key, state) {
400
+ let target = innerExpanded.value
401
+ const shouldEmit = props.expanded !== void 0
402
+
403
+ if (shouldEmit === true) {
404
+ target = target.slice()
405
+ }
406
+
407
+ if (state) {
408
+ // if (props.accordion) {
409
+ // if (meta.value[ key ]) {
410
+ // const collapse = []
411
+ // if (meta.value[ key ].parent) {
412
+ // meta.value[ key ].parent.children.forEach(m => {
413
+ // if (m.key !== key && m.expandable === true) {
414
+ // collapse.push(m.key)
415
+ // }
416
+ // })
417
+ // }
418
+ // else {
419
+ // props.nodes.forEach(node => {
420
+ // const k = node[ props.nodeKey ]
421
+ // if (k !== key) {
422
+ // collapse.push(k)
423
+ // }
424
+ // })
425
+ // }
426
+ // if (collapse.length > 0) {
427
+ // target = target.filter(k => collapse.includes(k) === false)
428
+ // }
429
+ // }
430
+ // }
431
+
432
+ target = target.concat([ key ])
433
+ .filter((key, index, self) => self.indexOf(key) === index)
434
+ }
435
+ else {
436
+ target = target.filter(k => k !== key)
437
+ }
438
+
439
+ if (shouldEmit === true) {
440
+ emit('update:expanded', target)
441
+ }
442
+ else {
443
+ innerExpanded.value = target
444
+ }
445
+ }
446
+
447
+ function getCellValue (col, row) {
448
+ const val = typeof col.field === 'function' ? col.field(row) : row[ col.field ]
449
+ return col.format !== void 0 ? col.format(val, row) : val
450
+ }
451
+
452
+ /**
453
+ * 用于折叠所有分支
454
+ */
455
+ function collapseAll () {
456
+ if (props.expanded !== void 0) {
457
+ emit('update:expanded', [])
458
+ }
459
+ else {
460
+ innerExpanded.value = []
461
+ }
462
+ }
463
+
464
+ /**
465
+ * 用于展开所有分支
466
+ */
467
+ function expandAll () {
468
+
469
+ if (! hasChildren.value) {
470
+ return
471
+ }
472
+
473
+ const expanded = innerExpanded.value
474
+
475
+ const travel = row => {
476
+ if (
477
+ $n_has(row, props.childrenKey)
478
+ && $n_isValidArray(row[props.childrenKey])
479
+ ) {
480
+ expanded.push(row[ props.rowKey ])
481
+ row[ props.childrenKey ].forEach(travel)
482
+ }
483
+ }
484
+
485
+ props.rows.forEach(travel)
486
+
487
+ if (props.expanded !== void 0) {
488
+ emit('update:expanded', expanded)
489
+
490
+ } else {
491
+ innerExpanded.value = expanded
492
+ }
493
+ }
494
+
495
+ // ==========【返回】=============================================================================================
496
+
497
+ return {
498
+ // 当前行数据
499
+ currentRows,
500
+ hasChildren,
501
+ // 插槽标识
502
+ slotNames,
503
+ computedIcon,
504
+ meta,
505
+
506
+ onExpandClick,
507
+ expandAll,
508
+ collapseAll,
509
+ getCellValue,
510
+ }
511
+ },
512
+ }
513
+ </script>