@wp1001/ui 2.9.13

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 (177) hide show
  1. package/.env +6 -0
  2. package/@vant-D4fmGxs6.js +3891 -0
  3. package/index.js +8419 -0
  4. package/package.json +59 -0
  5. package/packages/assets/devtools-detector.js +2 -0
  6. package/packages/components/xarray/index.js +64 -0
  7. package/packages/components/xarray/xarray.vue +57 -0
  8. package/packages/components/xautorows/index.js +35 -0
  9. package/packages/components/xautorows/xautorows.vue +29 -0
  10. package/packages/components/xbutton/mobile.js +3 -0
  11. package/packages/components/xbutton/mobile.vue +9 -0
  12. package/packages/components/xbutton/pc.js +3 -0
  13. package/packages/components/xbutton/pc.vue +9 -0
  14. package/packages/components/xbuttons/mobile.js +51 -0
  15. package/packages/components/xbuttons/mobile.vue +12 -0
  16. package/packages/components/xbuttons/pc.js +51 -0
  17. package/packages/components/xbuttons/pc.vue +16 -0
  18. package/packages/components/xchart/constants.js +58 -0
  19. package/packages/components/xchart/index.js +263 -0
  20. package/packages/components/xchart/utils.js +121 -0
  21. package/packages/components/xchart/xchart.vue +173 -0
  22. package/packages/components/xcheckboxs/mobile.js +58 -0
  23. package/packages/components/xcheckboxs/mobile.vue +38 -0
  24. package/packages/components/xcheckboxs/pc.js +49 -0
  25. package/packages/components/xcheckboxs/pc.vue +42 -0
  26. package/packages/components/xcol/mobile.js +10 -0
  27. package/packages/components/xcol/mobile.vue +9 -0
  28. package/packages/components/xcol/pc.js +10 -0
  29. package/packages/components/xcol/pc.vue +9 -0
  30. package/packages/components/xdatepicker/mobile.js +71 -0
  31. package/packages/components/xdatepicker/mobile.vue +44 -0
  32. package/packages/components/xdatepicker/pc.js +9 -0
  33. package/packages/components/xdatepicker/pc.vue +12 -0
  34. package/packages/components/xdialog/mobile.js +60 -0
  35. package/packages/components/xdialog/mobile.vue +43 -0
  36. package/packages/components/xdialog/pc.js +64 -0
  37. package/packages/components/xdialog/pc.vue +51 -0
  38. package/packages/components/xdict/index.js +47 -0
  39. package/packages/components/xdict/xdict.vue +9 -0
  40. package/packages/components/xdistrictselect/mobile.js +79 -0
  41. package/packages/components/xdistrictselect/mobile.vue +28 -0
  42. package/packages/components/xdistrictselect/pc.js +127 -0
  43. package/packages/components/xdistrictselect/pc.vue +32 -0
  44. package/packages/components/xform/mobile.js +29 -0
  45. package/packages/components/xform/mobile.vue +43 -0
  46. package/packages/components/xform/pc.js +42 -0
  47. package/packages/components/xform/pc.vue +76 -0
  48. package/packages/components/xform/utils.js +95 -0
  49. package/packages/components/xformitem/mobile.js +56 -0
  50. package/packages/components/xformitem/mobile.vue +3 -0
  51. package/packages/components/xformitem/pc.js +72 -0
  52. package/packages/components/xformitem/pc.vue +10 -0
  53. package/packages/components/xformitem/utils.jsx +181 -0
  54. package/packages/components/xicon/mobile.js +35 -0
  55. package/packages/components/xicon/mobile.vue +9 -0
  56. package/packages/components/xicon/pc.js +35 -0
  57. package/packages/components/xicon/pc.vue +11 -0
  58. package/packages/components/xinfo/index.js +100 -0
  59. package/packages/components/xinfo/xinfo.vue +140 -0
  60. package/packages/components/xlooper/index.js +7 -0
  61. package/packages/components/xlooper/xlooper.vue +20 -0
  62. package/packages/components/xpagination/mobile.js +21 -0
  63. package/packages/components/xpagination/mobile.vue +31 -0
  64. package/packages/components/xpagination/pc.js +21 -0
  65. package/packages/components/xpagination/pc.vue +16 -0
  66. package/packages/components/xpicker/index.js +38 -0
  67. package/packages/components/xpicker/xpicker.vue +29 -0
  68. package/packages/components/xradios/mobile.js +40 -0
  69. package/packages/components/xradios/mobile.vue +22 -0
  70. package/packages/components/xradios/pc.js +53 -0
  71. package/packages/components/xradios/pc.vue +43 -0
  72. package/packages/components/xrow/mobile.js +9 -0
  73. package/packages/components/xrow/mobile.vue +23 -0
  74. package/packages/components/xrow/pc.js +9 -0
  75. package/packages/components/xrow/pc.vue +22 -0
  76. package/packages/components/xscan/mobile.js +24 -0
  77. package/packages/components/xscan/mobile.vue +21 -0
  78. package/packages/components/xscan/pc.js +20 -0
  79. package/packages/components/xscan/pc.vue +18 -0
  80. package/packages/components/xsearcher/index.js +198 -0
  81. package/packages/components/xsearcher/xsearcher.vue +170 -0
  82. package/packages/components/xselect/mobile.js +86 -0
  83. package/packages/components/xselect/mobile.vue +24 -0
  84. package/packages/components/xselect/pc.js +114 -0
  85. package/packages/components/xselect/pc.vue +55 -0
  86. package/packages/components/xselect/util.js +66 -0
  87. package/packages/components/xselectv2/index.js +91 -0
  88. package/packages/components/xselectv2/xselectv2.vue +46 -0
  89. package/packages/components/xtable/mobile.js +108 -0
  90. package/packages/components/xtable/mobile.vue +246 -0
  91. package/packages/components/xtable/pc.js +143 -0
  92. package/packages/components/xtable/pc.vue +421 -0
  93. package/packages/components/xtable/searcher.js +477 -0
  94. package/packages/components/xtable/searcher.jsx +330 -0
  95. package/packages/components/xtable/searcher.vue +133 -0
  96. package/packages/components/xtable/settings.js +80 -0
  97. package/packages/components/xtable/settings.vue +77 -0
  98. package/packages/components/xtable/utils.js +692 -0
  99. package/packages/components/xtabletools/mobile.js +25 -0
  100. package/packages/components/xtabletools/mobile.vue +126 -0
  101. package/packages/components/xtabletools/pc.js +18 -0
  102. package/packages/components/xtabletools/pc.vue +135 -0
  103. package/packages/components/xtablev2/index.js +53 -0
  104. package/packages/components/xtablev2/utils.jsx +214 -0
  105. package/packages/components/xtablev2/xtablev2.vue +147 -0
  106. package/packages/components/xtags/mobile.js +17 -0
  107. package/packages/components/xtags/mobile.vue +21 -0
  108. package/packages/components/xtags/pc.js +17 -0
  109. package/packages/components/xtags/pc.vue +22 -0
  110. package/packages/components/xtinymce/index.js +71 -0
  111. package/packages/components/xtinymce/xtinymce.vue +9 -0
  112. package/packages/components/xuploader/xfileuploader.js +48 -0
  113. package/packages/components/xuploader/xfileuploader.vue +54 -0
  114. package/packages/components/xuploader/ximageuploader.js +53 -0
  115. package/packages/components/xuploader/ximageuploader.vue +52 -0
  116. package/packages/comps.js +108 -0
  117. package/packages/controllers/BaseController.js +125 -0
  118. package/packages/controllers/CrudController.js +907 -0
  119. package/packages/controllers/TempCrudController.js +32 -0
  120. package/packages/controllers/index.js +15 -0
  121. package/packages/directives/el-table-infinite-scroll.js +55 -0
  122. package/packages/directives/index.js +5 -0
  123. package/packages/index.js +81 -0
  124. package/packages/index.scss +4 -0
  125. package/packages/layout/breadcrumb/breadcrumb.vue +31 -0
  126. package/packages/layout/breadcrumb/index.js +41 -0
  127. package/packages/layout/header/header.vue +281 -0
  128. package/packages/layout/header/inner.js +11 -0
  129. package/packages/layout/header/inner.vue +3 -0
  130. package/packages/layout/mobile-menu.vue +83 -0
  131. package/packages/layout/mobile-tabs.vue +54 -0
  132. package/packages/layout/pc.vue +85 -0
  133. package/packages/layout/screenlock/index.js +129 -0
  134. package/packages/layout/screenlock/screenlock.vue +85 -0
  135. package/packages/layout/sidebar/item.js +16 -0
  136. package/packages/layout/sidebar/item.vue +16 -0
  137. package/packages/layout/sidebar/menu.js +72 -0
  138. package/packages/layout/sidebar/menu.vue +106 -0
  139. package/packages/layout/sidebar/sidebar.vue +147 -0
  140. package/packages/layout/tagsview/ScrollPane.js +65 -0
  141. package/packages/layout/tagsview/ScrollPane.vue +24 -0
  142. package/packages/layout/tagsview/index.js +169 -0
  143. package/packages/layout/tagsview/index.vue +124 -0
  144. package/packages/plop/actions/make-fill-admin-partials-action.js +95 -0
  145. package/packages/plop/generators/make-admin-page.js +39 -0
  146. package/packages/plop/generators/make-database-admin-pages.js +84 -0
  147. package/packages/plop/generators/make-page-generator.js +52 -0
  148. package/packages/plop/generators/make-simple-page.js +20 -0
  149. package/packages/plop/plopfile.js +24 -0
  150. package/packages/plop/templates/admin_page/controller.js +3 -0
  151. package/packages/plop/templates/admin_page/model.js +24 -0
  152. package/packages/plop/templates/admin_page/{{snakeCase pagename}}-scoped.scss +3 -0
  153. package/packages/plop/templates/admin_page/{{snakeCase pagename}}.vue +11 -0
  154. package/packages/plop/templates/simple_page/controller.js +3 -0
  155. package/packages/plop/templates/simple_page/model.js +6 -0
  156. package/packages/plop/templates/simple_page/{{snakeCase pagename}}-scoped.scss +3 -0
  157. package/packages/plop/templates/simple_page/{{snakeCase pagename}}.vue +7 -0
  158. package/packages/plop/utils/index.js +168 -0
  159. package/packages/plop/utils/plop-utils.js +86 -0
  160. package/packages/styles/common.scss +137 -0
  161. package/packages/styles/element-ui.scss +142 -0
  162. package/packages/styles/vant.scss +133 -0
  163. package/packages/styles/variables.scss +23 -0
  164. package/packages/utils/crypt.js +24 -0
  165. package/packages/utils/decorators.js +67 -0
  166. package/packages/utils/disallowDevtools.js +53 -0
  167. package/packages/utils/effects.js +173 -0
  168. package/packages/utils/funcs.js +78 -0
  169. package/packages/utils/index.js +95 -0
  170. package/packages/utils/message.js +110 -0
  171. package/packages/utils/middlewares.js +86 -0
  172. package/packages/utils/model.js +71 -0
  173. package/packages/utils/modelUtils.js +203 -0
  174. package/packages/utils/request.js +57 -0
  175. package/packages/utils/site.js +33 -0
  176. package/packages/vite-plugins.js +141 -0
  177. package/publish.sh +12 -0
@@ -0,0 +1,110 @@
1
+ let { ElMessage, ElNotification, ElMessageBox } = window.ElementPlus || {}
2
+ let { showToast, showNotify, showConfirmDialog } = window.vant || {}
3
+
4
+ export const initMessageUtils = ({ ElementPlus, Vant }) => {
5
+ if (ElementPlus) {
6
+ ElMessage = ElementPlus.ElMessage
7
+ ElNotification = ElementPlus.ElNotification
8
+ ElMessageBox = ElementPlus.ElMessageBox
9
+ }
10
+ if (Vant) {
11
+ showToast = Vant.showToast
12
+ showNotify = Vant.showNotify
13
+ showConfirmDialog = Vant.showConfirmDialog
14
+ }
15
+ }
16
+
17
+ export const Message = options => {
18
+ let opts = typeof options !== 'string' ? options : { message: options }
19
+ opts = {
20
+ type: 'error',
21
+ duration: 3000,
22
+ ...opts
23
+ }
24
+ const { isMobile = window.isMobile, type } = opts
25
+ if (isMobile) {
26
+ if (type === 'error' || type === 'warning') opts.type = 'fail'
27
+ opts['z-index'] ||= 1e6
28
+ showToast(opts)
29
+ } else {
30
+ ElMessage({
31
+ showClose: true,
32
+ grouping: true,
33
+ ...opts
34
+ })
35
+ }
36
+ }
37
+
38
+ export const Notify = options => {
39
+ let opts = typeof options !== 'string' ? options : { message: options }
40
+ opts = {
41
+ type: 'error',
42
+ duration: 3000,
43
+ ...opts
44
+ }
45
+ const { isMobile = window.isMobile, type } = opts
46
+ if (isMobile) {
47
+ if (type === 'error') opts.type = 'danger'
48
+ showNotify(opts)
49
+ } else {
50
+ ElNotification({
51
+ showClose: true,
52
+ ...opts
53
+ })
54
+ }
55
+ }
56
+
57
+ export const Confirm = options => {
58
+ let promise = null
59
+ const { isMobile = window.isMobile } = options
60
+ if (isMobile) {
61
+ promise = showConfirmDialog(options)
62
+ } else {
63
+ promise = ElMessageBox.confirm(
64
+ options.message || '',
65
+ options.title || '',
66
+ {
67
+ draggable: true,
68
+ ...options,
69
+ type: options.type || 'info',
70
+ confirmButtonText: options.confirmButtonText || '确定',
71
+ cancelButtonText: options.cancelButtonText || '取消',
72
+ }
73
+ )
74
+ }
75
+ return promise.then(() => {
76
+ return options.distinguishCancelAndClose ? 'confirm' : true
77
+ }).catch(action => {
78
+ return options.distinguishCancelAndClose ? action : false
79
+ })
80
+ }
81
+
82
+ export const Prompt = options => {
83
+ return ElMessageBox.prompt(options.message, options.title, {
84
+ confirmButtonText: '确定',
85
+ cancelButtonText: '取消',
86
+ inputPattern: /[^\s]+/,
87
+ inputErrorMessage: '请输入',
88
+ ...options
89
+ }).then(({ value }) => value).catch(() => '')
90
+ }
91
+
92
+ for (let type of ['success', 'warning', 'info', 'error', 'primary', 'loading', 'fail', 'html']) {
93
+ Message[type] = Message[type[0]] = options => {
94
+ const opts = typeof options !== 'string' ? options : { message: options }
95
+ return Message({ type, ...opts })
96
+ }
97
+ Notify[type] = Notify[type[0]] = options => {
98
+ const opts = typeof options !== 'string' ? options : { message: options }
99
+ return Notify({ type, ...opts })
100
+ }
101
+ Confirm[type] = Confirm[type[0]] = options => Confirm({ type, ...options })
102
+ }
103
+
104
+ export default {
105
+ initMessageUtils,
106
+ Message,
107
+ Notify,
108
+ Confirm,
109
+ Prompt
110
+ }
@@ -0,0 +1,86 @@
1
+ import { watch, nextTick } from 'vue'
2
+ import { Message } from './message.js'
3
+
4
+ const { funcs } = StardustJs
5
+
6
+ export const check404 = (router, store, routes) => {
7
+ router.beforeEach(async (to, from) => {
8
+ return !!to.matched.length || '/404'
9
+ })
10
+ }
11
+
12
+ export const setTitle = (router, store, routes) => {
13
+ router.afterEach((to, from) => {
14
+ document.title = to.matched[to.matched.length - 1].meta?.title || store.app.sitename
15
+ })
16
+ }
17
+
18
+ export const checkRolesPages = (router, store, routes) => {
19
+ router.beforeEach(async (to, from) => {
20
+ const path = to.matched[to.matched.length - 1].path.split('/:')[0]
21
+ if (to.meta.acl === false || to.meta?.visitable) return true
22
+ while (store.getters.logging) {
23
+ await funcs.sleep(20)
24
+ }
25
+ await nextTick()
26
+ if (store.acl.paths.includes(path)) return true
27
+ const query = { redirectTo: to.path, ...to.query }
28
+ if (store.getters.logined) {
29
+ query.error = '受限于您的账号权限,暂时无法访问 ' + to.path + ' 页面,如有需要请联系我们'
30
+ Message({ message: query.error, duration: 1e4 })
31
+ }
32
+ return { path: store.acl.paths[0] || '/404', query }
33
+ })
34
+ nextTick(() => {
35
+ let inited = false
36
+ watch(() => store.acl.menus, menus => {
37
+ if (!inited) {
38
+ if (!menus.length) return
39
+ inited = true
40
+ }
41
+ const paths = store.acl.paths
42
+ const update = (route, parents) => {
43
+ let path
44
+ if (route.redirect && !route.component) {
45
+ path = route.redirect
46
+ } else {
47
+ path = [...parents, route].reduce((path, p) => path + '/' + p.path, '').replace('//', '/')
48
+ }
49
+ route.meta ||= {}
50
+ if (route.meta.acl === false) {
51
+ route.children?.forEach(sub => {
52
+ sub.meta ||= {}
53
+ sub.meta.acl ||= false
54
+ update(sub, [...parents, route])
55
+ })
56
+ } else {
57
+ route.meta._hidden = route.meta.hidden
58
+ if (parent) {
59
+ if (route.meta.hidden == null) {
60
+ route.meta.hidden ??= parent.meta?.hidden
61
+ route.meta = { ...route.meta }
62
+ }
63
+ if (route.meta.visitable == null) {
64
+ route.meta.visitable ??= parent.meta?.visitable
65
+ route.meta = { ...route.meta }
66
+ }
67
+ }
68
+ route.children?.forEach(sub => update(sub, [...parents, route]))
69
+ if (route.meta.hidden !== false && route.meta._hidden !== true) {
70
+ route.meta.hidden = !paths.includes(path)
71
+ if (route.children?.some(sub => sub.meta.hidden === false)) {
72
+ route.meta.hidden = false
73
+ }
74
+ }
75
+ }
76
+ }
77
+ routes.forEach(route => update(route, []))
78
+ }, { immediate: true })
79
+ })
80
+ }
81
+
82
+ export default {
83
+ check404,
84
+ setTitle,
85
+ checkRolesPages
86
+ }
@@ -0,0 +1,71 @@
1
+
2
+ export const baseForm = () => ({
3
+ loading: false,
4
+ form: {},
5
+ initialForm: {},
6
+ formItems: [],
7
+ formRef: null,
8
+ formRules: {},
9
+ initialFormRules: {},
10
+ _isBaseForm: true,
11
+ viewonly: false
12
+ })
13
+
14
+ export const baseTable = (query = {}) => ({
15
+ loading: false,
16
+ query: {
17
+ page: 1,
18
+ limit: 10,
19
+ order: [],
20
+ ...query
21
+ },
22
+ total: 0,
23
+ moreLoading: false,
24
+ finished: false,
25
+ isInfinite: false,
26
+ list: [],
27
+ columns: [],
28
+ tableRef: null,
29
+ selection: [],
30
+ checked: null,
31
+ searchFields: [],
32
+ _isBaseTable: true
33
+ })
34
+
35
+ export const baseDialog = () => ({
36
+ ...baseForm(),
37
+ visible: false,
38
+ isEditing: false,
39
+ editingIndex: '',
40
+ editingRow: {},
41
+ _isBaseDialog: true
42
+ })
43
+
44
+ export const baseModel = ({
45
+ table = {},
46
+ dialog = {},
47
+ columns = [
48
+ { fixed: 'left', type: 'selection' },
49
+ { type: '_index' }
50
+ ],
51
+ query = {},
52
+ form = {}
53
+ } = {}) => ({
54
+ table: {
55
+ ...baseTable(query),
56
+ ...table,
57
+ columns
58
+ },
59
+ dialog: {
60
+ ...baseDialog(),
61
+ ...dialog,
62
+ form
63
+ }
64
+ })
65
+
66
+ export default {
67
+ baseForm,
68
+ baseTable,
69
+ baseDialog,
70
+ baseModel
71
+ }
@@ -0,0 +1,203 @@
1
+ import { watch } from 'vue'
2
+
3
+ const { funcs } = StardustJs
4
+
5
+ export const initFields = fields => {
6
+ return fields.map(f => {
7
+ const keys = Object.keys(f)
8
+ for (let key of keys) {
9
+ if (key.startsWith('ta_')) {
10
+ f.tableAttrs ??= {}
11
+ f.tableAttrs[key.slice(3)] = f[key]
12
+ delete f[key]
13
+ } else if (key.startsWith('fa_')) {
14
+ f.formAttrs ??= {}
15
+ f.formAttrs[key.slice(3)] = f[key]
16
+ delete f[key]
17
+ }
18
+ }
19
+ if (f.type === 'date') {
20
+ f.formAttrs ??= {}
21
+ f.formAttrs['value-format'] ??= 'YYYY-MM-DD'
22
+ } else if (f.type === 'datetime') {
23
+ f.formAttrs ??= {}
24
+ f.formAttrs['value-format'] ??= 'YYYY-MM-DD HH:mm:ss'
25
+ }
26
+ f.xs ??= 24
27
+ return f
28
+ })
29
+ }
30
+
31
+ export const initModel = (model, fields) => {
32
+ for (let key in model) {
33
+ const value = model[key]
34
+ if (!value || typeof value !== 'object') {
35
+ continue
36
+ }
37
+ if (key === 'table' && model[key]._isBaseTable) {
38
+ initTable(value, fields)
39
+ }
40
+ if (key === 'dialog' && model[key]._isBaseDialog) {
41
+ initDialog(value, fields)
42
+ }
43
+ if (key === 'form' && model[key]._isBaseForm) {
44
+ initForm(value, fields)
45
+ }
46
+ }
47
+ return model
48
+ }
49
+
50
+ export const initTable = (table, fields) => {
51
+ table.columns.push(...fields.filter(field => {
52
+ return field.visible === false ? field.canView : field.canView !== false
53
+ }))
54
+ return table
55
+ }
56
+
57
+ export const initDialog = (dialog, fields) => {
58
+ dialog.formItems = fields.filter(field => {
59
+ if (field.visible === false) {
60
+ return field.canAdd || field.canEdit
61
+ }
62
+ return (field.canAdd !== false) || (field.canEdit !== false)
63
+ })
64
+ initForm(dialog, fields)
65
+ return dialog
66
+ }
67
+
68
+ export const initForm = (form, fields) => {
69
+ if (form._isBaseForm && !form._isBaseDialog) {
70
+ form.formItems = fields.filter(field => field.visible !== false)
71
+ }
72
+ initDefaultForm(form.form, form.formItems)
73
+ form.initialForm = funcs.deepCopy(form.form)
74
+ form.initialFormRules = funcs.deepCopy(form.formRules)
75
+
76
+ const init = () => {
77
+ initFormRules(form)
78
+ }
79
+ watch(() => form.formItems, init, { immediate: true, deep: true })
80
+ return form
81
+ }
82
+
83
+ export const initFormRules = (container) => {
84
+ const { formItems, initialFormRules } = container
85
+ Object.assign(container.formRules, funcs.deepCopy(initialFormRules))
86
+ Object.keys(container.formRules).forEach(key => {
87
+ if (!initialFormRules.hasOwnProperty(key)) {
88
+ delete container.formRules[key]
89
+ }
90
+ })
91
+ const rules = {}
92
+ formItems.forEach(item => {
93
+ if (container.formRules[item.prop]) return
94
+ if (!item.required && !item.validator && !item.asyncValidator) return
95
+ const platform = item.platform || container.platform || (window.isMobile ? 'mobile' : 'pc')
96
+ const trigger = triggers[platform]
97
+ const itemRules = []
98
+ const isSelects = 'options' in item
99
+ const message = `请${item.validator || item.asyncValidator ? '正确' : ''}${isSelects ? '选择' : '输入'}${item?.label || item.prop}`
100
+ const baseRule = { required: true, message }
101
+ if (item.validator) baseRule.validator = (param1, param2) => {
102
+ return platform === 'pc' ? item.validator(param1, param2) : item.validator(param2, param1)
103
+ }
104
+ if (item.asyncValidator) baseRule.asyncValidator = (param1, param2) => {
105
+ return platform === 'pc' ? item.asyncValidator(param1, param2) : item.asyncValidator(param2, param1)
106
+ }
107
+ if (!item.comp) {
108
+ itemRules.push({ ...baseRule, trigger: trigger.blur })
109
+ } else {
110
+ itemRules.push({ ...baseRule, trigger: trigger.change })
111
+ }
112
+ if (item.comp === 'ElInputNumber') {
113
+ itemRules.push({ ...baseRule, trigger: trigger.blur })
114
+ }
115
+ rules[item.prop] = itemRules
116
+ })
117
+ Object.assign(container.formRules, rules)
118
+ return container.formRules
119
+ }
120
+
121
+ export const initDefaultForm = (form, formItems, number0 = true) => {
122
+ const defaultForm = {}
123
+ formItems.forEach(item => {
124
+ if (!item.prop || item.virtual) return
125
+ let value = ''
126
+ const { type, options } = item
127
+ const { multiple } = item.formAttrs || {}
128
+ if (number0 && type === 'number' || item.comp === 'ElInputNumber') {
129
+ value = null
130
+ } else if (item.comp === 'ElSwitch') {
131
+ value = false
132
+ } else if (options && (item.comp?.endsWith('XCheckboxs') || item.comp?.endsWith('x-checkboxs') || multiple)) {
133
+ value = []
134
+ } else if (item.comp === 'ElDatePicker' && ['datetimerange', 'daterange', 'monthrange'].includes(item.type)) {
135
+ const placeholer = ({
136
+ datetimerange: '时间',
137
+ daterange: '日期',
138
+ monthrange: '月份'
139
+ })[item.type]
140
+ if (!item['start-placeholder']) {
141
+ item['start-placeholder'] = '开始' + placeholer
142
+ }
143
+ if (!item['end-placeholder']) {
144
+ item['end-placeholder'] = '结束' + placeholer
145
+ }
146
+ value = []
147
+ }
148
+ defaultForm[item.prop] = value
149
+ })
150
+ Object.assign(form, { ...defaultForm, ...form })
151
+ return form
152
+ }
153
+
154
+ export const isWhenMatched = (when, form) => {
155
+ if (!when) return true
156
+ const parts = when.split(/\s?(&&|\|\|)\s?/g)
157
+ if (parts.includes('&&') && parts.includes('||')) {
158
+ throw '一个 when 表达式中仅支持 && 模式或 || 模式'
159
+ }
160
+ const isEvery = parts.includes('&&')
161
+ const reg = /[\^\*\$\~\!]?=/
162
+ const groups = parts.filter(p => p !== '&&' && p !== '||')
163
+ return groups[isEvery ? 'every' : 'some'](group => {
164
+ let [field, values] = group.split(reg)
165
+ values = values.split('|')
166
+ let v = form[field]
167
+ if (typeof v === 'number') v += ''
168
+ else if (typeof v === 'string') v = v.trim()
169
+ const type = group.match(reg)[0]
170
+ if (type === '!=') return !values.includes(v)
171
+ return values.some(ele => {
172
+ if (type === '^=') return v?.startsWith(ele)
173
+ else if (type === '*=') return v?.includes(ele)
174
+ else if (type === '$=') return v?.endsWith(ele)
175
+ else if (type === '~=') return !v?.includes(ele)
176
+ else if (type === '!=') return v !== ele
177
+ return ele === v
178
+ })
179
+ })
180
+ }
181
+
182
+ export const triggers = {
183
+ mobile: {
184
+ blur: 'onBlur',
185
+ change: 'onChange'
186
+ },
187
+ pc: {
188
+ blur: 'blur',
189
+ change: 'change'
190
+ }
191
+ }
192
+
193
+ export default {
194
+ initFields,
195
+ initModel,
196
+ initTable,
197
+ initDialog,
198
+ initForm,
199
+ initFormRules,
200
+ initDefaultForm,
201
+ isWhenMatched,
202
+ triggers
203
+ }
@@ -0,0 +1,57 @@
1
+ import { Message } from './message.js'
2
+
3
+ const requestUse = (app, crypt, store, router, config) => {
4
+ config.headers.Authorization ||= store.user.token
5
+ const type = app.config.globalProperties.httpEncrypt
6
+ if (type !== false) {
7
+ config.headers['Http-Encrypt'] = type
8
+ config.headers['Content-Type'] ||= 'application/json; charset=UTF-8'
9
+ if (config.url.indexOf('?') >= 0) {
10
+ const [path, ...others] = config.url.split('?')
11
+ const encrypted = crypt.encrypt[type](others.join('?'), 'query')
12
+ config.url = path + '?' + encrypted
13
+ } else {
14
+ config.params ||= { __placeholder__: Date.now().toString(16) }
15
+ }
16
+ if (config.params) {
17
+ const query = decodeURIComponent(new URLSearchParams(config.params).toString())
18
+ config.url += '?' + crypt.encrypt[type](query, 'query')
19
+ delete config.params
20
+ }
21
+ if (config.data !== undefined && !(config.data instanceof FormData)) {
22
+ const encrypted = crypt.encrypt[type](JSON.stringify(config.data), 'body')
23
+ config.data = encrypted
24
+ }
25
+ }
26
+ return config
27
+ }
28
+
29
+ const responseUse = (app, crypt, store, router, res) => {
30
+ if ([401, 402, 10001].includes(res.data.code)) {
31
+ store.user.setExpired()
32
+ const currentPath = '/' + location.hash.slice(2).split('?')[0]
33
+ const query = StardustJs.funcs.decodeQuery(location.href.split('?')[1] || '')
34
+ router.replace(query.redirectTo ? `/login?redirectTo=${query.redirectTo || currentPath}` : '/login')
35
+ return Promise.reject(res)
36
+ } else if ([10002].includes(res.data.code)) {
37
+ Message.e(res.data.err)
38
+ return Promise.reject(res)
39
+ }
40
+ const token = res.headers['refresh-token'] || res.data.token
41
+ if (token) {
42
+ store.user.setToken(token)
43
+ }
44
+ if (res.data.err) {
45
+ Message.e(res.data.err || '未知错误')
46
+ return Promise.reject(res)
47
+ }
48
+ if (res.headers['content-type']?.includes('application/json')) {
49
+ res.data = JSON.parse(StardustJs.dates.convertIsoDates(JSON.stringify(res.data)))
50
+ }
51
+ return Promise.resolve(res.data)
52
+ }
53
+
54
+ export {
55
+ requestUse,
56
+ responseUse
57
+ }
@@ -0,0 +1,33 @@
1
+
2
+ export const createWatermark = ({
3
+ text,
4
+ gap,
5
+ fontSize,
6
+ color,
7
+ width = window.innerWidth,
8
+ height = window.innerHeight,
9
+ drawMode = 'fill'
10
+ }) => {
11
+ const canvas = document.createElement('canvas')
12
+ canvas.width = width
13
+ canvas.height = height
14
+
15
+ const ctx = canvas.getContext('2d')
16
+ ctx.font = `${fontSize}px Arial`
17
+ ctx[drawMode + 'Style'] = color
18
+
19
+ const textWidth = ctx.measureText(text).width
20
+ const perWidth = textWidth + gap
21
+ const perHeight = fontSize + gap
22
+ for (let y = gap / 2; y < height; y += perHeight) {
23
+ for (let x = gap / 2; x < width; x += perWidth) {
24
+ ctx[drawMode + 'Text'](text, x, y)
25
+ }
26
+ }
27
+
28
+ return canvas
29
+ }
30
+
31
+ export default {
32
+ createWatermark
33
+ }
@@ -0,0 +1,141 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ const filterPrivateFields = `
5
+ const filterPrivateFields = source => {
6
+ const target = {}
7
+ for (let key in source) {
8
+ if (key[0] !== "$" && key[0] !== "_") {
9
+ target[key] = source[key]
10
+ }
11
+ }
12
+ return target
13
+ }
14
+ const wrapCtx = (_ctx, model, controller) => {
15
+ return new Proxy(_ctx, {
16
+ get (obj, prop) {
17
+ if (prop in obj) return obj[prop]
18
+ return model?.[prop] ?? controller?.[prop]
19
+ }
20
+ })
21
+ }
22
+ `
23
+
24
+ const inject = (src, id) => {
25
+ const dirname = path.dirname(id)
26
+ const basename = path.basename(id)
27
+ const name = basename.split('.')[0]
28
+ const hasScopedScss = fs.existsSync(path.join(dirname, name + '-scoped.scss'))
29
+ const hasScss = fs.existsSync(path.join(dirname, name + '.scss'))
30
+ const hasModel = fs.existsSync(path.join(dirname, 'model.js'))
31
+ const hasController = fs.existsSync(path.join(dirname, 'controller.js'))
32
+ const needModel = hasModel && !src.includes('no model') && !src.includes('const model')
33
+ const needController = hasController && !src.includes('no controller') && !src.includes('const controller')
34
+
35
+ if (id.includes('/src/') && basename.includes('.vue') && src.startsWith('<script setup>')) {
36
+ src = src.replace('<script setup>', '<script setup>\n')
37
+ const lines = src.split('\n')
38
+ if (hasScopedScss) {
39
+ lines.push(...['<style lang="scss" scoped>', `@use "./${name}-scoped.scss";`, '</style>'])
40
+ }
41
+ if (hasScss) {
42
+ lines.push(...['<style lang="scss">', `@use "./${name}.scss";`, '</style>'])
43
+ }
44
+ if (needController) {
45
+ lines.splice(1, 0, `import makeController from './controller.js'`, `const controller = makeController({ ${needModel ? 'model, ' : ''}vue })`)
46
+ }
47
+ if (needModel) {
48
+ lines.splice(1, 0, `import makeModel from './model.js'`, `const model = makeModel()`)
49
+ }
50
+ src = lines.join('\n')
51
+ }
52
+ return src
53
+ }
54
+
55
+ const instantiateTables = (src, id) => {
56
+ const basename = path.basename(id)
57
+ const isVue = basename.includes('.vue')
58
+ const isJs = basename.includes('.js')
59
+ if (id.includes('/src/') && (isVue || isJs)) {
60
+ const code = src.split('\n').map(l => l.trim()).filter(l => !l.startsWith('//')).join('\n')
61
+ const names = new Set([...code.matchAll(/[^a-z][A-Z]\w+\.(search|add|update|remove|func|batch|get)/g)].map(e => e[0].slice(1).split('.')[0]))
62
+ if (names.size) {
63
+ let top = ''
64
+ names.forEach(name => {
65
+ let [dbname, tablename] = name.split('_').map(n => n.replace(/[A-Z]/g, c => '_' + c.toLowerCase()).slice(1))
66
+ if (tablename) {
67
+ dbname = `'${dbname}'`
68
+ } else {
69
+ tablename = dbname
70
+ dbname = 'DbName'
71
+ }
72
+ top += `const ${name} = new Table(${dbname}, '${tablename}')\n`
73
+ })
74
+ if (isVue) {
75
+ src = src.replace('<script setup>', '<script setup>\n' + top).replace('<script>', '<script>\n' + top)
76
+ } else {
77
+ src = top + src
78
+ }
79
+ }
80
+ }
81
+ return src
82
+ }
83
+
84
+ const deconstruct = (src, id) => {
85
+ const basename = path.basename(id)
86
+ const isVue = basename.includes('.vue')
87
+ if (id.includes('/src/') && isVue) {
88
+ const devText = 'return __returned__'
89
+ const buildText = 'return (_ctx, _cache) => {'
90
+ const isDev = src.includes(devText)
91
+ const isBuild = src.includes(buildText)
92
+ const needModel = (isDev || isBuild) && src.includes('import makeModel ')
93
+ const needController = (isDev || isBuild) && src.includes('import makeController ')
94
+ if (needModel || needController) {
95
+ let replacement = filterPrivateFields
96
+ if (isDev) {
97
+ if (needModel && needController) {
98
+ replacement += 'return { ...__returned__, ...filterPrivateFields(model), ...filterPrivateFields(controller) }'
99
+ } else if (needModel) {
100
+ replacement += 'return { ...__returned__, ...filterPrivateFields(model) }'
101
+ } else if (needController) {
102
+ replacement += 'return { ...__returned__, ...filterPrivateFields(controller) }'
103
+ }
104
+ } else {
105
+ replacement += buildText + '\n'
106
+ if (needModel && needController) {
107
+ replacement += '_ctx = wrapCtx(_ctx, filterPrivateFields(model), filterPrivateFields(controller))'
108
+ } else if (needModel) {
109
+ replacement += '_ctx = wrapCtx(_ctx, filterPrivateFields(model))'
110
+ } else if (needController) {
111
+ replacement += '_ctx = wrapCtx(_ctx, null, filterPrivateFields(controller))'
112
+ }
113
+ replacement += '\n'
114
+ }
115
+ src = src.replace(isDev ? devText : buildText, replacement)
116
+ }
117
+ }
118
+ return src
119
+ }
120
+
121
+ export const autoInject = (config = {}) => {
122
+ return {
123
+ name: 'auto-inject',
124
+ transform (src, id) {
125
+ src = inject(src, id)
126
+ if (config.instantiateTables !== false) {
127
+ src = instantiateTables(src, id)
128
+ }
129
+ return { code: src }
130
+ }
131
+ }
132
+ }
133
+
134
+ export const autoDeconstruct = () => {
135
+ return {
136
+ name: 'auto-deconstruct',
137
+ transform (src, id) {
138
+ return { code: deconstruct(src, id) }
139
+ }
140
+ }
141
+ }