@netang/quasar 0.0.20

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 (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -0
  3. package/components/column-title/index.vue +32 -0
  4. package/components/dialog/components/index.js +6 -0
  5. package/components/dialog/components/move-to-tree/index.vue +150 -0
  6. package/components/dialog/index.vue +330 -0
  7. package/components/dialog-table/index.vue +92 -0
  8. package/components/dragger/index.vue +202 -0
  9. package/components/drawer/index.vue +262 -0
  10. package/components/field-date/index.vue +844 -0
  11. package/components/field-date/methods.js +100 -0
  12. package/components/field-table/index.vue +468 -0
  13. package/components/field-text/index.vue +167 -0
  14. package/components/field-tree/index.vue +435 -0
  15. package/components/input-number/index.vue +324 -0
  16. package/components/input-number/number.js +67 -0
  17. package/components/input-price-cent/index.vue +213 -0
  18. package/components/input-price-yuan/index.vue +179 -0
  19. package/components/layout/index.vue +119 -0
  20. package/components/list-menu/index.vue +137 -0
  21. package/components/list-menu-item/index.vue +79 -0
  22. package/components/power-data/index.vue +667 -0
  23. package/components/search/index.vue +176 -0
  24. package/components/search-item/index.vue +219 -0
  25. package/components/select/index.vue +71 -0
  26. package/components/select-filter/index.vue +75 -0
  27. package/components/table/index.vue +347 -0
  28. package/components/table-column-fixed/index.vue +68 -0
  29. package/components/table-pagination/index.vue +83 -0
  30. package/components/table-summary/index.vue +91 -0
  31. package/components/thumbnail/index.vue +87 -0
  32. package/components/toolbar/container.vue +31 -0
  33. package/components/toolbar/index.vue +405 -0
  34. package/components/uploader/index.vue +157 -0
  35. package/components/uploader-query/index.vue +731 -0
  36. package/package.json +21 -0
  37. package/sass/common.scss +165 -0
  38. package/sass/index.scss +14 -0
  39. package/sass/line.scss +39 -0
  40. package/sass/quasar/btn.scss +46 -0
  41. package/sass/quasar/common.scss +3 -0
  42. package/sass/quasar/dialog.scss +7 -0
  43. package/sass/quasar/drawer.scss +6 -0
  44. package/sass/quasar/field.scss +210 -0
  45. package/sass/quasar/loading.scss +6 -0
  46. package/sass/quasar/menu.scss +8 -0
  47. package/sass/quasar/table.scss +112 -0
  48. package/sass/quasar/toolbar.scss +22 -0
  49. package/store/index.js +32 -0
  50. package/utils/$area.js +387 -0
  51. package/utils/$auth.js +135 -0
  52. package/utils/$dialog.js +43 -0
  53. package/utils/$role.js +807 -0
  54. package/utils/$rule.js +17 -0
  55. package/utils/$search.js +336 -0
  56. package/utils/$table.js +802 -0
  57. package/utils/$tree.js +620 -0
  58. package/utils/$uploader.js +1029 -0
  59. package/utils/alert.js +10 -0
  60. package/utils/bus.js +6 -0
  61. package/utils/config.js +22 -0
  62. package/utils/confrim.js +11 -0
  63. package/utils/dict.js +44 -0
  64. package/utils/getData.js +61 -0
  65. package/utils/getFile.js +30 -0
  66. package/utils/getImage.js +136 -0
  67. package/utils/getTime.js +94 -0
  68. package/utils/http.js +251 -0
  69. package/utils/loading.js +13 -0
  70. package/utils/notify.js +13 -0
  71. package/utils/previewImage.js +8 -0
  72. package/utils/symbols.js +3 -0
  73. package/utils/timestamp.js +18 -0
  74. package/utils/toast.js +13 -0
  75. package/utils/uploader/aliyun.js +6 -0
  76. package/utils/uploader/local.js +8 -0
  77. package/utils/uploader/qiniu.js +311 -0
  78. package/utils/useAuth.js +26 -0
  79. package/utils/useRouter.js +36 -0
  80. package/utils/useUploader.js +58 -0
@@ -0,0 +1,347 @@
1
+ <template>
2
+ <n-layout
3
+ class="absolute-full"
4
+ :class="{
5
+ 'n-table--grid': tableGrid,
6
+ }"
7
+ view="lHr LpR lff"
8
+ container
9
+ :page-status="pageStatus"
10
+ :empty-description="emptyDescription"
11
+ >
12
+ <!-- 头部 -->
13
+ <n-toolbar
14
+ ref="tableToolbarRef"
15
+ :model-value="roleBtnLists"
16
+ v-model:table-grid="tableGrid"
17
+ v-model:table-visible-columns="tableVisibleColumns"
18
+ :query="tableQuery"
19
+ :table-columns="tableColumns"
20
+ :table-selected="tableSelected"
21
+ :table-refresh="tableRefresh"
22
+ v-bind="toolbarProps"
23
+ header
24
+ />
25
+ <!-- 左侧分类 -->
26
+ <n-drawer
27
+ side="left"
28
+ :width="200"
29
+ :min-width="150"
30
+ bordered
31
+ show
32
+ drag
33
+ :cache="currentUrl"
34
+ v-if="treeNodes.length"
35
+ >
36
+ <q-scroll-area class="absolute-full">
37
+
38
+ <!-- 树筛选 -->
39
+ <div class="q-pa-sm q-gutter-sm" v-if="treeFilter">
40
+ <q-input
41
+ v-model="treeFilterValue"
42
+ placeholder="搜索"
43
+ dense
44
+ outlined
45
+ clearable
46
+
47
+ />
48
+ </div>
49
+
50
+ <!-- 分类树 -->
51
+ <q-tree
52
+ color="grey-5"
53
+ ref="treeRef"
54
+ :nodes="treeNodes"
55
+ :filter="treeFilterValue"
56
+ :node-key="treeNodeKey"
57
+ :label-key="treeLabelKey"
58
+ selected-color="primary"
59
+ v-model:selected="treeSelected"
60
+ no-selection-unset
61
+ default-expand-all
62
+ />
63
+
64
+ </q-scroll-area>
65
+ </n-drawer>
66
+
67
+ <!-- 列表 -->
68
+ <q-page-container>
69
+ <q-page>
70
+ <q-table
71
+ ref="tableRef"
72
+ class="n-table absolute-full"
73
+ :class="{
74
+ 'n-table--last-fixed': showTableFixed,
75
+ }"
76
+ v-model:pagination="tablePagination"
77
+ v-model:selected="tableSelected"
78
+ :row-key="tableRowKey"
79
+ :rows="tableRows"
80
+ :columns="tableColumns"
81
+ :visible-columns="tableVisibleColumns"
82
+ :selection="tableSelection"
83
+ :loading="tableLoading"
84
+ :rows-per-page-options="tableRowsPerPageOptions"
85
+ :grid="tableGrid"
86
+ @row-click="tableRowClick"
87
+ @row-dblclick="tableRowDblclick"
88
+ @request="tableRequest"
89
+ flat
90
+ virtual-scroll
91
+ >
92
+ <!-- 图片 -->
93
+ <template
94
+ v-for="imgName in tableImgNames"
95
+ v-slot:[`body-cell-${imgName}`]="props"
96
+ >
97
+ <q-td :props="props">
98
+ <!-- 缩略图 -->
99
+ <n-thumbnail
100
+ :src="props.row[imgName]"
101
+ preview
102
+ />
103
+ </q-td>
104
+ </template>
105
+
106
+ <!-- 插槽 -->
107
+ <template
108
+ v-for="slotName in slotNames"
109
+ v-slot:[slotName]="props"
110
+ >
111
+ <q-td :props="props">
112
+ <slot
113
+ :name="slotName"
114
+ v-bind="props"
115
+ />
116
+ </q-td>
117
+ </template>
118
+
119
+ <!-- 操作 -->
120
+ <template v-slot:body-cell-settings="props">
121
+ <n-table-column-fixed
122
+ :props="props"
123
+ :role-btn-lists="tableFixedRoleBtnLists"
124
+ />
125
+ </template>
126
+
127
+ <!-- 合计 -->
128
+ <template v-slot:bottom-row="props" v-if="tableSummary">
129
+ <n-table-summary
130
+ :props="props"
131
+ :data="tableSummary"
132
+ :selection="tableSelection"
133
+ />
134
+ </template>
135
+
136
+ <!-- 翻页 -->
137
+ <template v-slot:pagination="props">
138
+ <n-table-pagination
139
+ :props="props"
140
+ :table-refresh="tableRefresh"
141
+ />
142
+ </template>
143
+ </q-table>
144
+ </q-page>
145
+ </q-page-container>
146
+
147
+ <!-- 右侧搜索 -->
148
+ <n-drawer
149
+ side="right"
150
+ :min-width="320"
151
+ bordered
152
+ drag
153
+ :cache="currentUrl"
154
+ show
155
+ v-if="! noSearch && tableSearchValue.length"
156
+ >
157
+ <!-- 搜索 -->
158
+ <n-search
159
+ v-model="tableSearchValue"
160
+ :options="tableSearchOptions"
161
+ :on-search="tableReload"
162
+ :on-reset="tableSearchReset"
163
+ />
164
+ </n-drawer>
165
+ </n-layout>
166
+ </template>
167
+
168
+ <script>
169
+ import { ref, onMounted, watch, computed } from 'vue'
170
+ import { useRoute } from 'vue-router'
171
+
172
+ export default {
173
+
174
+ /**
175
+ * 标识
176
+ */
177
+ name: 'NTable',
178
+
179
+ /**
180
+ * 声明属性
181
+ */
182
+ props: {
183
+ // 表格请求地址
184
+ url: String,
185
+ // 表格参数
186
+ tableParams: Object,
187
+ // 权限按钮列表
188
+ roleBtnLists: Array,
189
+ // 树节点唯一键值
190
+ treeNodeKey: {
191
+ type: String,
192
+ default: 'id',
193
+ },
194
+ // 树标签键值
195
+ treeLabelKey: {
196
+ type: String,
197
+ default: 'title',
198
+ },
199
+ // 树节点列表
200
+ treeNodes: {
201
+ type: Array,
202
+ default: ()=>[],
203
+ },
204
+ // 树节点点击
205
+ treeNodeClick: Function,
206
+ // 显示树筛选
207
+ treeFilter: Boolean,
208
+ // 页面状态
209
+ pageStatus: {
210
+ type: Boolean,
211
+ default: null,
212
+ },
213
+ // 空状态描述
214
+ emptyDescription: {
215
+ type: String,
216
+ default: '发生未知错误',
217
+ },
218
+ // 工具栏声明属性
219
+ toolbarProps: Object,
220
+ // 不显示搜索
221
+ noSearch: Boolean,
222
+ // 表格加载回调
223
+ load: Function,
224
+ },
225
+
226
+ /**
227
+ * 声明事件
228
+ */
229
+ emits: [
230
+ // 表格加载回调
231
+ 'load',
232
+ ],
233
+
234
+ /**
235
+ * 组合式
236
+ */
237
+ setup(props, { emit, slots }) {
238
+
239
+ // ==========【数据】============================================================================================
240
+
241
+ // 树节点
242
+ const treeRef = ref(null)
243
+
244
+ // 树筛选值
245
+ const treeFilterValue = ref('')
246
+
247
+ // 树选择数据
248
+ const treeSelected = ref('')
249
+
250
+ // 当前请求地址
251
+ const currentUrl = ref(props.url ? props.url : useRoute().fullPath)
252
+
253
+ // 表格参数
254
+ const tableParams = Object.assign({}, props.tableParams, {
255
+ // 请求地址
256
+ url: currentUrl.value,
257
+ // 权限按钮列表
258
+ roleBtnLists: computed(()=>props.roleBtnLists),
259
+ })
260
+
261
+ // 如果不显示搜索
262
+ if (props.noSearch) {
263
+ tableParams.search = false
264
+ }
265
+
266
+ // 创建表格
267
+ const $table = utils.$table.create(tableParams)
268
+
269
+ // ==========【计算属性】==========================================================================================
270
+
271
+ /**
272
+ * 插槽标识
273
+ */
274
+ const slotNames = computed(function() {
275
+ if (utils.isValidObject(slots)) {
276
+ return Object.keys(slots)
277
+ }
278
+ return []
279
+ })
280
+
281
+ // ==========【监听数据】=========================================================================================
282
+
283
+ /**
284
+ * 监听树选择数据
285
+ */
286
+ if (_.isFunction(props.treeNodeClick)) {
287
+ watch(treeSelected, function(nodeKey) {
288
+
289
+ // 树节点点击
290
+ const res = props.treeNodeClick({
291
+ nodeKey,
292
+ node: treeRef.value.getNodeByKey(nodeKey),
293
+ $table
294
+ })
295
+
296
+ if (! _.isNil(res)) {
297
+
298
+ if (res === false) {
299
+ return
300
+ }
301
+
302
+ if (utils.isValidObject(res)) {
303
+
304
+ // 设置表格传参
305
+ $table.tableQuery.value = res
306
+
307
+ // 表格重新加载
308
+ $table.tableReload()
309
+ }
310
+ }
311
+ })
312
+ }
313
+
314
+ // ==========【生命周期】=========================================================================================
315
+
316
+ /**
317
+ * 实例被挂载后调用
318
+ */
319
+ onMounted( async function() {
320
+
321
+ // 表格加载回调
322
+ emit('load', { $table })
323
+ await utils.runAsync(props.load)({ $table })
324
+ })
325
+
326
+ // ==========【返回】=============================================================================================
327
+
328
+ return {
329
+ // 解构表格实例
330
+ ...$table,
331
+
332
+ // 树节点
333
+ treeRef,
334
+ // 树筛选值
335
+ treeFilterValue,
336
+ // 树选择数据
337
+ treeSelected,
338
+
339
+ // 当前请求地址
340
+ currentUrl,
341
+
342
+ // 插槽 body 单元格标识
343
+ slotNames,
344
+ }
345
+ },
346
+ }
347
+ </script>
@@ -0,0 +1,68 @@
1
+ <template>
2
+ <q-td :props="props">
3
+ <div class="q-gutter-sm">
4
+ <q-btn
5
+ v-for="item in roleBtnLists"
6
+ :key="`btn-item-${item.id}`"
7
+ class="n-button-icon"
8
+ :icon="item.icon"
9
+ @click.prevent.stop="onClick(item)"
10
+ unelevated
11
+ round
12
+ >
13
+ <!-- 标题提示 -->
14
+ <q-tooltip>{{item.title}}</q-tooltip>
15
+ </q-btn>
16
+ </div>
17
+ </q-td>
18
+ </template>
19
+
20
+ <script>
21
+ import { inject } from 'vue'
22
+ import { NLayoutKey } from '../../utils/symbols'
23
+
24
+ export default {
25
+
26
+ /**
27
+ * 标识
28
+ */
29
+ name: 'NTableColumnFixed',
30
+
31
+ /**
32
+ * 声明属性
33
+ */
34
+ props: {
35
+ // 传值
36
+ props: Object,
37
+ // 权限按钮列表
38
+ roleBtnLists: Array,
39
+ },
40
+
41
+ /**
42
+ * 组合式
43
+ */
44
+ setup(props) {
45
+
46
+ // ==========【注入】============================================================================================
47
+
48
+ // 获取布局注入数据
49
+ const $nLayout = inject(NLayoutKey)
50
+
51
+ // ==========【方法】=============================================================================================
52
+
53
+ /**
54
+ * 点击
55
+ */
56
+ function onClick(item) {
57
+ $nLayout.data.role?.click(item, [ props.props.row ])
58
+ }
59
+
60
+ // ==========【返回】=============================================================================================
61
+
62
+ return {
63
+ // 点击
64
+ onClick,
65
+ }
66
+ },
67
+ }
68
+ </script>
@@ -0,0 +1,83 @@
1
+ <template>
2
+ <div>
3
+ <!-- 页码 -->
4
+ <span class="q-table__bottom-item">{{props.pagination.page}} / {{Math.ceil(props.pagination.rowsNumber / props.pagination.rowsPerPage)}}</span>
5
+
6
+ <!-- 第一页 -->
7
+ <q-btn
8
+ v-if="props.pagesNumber > 2"
9
+ icon="first_page"
10
+ color="grey-8"
11
+ round
12
+ dense
13
+ flat
14
+ :disable="props.isFirstPage"
15
+ @click="props.firstPage"
16
+ />
17
+
18
+ <!-- 上页 -->
19
+ <q-btn
20
+ icon="chevron_left"
21
+ color="grey-8"
22
+ round
23
+ dense
24
+ flat
25
+ :disable="props.isFirstPage"
26
+ @click="props.prevPage"
27
+ />
28
+
29
+ <!-- 下页 -->
30
+ <q-btn
31
+ icon="chevron_right"
32
+ color="grey-8"
33
+ round
34
+ dense
35
+ flat
36
+ :disable="props.isLastPage"
37
+ @click="props.nextPage"
38
+ />
39
+
40
+ <!-- 最后一页 -->
41
+ <q-btn
42
+ v-if="props.pagesNumber > 2"
43
+ icon="last_page"
44
+ color="grey-8"
45
+ round
46
+ dense
47
+ flat
48
+ :disable="props.isLastPage"
49
+ @click="props.lastPage"
50
+ />
51
+
52
+ <!-- 刷新 -->
53
+ <q-btn
54
+ icon="refresh"
55
+ color="grey-8"
56
+ round
57
+ dense
58
+ flat
59
+ @click="tableRefresh"
60
+ v-if="tableRefresh"
61
+ />
62
+ </div>
63
+ </template>
64
+
65
+ <script>
66
+ export default {
67
+
68
+ /**
69
+ * 标识
70
+ */
71
+ name: 'NTablePagination',
72
+
73
+ /**
74
+ * 声明属性
75
+ */
76
+ props: {
77
+ // 传值
78
+ props: Object,
79
+ // 表格刷新
80
+ tableRefresh: Function,
81
+ },
82
+ }
83
+ </script>
@@ -0,0 +1,91 @@
1
+ <template>
2
+ <q-tr class="q-table__bottom">
3
+ <q-td
4
+ v-for="(item, index) in columns"
5
+ :class="item.css"
6
+ >
7
+ <!-- 合计标题 -->
8
+ <span v-if="index === 0">合计</span>
9
+
10
+ <!-- 合计数据 -->
11
+ <span v-else-if="item.value">{{item.value}}</span>
12
+ </q-td>
13
+ </q-tr>
14
+ </template>
15
+
16
+ <script>
17
+ import { computed } from 'vue'
18
+
19
+ export default {
20
+
21
+ /**
22
+ * 标识
23
+ */
24
+ name: 'NTableSummary',
25
+
26
+ /**
27
+ * 声明属性
28
+ */
29
+ props: {
30
+ // 传值
31
+ props: Object,
32
+ // 选择类型, 可选值 single multiple none
33
+ selection: String,
34
+ // 表格合计数据
35
+ data: Object,
36
+ },
37
+
38
+ /**
39
+ * 组合式
40
+ */
41
+ setup(props) {
42
+
43
+ // ==========【计算属性】============================================================================================
44
+
45
+ const columns = computed(function () {
46
+
47
+ const lists = []
48
+
49
+ if (props.selection !== 'none') {
50
+ lists.push({
51
+ css: 'q-table--col-auto-width text-center',
52
+ name: '',
53
+ })
54
+ }
55
+
56
+ utils.forEach(_.get(props.props, 'cols'), function(item) {
57
+
58
+ const {
59
+ // 标识
60
+ name,
61
+ // 对齐方式
62
+ align,
63
+ } = item
64
+
65
+ const res = {
66
+ css: `text-${align}`,
67
+ name,
68
+ value: '',
69
+ }
70
+
71
+ // 如果有统计字段
72
+ if (_.has(props.data, name)) {
73
+ // 判断是否是价格
74
+ res.value = _.has(item, 'price') ? utils.price(props.data[name]) : props.data[name]
75
+ }
76
+
77
+ lists.push(res)
78
+ })
79
+
80
+ return lists
81
+ })
82
+
83
+ // ==========【返回】=============================================================================================
84
+
85
+ return {
86
+ // 栏目
87
+ columns,
88
+ }
89
+ },
90
+ }
91
+ </script>
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <q-img
3
+ :src="currentSrc"
4
+ :spinner-size="utils.px(size / 2)"
5
+ :width="utils.px(size)"
6
+ :height="utils.px(size)"
7
+ fit="fill"
8
+ v-if="currentSrc"
9
+ >
10
+ <!-- 预览点击 -->
11
+ <div
12
+ class="absolute-full transparent cursor-pointer"
13
+ @click.prevent.stop="onPreview"
14
+ @dblclick.prevent.stop="utils.noop"
15
+ v-if="preview"
16
+ ></div>
17
+ </q-img>
18
+ </template>
19
+
20
+ <script>
21
+ import { computed } from 'vue'
22
+ import { useQuasar } from 'quasar'
23
+
24
+
25
+ export default {
26
+
27
+ /**
28
+ * 标识
29
+ */
30
+ name: 'NThumbnail',
31
+
32
+ /**
33
+ * 声明属性
34
+ */
35
+ props: {
36
+ // 图片地址
37
+ src: [String, Array, Object],
38
+ // 图片尺寸
39
+ size: {
40
+ type: Number,
41
+ default: 40,
42
+ },
43
+ // 点击预览
44
+ preview: Boolean,
45
+ },
46
+
47
+ /**
48
+ * 组合式
49
+ */
50
+ setup(props) {
51
+
52
+ // ==========【数据】============================================================================================
53
+
54
+ // quasar 对象
55
+ const $q = useQuasar()
56
+
57
+ // ==========【计算属性】==========================================================================================
58
+
59
+ /**
60
+ * 当前图片地址
61
+ */
62
+ const currentSrc = computed(function () {
63
+ const res = utils.getImage(props.src, { w: $q.platform.is.mobile ? props.size * 2 : props.size })
64
+ if (res) {
65
+ return res
66
+ }
67
+ })
68
+
69
+ // ==========【方法】=============================================================================================
70
+
71
+ /**
72
+ * 预览
73
+ */
74
+ function onPreview() {
75
+ // 预览图片
76
+ utils.previewImage(props.src)
77
+ }
78
+
79
+ return {
80
+ // 当前图片地址
81
+ currentSrc,
82
+ // 预览
83
+ onPreview,
84
+ }
85
+ }
86
+ }
87
+ </script>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <q-header
3
+ class="n-toolbar"
4
+ :dark="$q.dark.isActive"
5
+ bordered
6
+ v-if="header"
7
+ >
8
+ <slot />
9
+ </q-header>
10
+
11
+ <q-footer
12
+ class="n-toolbar"
13
+ :dark="$q.dark.isActive"
14
+ bordered
15
+ v-else
16
+ >
17
+ <slot />
18
+ </q-footer>
19
+ </template>
20
+
21
+ <script>
22
+ export default {
23
+ /**
24
+ * 声明属性
25
+ */
26
+ props: {
27
+ // 是否头部
28
+ header: Boolean,
29
+ },
30
+ }
31
+ </script>