@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,181 @@
1
+ import { h, resolveComponent } from 'vue'
2
+ import tableUtils from '../xtable/utils.js'
3
+
4
+ const OPTIONS_COMPS = ['x-select', 'XSelect', 'x-radios', 'XRadios', 'x-checkboxs', 'XCheckboxs']
5
+
6
+ export const compRender = (vm) => {
7
+ const { $props, $attrs, attrs, $emit } = vm
8
+ let { comp, compType, html, text } = $props
9
+ const opts = {
10
+ ...attrs,
11
+ ...attrs.formAttrs,
12
+ 'onUpdate:modelValue': value => $emit('update:modelValue', value),
13
+ onChange: value => $emit('change', value)
14
+ }
15
+ const children = []
16
+ if (compType === 'html') {
17
+ opts.class = 'comp-html'
18
+ } else {
19
+ comp = resolveComponent(comp)
20
+ }
21
+ if (html) {
22
+ opts.innerHTML = html
23
+ }
24
+ if (text) {
25
+ children.push(text)
26
+ }
27
+ return h(comp, opts, {
28
+ default: () => children
29
+ })
30
+ }
31
+
32
+ const innerSlots = (vm, slotAttrs) => {
33
+ const { $props, $attrs, attrs, $emit, $slots } = vm
34
+ const { model, item, modelValue, viewonly, showTooltip } = $props
35
+ const { slot } = slotAttrs
36
+ let inner = null
37
+ if (slot === '$link') {
38
+ const to = slotAttrs.to(model)
39
+ const isUrl = /https?\:/.test(to)
40
+ const options = isUrl ? { href: to, target: '_blank' } : { to }
41
+ inner = h(isUrl ? 'a' : resolveComponent('router-link'), options, {
42
+ default: () => tableUtils.methods.calcLink(model, { ...item, ...slotAttrs })
43
+ })
44
+ } else if (slot === '$phone') {
45
+ inner = h('a', {
46
+ href: `tel:${modelValue}`
47
+ }, {
48
+ default: () => modelValue
49
+ })
50
+ } else if (slot === '$image') {
51
+ let images = slotAttrs.images?.(modelValue) ?? [modelValue]
52
+ images = images.filter(ele => ele)
53
+ inner = h('div', { }, {
54
+ default: () => images.map((image, index) => {
55
+ return h(resolveComponent('el-image'), {
56
+ src: image, width: 128, height: 128, ...slotAttrs,
57
+ previewSrcList: images,
58
+ 'initial-index': index,
59
+ style: { width: '128px', height: '128px', margin: '0 5px 5px 0' }
60
+ })
61
+ })
62
+ })
63
+ } else if (slot === '$qrcode') {
64
+ inner = h('img', { src: '', title: modelValue })
65
+ modelValue && window.QRCode && window.QRCode.toDataURL(modelValue, {
66
+ width: 128, height: 128, margin: 1, ...slotAttrs
67
+ }).then(src => { inner.el.src = src })
68
+ } else {
69
+ inner = $slots.default()
70
+ }
71
+ return inner
72
+ }
73
+
74
+ export const PcItem = (vm) => {
75
+ const { $props, $attrs, attrs, $emit, $slots } = vm
76
+ const { model, item, modelValue, viewonly, slot, showTooltip, placeholder } = $props
77
+
78
+ let vnode
79
+
80
+ if (slot && !$attrs.label) {
81
+ vnode = $slots.default()
82
+ } else {
83
+ let inner = null
84
+ if (slot) {
85
+ inner = $slots.default()
86
+ } else if (viewonly) {
87
+ const slotAttrs = attrs.infoAttrs?.slot && attrs.infoAttrs
88
+ || attrs.tableAttrs?.slot && attrs.tableAttrs
89
+ || attrs.slot && attrs
90
+ if (slotAttrs?.slot) {
91
+ inner = innerSlots(vm, slotAttrs)
92
+ } else if (OPTIONS_COMPS.includes($props.comp)) {
93
+ inner = attrs.options.find(o => o[attrs.value ?? 'value'] == modelValue)?.[attrs.text ?? 'text'] ?? modelValue
94
+ } else if (modelValue && typeof modelValue === 'object') {
95
+ inner = JSON.stringify(modelValue)
96
+ } else {
97
+ inner = modelValue
98
+ }
99
+ } else if (showTooltip) {
100
+ inner = (
101
+ <el-tooltip effect="dark" content={placeholder} placement="bottom">
102
+ { compRender(vm) }
103
+ </el-tooltip>
104
+ )
105
+ } else {
106
+ inner = compRender(vm)
107
+ }
108
+ vnode = h(
109
+ resolveComponent('el-form-item'),
110
+ { ...$props, ...$attrs },
111
+ {
112
+ default: () => [inner],
113
+ label: () => h('span', {
114
+ title: $attrs.label,
115
+ class: 'overflow-text',
116
+ style: {
117
+ width: ($props.required ? (parseInt($props.labelWidth) - 13 + 'px') : $props.labelWidth),
118
+ display: 'inline-block'
119
+ }
120
+ }, [$attrs.label])
121
+ }
122
+ )
123
+ }
124
+ return vnode
125
+ }
126
+
127
+ export const MobileItem = (vm) => {
128
+ const { $props, $attrs, attrs, $emit, $slots } = vm
129
+ const { viewonly, slot, comp, modelValue } = $props
130
+
131
+ let vnode
132
+
133
+ if (slot && !$attrs.label) {
134
+ vnode = $slots.default({ ...$props, ...$attrs })
135
+ } else {
136
+ const opts = {
137
+ modelValue,
138
+ labelWidth: $attrs['label-width'],
139
+ labelAlign: $attrs['label-align'] ?? $attrs['label-position'],
140
+ 'onUpdate:modelValue': value => $emit('update:modelValue', value),
141
+ onChange: value => $emit('change', value)
142
+ }
143
+ if (slot && $attrs.label || comp) {
144
+ if (!(slot && $attrs.label) && !viewonly) {
145
+ delete opts['onUpdate:modelValue']
146
+ }
147
+ vnode = h(resolveComponent('van-field'), opts, {
148
+ input: () => {
149
+ if (slot && $attrs.label) {
150
+ return $slots.default()
151
+ } else if (viewonly) {
152
+ let inner = null
153
+ const slotAttrs = attrs.infoAttrs?.slot && attrs.infoAttrs
154
+ || attrs.tableAttrs?.slot && attrs.tableAttrs
155
+ || attrs.slot && attrs
156
+ if (slotAttrs?.slot) {
157
+ inner = innerSlots(vm, slotAttrs)
158
+ } else {
159
+ inner = modelValue
160
+ if (OPTIONS_COMPS.includes($props.comp)) {
161
+ inner = attrs.options.find(o => o[attrs.value ?? 'value'] == modelValue)?.[attrs.text ?? 'text'] ?? modelValue
162
+ }
163
+ if (modelValue && typeof modelValue === 'object') {
164
+ inner = JSON.stringify(modelValue)
165
+ }
166
+ }
167
+ return inner
168
+ }
169
+ return compRender(vm)
170
+ }
171
+ })
172
+ } else {
173
+ Object.assign(opts, attrs)
174
+ if (viewonly) {
175
+ Object.assign(opts, { readonly: true })
176
+ }
177
+ vnode = h(resolveComponent('van-field'), opts)
178
+ }
179
+ }
180
+ return vnode
181
+ }
@@ -0,0 +1,35 @@
1
+ // javascript-obfuscator:disable
2
+ const modules = import.meta.glob('../../assets/icons/*.png')
3
+ // javascript-obfuscator:enable
4
+
5
+ export default {
6
+ name: 'MobileXIcon',
7
+ props: {
8
+ name: String
9
+ },
10
+ data () {
11
+ return {
12
+ icons: {}
13
+ }
14
+ },
15
+ computed: {
16
+ iconClass () {
17
+ const [set, name] = this.name.split(':')
18
+ return 'icon--' + set + ' icon--' + set + '--' + name
19
+ }
20
+ },
21
+ created () {
22
+ this.initIcons()
23
+ },
24
+ methods: {
25
+ async initIcons () {
26
+ const icons = {}
27
+ await Promise.all(Object.keys(modules).map(async path => {
28
+ const name = path.split('/').pop().split('.')[0]
29
+ const res = await modules[path]()
30
+ icons[name] = res.default
31
+ }))
32
+ this.icons = icons
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,9 @@
1
+ <script>
2
+ export { default } from './mobile.js'
3
+ </script>
4
+
5
+ <template>
6
+ <span v-if="name.includes(':')" :class="iconClass" />
7
+ <img v-else-if="icons[name]" :src="icons[name]" alt="icon">
8
+ <van-icon v-else v-bind="$attrs" :name />
9
+ </template>
@@ -0,0 +1,35 @@
1
+ // javascript-obfuscator:disable
2
+ const modules = import.meta.glob('../../assets/icons/*.png')
3
+ // javascript-obfuscator:enable
4
+
5
+ export default {
6
+ name: 'PcXIcon',
7
+ props: {
8
+ name: String
9
+ },
10
+ data () {
11
+ return {
12
+ icons: {}
13
+ }
14
+ },
15
+ computed: {
16
+ iconClass () {
17
+ const [set, name] = this.name.split(':')
18
+ return 'icon--' + set + ' icon--' + set + '--' + name
19
+ }
20
+ },
21
+ created () {
22
+ this.initIcons()
23
+ },
24
+ methods: {
25
+ async initIcons () {
26
+ const icons = {}
27
+ await Promise.all(Object.keys(modules).map(async path => {
28
+ const name = path.split('/').pop().split('.')[0]
29
+ const res = await modules[path]()
30
+ icons[name] = res.default
31
+ }))
32
+ this.icons = icons
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,11 @@
1
+ <script>
2
+ export { default } from './pc.js'
3
+ </script>
4
+
5
+ <template>
6
+ <span v-if="name.includes(':')" :class="iconClass" />
7
+ <img v-else-if="icons[name]" :src="icons[name]" alt="icon">
8
+ <el-icon v-else v-bind="$attrs">
9
+ <component :is="name" />
10
+ </el-icon>
11
+ </template>
@@ -0,0 +1,100 @@
1
+ const { highdict } = StardustJs
2
+ import tableUtils from '../xtable/utils.js'
3
+
4
+ export default {
5
+ name: 'XInfo',
6
+ props: {
7
+ data: Object,
8
+ fields: Array,
9
+ span: {
10
+ type: Number,
11
+ default: window.isMobile ? 24 : 8
12
+ },
13
+ showColon: {
14
+ type: Boolean,
15
+ default: false
16
+ },
17
+ labelWidth: {
18
+ type: String,
19
+ default: '80px'
20
+ },
21
+ align: String,
22
+ labelAlign: String,
23
+ valueAlign: String,
24
+ defaultValue: ''
25
+ },
26
+ computed: {
27
+ blocks () {
28
+ const blocks = {}
29
+ this.fields.filter(f => f.prop || f.comp || f.slot).forEach(f => {
30
+ const { infoAttrs = {}, ...others } = f
31
+ const item = { span: this.span, ...others, ...infoAttrs }
32
+ const name = item.block || '基本信息'
33
+ let block = blocks[name]
34
+ if (!block) {
35
+ blocks[name] = block = []
36
+ block.span = 0
37
+ }
38
+ if (block.span + item.span > 24 && block.length) {
39
+ block[block.length - 1].span += 24 - block.span
40
+ } else {
41
+ block.span += item.span
42
+ }
43
+ block.push(item)
44
+ })
45
+ return blocks
46
+ },
47
+ hideHeader () {
48
+ const keys = Object.keys(this.blocks)
49
+ return keys.length === 1 && keys[0] === '基本信息'
50
+ },
51
+ _labelAlign () {
52
+ return this.labelAlign || this.align || 'left'
53
+ },
54
+ _valueAlign () {
55
+ return this.valueAlign || this.align || 'left'
56
+ }
57
+ },
58
+ data () {
59
+ return {
60
+ activeNames: [],
61
+ get: highdict.get
62
+ }
63
+ },
64
+ created () {
65
+ this.activeNames = Object.keys(this.blocks)
66
+ },
67
+ mounted () {
68
+ if (window.QRCode && this.$refs.qrcodeImg?.length) {
69
+ this.qrcodeDict ||= {}
70
+ this.fields.filter(field => {
71
+ return field.slot === '$qrcode' || field.infoAttrs?.slot === '$qrcode'
72
+ }).forEach(async (field, index) => {
73
+ const value = this.get(this.data, field.prop)
74
+ this.qrcodeDict[value] ||= new Promise(resolve => {
75
+ window.QRCode.toDataURL(value, {
76
+ width: 128, height: 128, margin: 1, ...field.infoAttrs
77
+ }).then(src => {
78
+ this.qrcodeDict[value] = src
79
+ resolve(src)
80
+ })
81
+ })
82
+ this.$refs.qrcodeImg[index].src = await this.qrcodeDict[value]
83
+ })
84
+ }
85
+ },
86
+ methods: {
87
+ calcValue: tableUtils.methods.calcValue,
88
+ calcLink: tableUtils.methods.calcLink,
89
+ calcImages (field, data) {
90
+ if (!data._images) {
91
+ const scope = { row: data }
92
+ tableUtils.methods.calcImages(scope, field)
93
+ data._images = scope._images
94
+ data._urls = scope._urls
95
+ data._image_urls = scope._image_urls
96
+ }
97
+ return data._images
98
+ }
99
+ }
100
+ }
@@ -0,0 +1,140 @@
1
+ <script>
2
+ export { default } from './index.js'
3
+ </script>
4
+
5
+ <template>
6
+ <el-collapse
7
+ v-model="activeNames"
8
+ class="x-info"
9
+ :class="[isMobile ? 'mobile-x-info' : 'pc-x-info', { 'hide-header': hideHeader }]"
10
+ >
11
+ <el-collapse-item
12
+ v-for="(items, k) in blocks"
13
+ :key="k"
14
+ :title="k"
15
+ :name="k"
16
+ >
17
+ <el-row :gutter="$attrs.gutter || 10">
18
+ <el-col
19
+ v-for="field in items"
20
+ :key="field.prop"
21
+ :span
22
+ v-bind="field"
23
+ >
24
+ <div
25
+ v-if="field.label || $slots.label" class="x-info__label"
26
+ :style="{ width: field.labelWidth || labelWidth }"
27
+ >
28
+ <slot v-if="$slots.label" name="label" :label="field.label" />
29
+ <span v-else>{{ field.label ? (showColon ? (field.label + ':') : field.label) : '' }}</span>
30
+ </div>
31
+ <div
32
+ class="x-info__value"
33
+ :style="{ width: `calc(100% - ${field.labelWidth || labelWidth})` }"
34
+ >
35
+ <a
36
+ v-if="field.slot === '$link' && /https?\:/.test(field.to(data))"
37
+ :href="field.to(data)" target="_blank"
38
+ >
39
+ {{ calcLink(data, field) }}
40
+ </a>
41
+ <router-link
42
+ v-else-if="field.slot === '$link'"
43
+ :to="field.to(data)"
44
+ >
45
+ {{ calcLink(data, field) }}
46
+ </router-link>
47
+ <el-space v-else-if="field.slot === '$image'" wrap>
48
+ <div class="image-item" v-for="(image, index) in calcImages(field, data)" :key="index">
49
+ <el-image
50
+ v-if="image.type === 'image'"
51
+ :src="image.url"
52
+ :preview-src-list="data._image_urls"
53
+ :initial-index="data._image_urls.indexOf(image.url)"
54
+ lazy preview-teleported
55
+ v-bind="field"
56
+ />
57
+ <video
58
+ v-else-if="image.type === 'video'"
59
+ :src="image.url" controls
60
+ />
61
+ <a
62
+ v-else
63
+ :href="image.url" target="_blank" @click.native="field.onDownload?.(image, index, $event)"
64
+ >
65
+ <x-icon :name="image.icon" class="file-icon" />
66
+ </a>
67
+ </div>
68
+ </el-space>
69
+ <a
70
+ v-else-if="field.slot === '$phone'"
71
+ :href="`tel:${get(data, field.prop)}`"
72
+ >
73
+ {{ get(data, field.prop) }}
74
+ </a>
75
+ <img
76
+ v-else-if="field.slot === '$qrcode'"
77
+ ref="qrcodeImg"
78
+ :title="get(data, field.prop)"
79
+ />
80
+ <x-icon
81
+ v-else-if="field.slot === '$icon'"
82
+ :name="get(data, field.prop)"
83
+ />
84
+ <div
85
+ v-else-if="field.slot === '$html'"
86
+ v-html="get(data, field.prop)"
87
+ />
88
+ <slot
89
+ v-else-if="field.slot"
90
+ :name="field.slot"
91
+ v-bind="{ data, field, value: calcValue(data, field) }"
92
+ />
93
+ <component
94
+ v-else-if="field.comp"
95
+ :is="field.comp"
96
+ v-bind="{ ...field, onClick: null }"
97
+ @click.stop="field.onClick?.(data)"
98
+ >
99
+ {{ field.text }}
100
+ </component>
101
+ <span v-else>{{ calcValue(data, field) }}</span>
102
+ </div>
103
+ </el-col>
104
+ </el-row>
105
+ </el-collapse-item>
106
+ </el-collapse>
107
+ </template>
108
+
109
+ <style lang="scss" scoped>
110
+ .x-info {
111
+ &.hide-header {
112
+ :deep(.el-collapse-item__header) {
113
+ display: none;
114
+ }
115
+ }
116
+ :deep(.el-collapse-item__content) {
117
+ padding: 10px 0;
118
+ .el-col {
119
+ margin: 3px 0;
120
+ }
121
+ }
122
+ .x-info__label {
123
+ padding: 0 10px;
124
+ color: #909999;
125
+ display: inline-block;
126
+ vertical-align: top;
127
+ text-align: v-bind('_labelAlign');
128
+ }
129
+ .x-info__value {
130
+ padding: 0 10px;
131
+ display: inline-block;
132
+ color: #303333;
133
+ text-align: v-bind('_valueAlign');
134
+ }
135
+ .file-icon {
136
+ font-size: 50px;
137
+ color: #606666;
138
+ }
139
+ }
140
+ </style>
@@ -0,0 +1,7 @@
1
+ export default {
2
+ name: 'XLooper',
3
+ props: {
4
+ compName: String,
5
+ items: Array
6
+ }
7
+ }
@@ -0,0 +1,20 @@
1
+ <script>
2
+ export { default } from './index.js'
3
+ </script>
4
+
5
+ <template>
6
+ <div class="x-looper" :class="isMobile ? 'mobile-x-looper' : 'pc-x-looper'">
7
+ <component
8
+ v-for="(item, index) in items"
9
+ :key="index"
10
+ :is="compName"
11
+ v-bind="item"
12
+ >
13
+ <slot
14
+ v-if="item.slot || $attrs.slot"
15
+ :item="item"
16
+ />
17
+ <span v-else>{{ item.text }}</span>
18
+ </component>
19
+ </div>
20
+ </template>
@@ -0,0 +1,21 @@
1
+ export default {
2
+ name: 'MobileXPagination',
3
+ props: {
4
+ query: Object,
5
+ total: Number
6
+ },
7
+ emits: ['search'],
8
+ computed: {
9
+ pageCount () {
10
+ return Math.ceil(this.total / this.query.limit)
11
+ }
12
+ },
13
+ watch: {
14
+ 'query.page' () {
15
+ this.$emit('search')
16
+ },
17
+ 'query.limit' () {
18
+ this.$emit('search')
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,31 @@
1
+ <script>
2
+ export { default } from './mobile.js'
3
+ </script>
4
+
5
+ <template>
6
+ <van-row align="center" class="x-paginaiton mobile-x-paginaiton">
7
+ <van-col :span="6">
8
+ <span>总计: {{ total }}</span>
9
+ </van-col>
10
+ <van-col :span="18">
11
+ <van-pagination
12
+ mode="simple"
13
+ :items-per-page="query.limit"
14
+ :total-items="total"
15
+ v-bind="{...$attrs, ...(mobilePagination || {})}"
16
+ v-model="query.page"
17
+ :page-count="pageCount"
18
+ >
19
+ <template #prev-text>
20
+ <van-icon name="arrow-left" />
21
+ 上一页
22
+ </template>
23
+ <template #next-text>
24
+ 下一页
25
+ <van-icon name="arrow" />
26
+ </template>
27
+ <template #page="{ text }">{{ text }}</template>
28
+ </van-pagination>
29
+ </van-col>
30
+ </van-row>
31
+ </template>
@@ -0,0 +1,21 @@
1
+ export default {
2
+ name: 'PcXPagination',
3
+ props: {
4
+ query: Object,
5
+ total: Number
6
+ },
7
+ emits: ['search'],
8
+ computed: {
9
+ pageCount () {
10
+ return Math.ceil(this.total / this.query.limit)
11
+ }
12
+ },
13
+ watch: {
14
+ 'query.page' () {
15
+ this.$emit('search')
16
+ },
17
+ 'query.limit' () {
18
+ this.$emit('search')
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,16 @@
1
+ <script>
2
+ export { default } from './pc.js'
3
+ </script>
4
+
5
+ <template>
6
+ <el-pagination
7
+ background
8
+ layout="total, sizes, prev, pager, next, jumper"
9
+ v-bind="{...$attrs, ...(pcPagination || {})}"
10
+ v-model:current-page="query.page"
11
+ v-model:page-size="query.limit"
12
+ :page-count="pageCount"
13
+ :total
14
+ class="x-paginaiton pc-x-pagination"
15
+ />
16
+ </template>
@@ -0,0 +1,38 @@
1
+ export default {
2
+ name: 'XPicker',
3
+ props: {
4
+ modelValue: Boolean | Number | String,
5
+ placeholder: String,
6
+ show: Boolean,
7
+ columns: Array
8
+ },
9
+ emits: [
10
+ 'show',
11
+ 'confirm',
12
+ 'cancel',
13
+ 'update:modelValue'
14
+ ],
15
+ computed: {
16
+ visible: {
17
+ get () {
18
+ return this.show
19
+ },
20
+ set (value) {
21
+ this.$emit(value ? 'show' : 'cancel')
22
+ }
23
+ },
24
+ value () {
25
+ return [this.modelValue]
26
+ },
27
+ text () {
28
+ return this.columns.find(c => c.value === this.modelValue)?.text ?? this.placeholder
29
+ }
30
+ },
31
+ methods: {
32
+ onConfirm (value) {
33
+ this.$emit('change', value)
34
+ this.$emit('confirm', value)
35
+ this.$emit('update:modelValue', value)
36
+ }
37
+ }
38
+ }