shijiplus-web-plugin 0.1.11 → 0.1.12

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 (27) hide show
  1. package/package.json +8 -4
  2. package/src/App.vue +3 -1
  3. package/src/components/plus-comp/index.js +15 -0
  4. package/src/components/plus-comp/permission-component/permission-component.vue +78 -0
  5. package/src/components/plus-comp/plus-card/plus-card.vue +21 -0
  6. package/src/components/plus-comp/plus-city-cascader/plus-city-cascader.vue +108 -0
  7. package/src/components/plus-comp/plus-common-header/plus-common-header.vue +58 -0
  8. package/src/components/plus-comp/plus-count-down/plus-count-down.vue +51 -0
  9. package/src/components/plus-comp/plus-drawer/plus-drawer.vue +116 -0
  10. package/src/components/plus-comp/plus-form/plus-form.vue +149 -0
  11. package/src/components/plus-comp/plus-icon/plus-icon.vue +91 -0
  12. package/src/components/plus-comp/plus-modal/plus-modal.vue +281 -0
  13. package/src/components/plus-comp/plus-poptip/plus-poptip.vue +42 -0
  14. package/src/components/plus-comp/plus-qr-code/plus-qr-code.vue +110 -0
  15. package/src/components/plus-comp/plus-remote-selector/plus-remote-selector.vue +126 -0
  16. package/src/components/plus-comp/plus-scrollview/plus-scrollview.vue +58 -0
  17. package/src/components/plus-comp/plus-select/plus-select.vue +118 -0
  18. package/src/components/plus-comp/plus-table/export-mixin.js +78 -0
  19. package/src/components/plus-comp/plus-table/plus-circle-progress-modal.vue +54 -0
  20. package/src/components/plus-comp/plus-table/plus-table.vue +568 -0
  21. package/src/components/plus-comp/plus-tabs/plus-tabs.vue +76 -0
  22. package/src/directive/index.js +2 -0
  23. package/src/directive/module/authAccess.js +2 -2
  24. package/src/extentionPlugin/string.js +30 -1
  25. package/src/libs/excel.js +203 -0
  26. package/src/libs/util.js +184 -0
  27. package/src/main.js +2 -0
@@ -0,0 +1,91 @@
1
+ <template>
2
+ <Icon v-if="type" :type="type" :size="size" :color="color" />
3
+ <span v-else-if="src" ref="plusIconInnerRef" class="plus-icon">
4
+ <img :src="handleSrc(src)" />
5
+ </span>
6
+ </template>
7
+ <script>
8
+ export default {
9
+ props: {
10
+ type: {
11
+ type: String,
12
+ default: ''
13
+ },
14
+ src: {
15
+ type: String,
16
+ default: ''
17
+ },
18
+ color: {
19
+ type: String,
20
+ default: ''
21
+ },
22
+ size: {
23
+ type: Number,
24
+ default: 16
25
+ }
26
+ },
27
+ watch: {
28
+ size: {
29
+ handler(val) {
30
+ if (val) {
31
+ this.$nextTick(() => {
32
+ if (this.$refs.plusIconInnerRef) {
33
+ this.$refs.plusIconInnerRef.style.setProperty(
34
+ '--size',
35
+ val + 'px'
36
+ )
37
+ }
38
+ })
39
+ }
40
+ },
41
+ deep: true,
42
+ immediate: true
43
+ },
44
+ color: {
45
+ handler(val) {
46
+ if (val) {
47
+ this.$nextTick(() => {
48
+ if (this.$refs.plusIconInnerRef) {
49
+ this.$refs.plusIconInnerRef.style.setProperty(
50
+ '--filterColor',
51
+ val
52
+ )
53
+ this.$refs.plusIconInnerRef.style.setProperty('--vector', -1)
54
+ }
55
+ })
56
+ }
57
+ },
58
+ deep: true,
59
+ immediate: true
60
+ }
61
+ },
62
+ computed: {},
63
+ data() {
64
+ return {}
65
+ },
66
+ methods: {
67
+ handleSrc(src) {
68
+ const ss = src.replace('@/assets', '')
69
+ return require(`@/assets` + ss)
70
+ }
71
+ }
72
+ }
73
+ </script>
74
+ <style lang="less" scoped>
75
+ .plus-icon {
76
+ display: block;
77
+ overflow: hidden;
78
+ --size: 16px;
79
+ --filterColor: transparent;
80
+ --vector: 0;
81
+ width: var(--size);
82
+ height: var(--size);
83
+ img {
84
+ position: relative;
85
+ width: var(--size);
86
+ height: var(--size);
87
+ left: ~'calc(var(--size) * var(--vector))';
88
+ filter: drop-shadow(var(--size) 0px var(--filterColor));
89
+ }
90
+ }
91
+ </style>
@@ -0,0 +1,281 @@
1
+ <template>
2
+ <Modal
3
+ id="plus-modal"
4
+ ref="modal"
5
+ v-model="visiable"
6
+ :closable="closable"
7
+ :mask-closable="false"
8
+ :width="width"
9
+ :transfer="transfer"
10
+ :styles="modalStyles"
11
+ :class-name="className"
12
+ @on-visible-change="visibleChange"
13
+ >
14
+ <div
15
+ v-if="title"
16
+ :style="headerStyles"
17
+ class="plus-modal-header f-s-16 f-w-600"
18
+ slot="header"
19
+ >
20
+ {{ title }}
21
+ </div>
22
+ <div ref="editslotRef" id="editslot" :style="editSlotStyle">
23
+ <slot></slot>
24
+ </div>
25
+ <div
26
+ slot="footer"
27
+ ref="footerRef"
28
+ :class="['plus-modal-footer', 'i-flex-wrap justify-center align-center']"
29
+ >
30
+ <slot name="footer">
31
+ <Button type="primary" @click="handlerClose"> 关闭 </Button>
32
+ </slot>
33
+ </div>
34
+ <Spin v-if="showLoading" fix>
35
+ <Icon type="ios-loading" size="18" class="demo-spin-icon-load"></Icon>
36
+ <div>{{ loadingTip || '正在处理...' }}</div>
37
+ </Spin>
38
+ </Modal>
39
+ </template>
40
+ <script>
41
+ export default {
42
+ name: 'edit-modal',
43
+ props: {
44
+ props: {
45
+ type: Object,
46
+ default() {
47
+ return {
48
+ show: false
49
+ }
50
+ }
51
+ },
52
+ closable: {
53
+ type: Boolean,
54
+ default: false
55
+ },
56
+ footerHide: {
57
+ type: Boolean,
58
+ default: false
59
+ },
60
+ title: {
61
+ default: null
62
+ },
63
+ showLoading: {
64
+ default: false
65
+ },
66
+ loadingTip: {
67
+ default: '正在处理...'
68
+ },
69
+ width: {
70
+ default: 520
71
+ },
72
+ headerCenter: {
73
+ default: false
74
+ },
75
+ transfer: {
76
+ default: true
77
+ },
78
+ fillParent: {
79
+ type: Boolean,
80
+ default: false
81
+ },
82
+ styles: {
83
+ type: Object,
84
+ default() {
85
+ return {
86
+ height: 'fit-content'
87
+ }
88
+ }
89
+ },
90
+ padding: {
91
+ type: String,
92
+ default: '16px 24px'
93
+ }
94
+ },
95
+ watch: {
96
+ 'props.show': {
97
+ handler(nValue) {
98
+ this.visiable = nValue
99
+ this.$nextTick(() => {
100
+ if (this.$slots.footer) {
101
+ if (this.$slots.footer[0] && this.$slots.footer[0].elm) {
102
+ if (!this.$slots.footer[0].elm.clientHeight) {
103
+ let height = window
104
+ .getComputedStyle(this.$slots.footer[0].elm)
105
+ .getPropertyValue('height')
106
+ if (!height || parseInt(height) == 0) {
107
+ this.$refs.footerRef.parentElement.style.display = 'none'
108
+ } else {
109
+ this.$refs.footerRef.parentElement.style.display = 'block'
110
+ }
111
+ } else {
112
+ this.$refs.footerRef.parentElement.style.display = 'block'
113
+ }
114
+ }
115
+ }
116
+ })
117
+ },
118
+ deep: true,
119
+ immediate: true
120
+ }
121
+ },
122
+ data() {
123
+ return {
124
+ visiable: false,
125
+ headerStyles: {
126
+ 'text-align': 'center'
127
+ },
128
+ computedPadding: ''
129
+ }
130
+ },
131
+ computed: {
132
+ modalStyles() {
133
+ return {
134
+ ...this.styles
135
+ }
136
+ },
137
+ className() {
138
+ return (
139
+ 'vertical-center-modal fill-parent' +
140
+ (this.footerHide ? ' footerHide' : '') +
141
+ (this.title ? '' : ' headerHide')
142
+ )
143
+ },
144
+ editSlotStyle() {
145
+ let maxHeight =
146
+ document.body.clientHeight -
147
+ (this.footerHide ? 0 : 80) -
148
+ (this.title ? 60 : 0) -
149
+ 60 +
150
+ 'px'
151
+ return {
152
+ 'overflow-y': 'auto',
153
+ 'max-height': maxHeight,
154
+ padding: this.computedPadding || this.padding
155
+ }
156
+ }
157
+ },
158
+ methods: {
159
+ handlerClose() {
160
+ this.props.show = false
161
+ this.$emit('on-close')
162
+ },
163
+ visibleChange(e) {
164
+ this.props.show = e
165
+ if (!e) {
166
+ this.$emit('on-close')
167
+ } else {
168
+ this.$nextTick(() => {
169
+ if (
170
+ this.$refs.editslotRef.scrollHeight >
171
+ this.$refs.editslotRef.clientHeight
172
+ ) {
173
+ var styles = window.getComputedStyle(this.$refs.editslotRef)
174
+
175
+ // 如果您只想获取特定方向的padding值,例如padding-top
176
+ var paddingLeft = parseFloat(
177
+ styles.getPropertyValue('padding-left')
178
+ )
179
+ var paddingRight = parseFloat(
180
+ styles.getPropertyValue('padding-right')
181
+ )
182
+ var paddingTop = parseFloat(styles.getPropertyValue('padding-top'))
183
+ var paddingBottom = parseFloat(
184
+ styles.getPropertyValue('padding-bottom')
185
+ )
186
+ this.$refs.editslotRef.style.width = `calc(100% + ${paddingRight}px)`
187
+ this.$refs.editslotRef.style.marginLeft = `-${paddingRight}px`
188
+ this.$refs.editslotRef.style.paddingRight = 0
189
+ this.$refs.editslotRef.style.paddingLeft = `${
190
+ paddingLeft + paddingRight
191
+ }px`
192
+ this.computedPadding = `${paddingTop}px ${0}px ${paddingBottom}px ${
193
+ paddingLeft + paddingRight
194
+ }px`
195
+ }
196
+ })
197
+ }
198
+ }
199
+ },
200
+ mounted() {}
201
+ }
202
+ </script>
203
+ <style lang="less">
204
+ #plus-modal {
205
+ height: 100%;
206
+ .vertical-center-modal {
207
+ display: flex;
208
+ align-items: center;
209
+ justify-content: center;
210
+ .ivu-modal {
211
+ top: 0;
212
+ /*flex: 0;*/
213
+ }
214
+ }
215
+ .fill-parent {
216
+ overflow: hidden;
217
+ .ivu-modal {
218
+ height: 98%;
219
+ max-height: 100vh;
220
+ .ivu-modal-content {
221
+ max-height: 100vh;
222
+ height: 100%;
223
+ .ivu-modal-body {
224
+ display: flex;
225
+ flex-direction: column;
226
+ height: calc(~'100% - 50px');
227
+ padding: 0;
228
+ #editslot {
229
+ position: relative;
230
+ flex-grow: 1;
231
+ max-height: calc(~'100% - 35px');
232
+ overflow: auto;
233
+ padding: 16px 24px;
234
+ }
235
+ .bottom {
236
+ flex-shrink: 0;
237
+ }
238
+ }
239
+ }
240
+ }
241
+ }
242
+ .ivu-modal-header {
243
+ padding: 0;
244
+ line-height: 60px;
245
+ height: 60px;
246
+ padding: 0;
247
+ // border-bottom: none;
248
+ .plus-modal-header {
249
+ font-family: PingFangSC-SNaNpxibold;
250
+ color: #17233d;
251
+ letter-spacing: 0.44px;
252
+ text-align: center;
253
+ line-height: 60px;
254
+ height: 60px;
255
+ }
256
+ }
257
+ .ivu-modal-footer {
258
+ text-align: center;
259
+ // border-top: none;
260
+ min-height: 80px;
261
+ padding: 0 24px;
262
+ .plus-modal-footer {
263
+ min-height: 80px;
264
+ &.i-flex-wrap {
265
+ * {
266
+ margin-top: 0;
267
+ margin-right: 5px;
268
+ &:last-child {
269
+ margin-right: 0;
270
+ }
271
+ }
272
+ }
273
+ }
274
+ }
275
+ .footerHide {
276
+ .ivu-modal-footer {
277
+ display: none;
278
+ }
279
+ }
280
+ }
281
+ </style>
@@ -0,0 +1,42 @@
1
+ <template>
2
+ <Poptip
3
+ class="plus-poptip"
4
+ popper-class="plus-poptip-content"
5
+ :trigger="trigger"
6
+ :padding="padding"
7
+ :width="width"
8
+ >
9
+ <slot></slot>
10
+ <div slot="content">
11
+ <slot name="content"></slot>
12
+ </div>
13
+ </Poptip>
14
+ </template>
15
+ <script>
16
+ export default {
17
+ props: {
18
+ width: {
19
+ type: String,
20
+ default: '150px'
21
+ },
22
+ padding: {
23
+ type: String,
24
+ default: '8px 16px'
25
+ },
26
+ trigger: {
27
+ default: 'hover'
28
+ }
29
+ }
30
+ }
31
+ </script>
32
+ <style lang="less" scoped>
33
+ .plus-poptip {
34
+ z-index: 1100;
35
+ }
36
+ /deep/.plus-poptip-content {
37
+ &.ivu-poptip-popper {
38
+ min-width: initial;
39
+ }
40
+ z-index: 9999;
41
+ }
42
+ </style>
@@ -0,0 +1,110 @@
1
+ <template>
2
+ <div
3
+ :ref="myRef"
4
+ class="plus-qr-code"
5
+ style="display: flex; justify-content: center"
6
+ >
7
+ <div
8
+ class="qrcodeEl"
9
+ :ref="'qrcodeEl'"
10
+ :style="`height:${size}px;width:${size}px;`"
11
+ ></div>
12
+ </div>
13
+ </template>
14
+ <script>
15
+ import html2canvas from 'html2canvas'
16
+ import QRCode from 'qrcodejs2'
17
+ export default {
18
+ props: {
19
+ type: {
20
+ type: String,
21
+ default: 'qrcode' // miniapp
22
+ },
23
+ size: {
24
+ default: 100
25
+ },
26
+ codeContent: {
27
+ default: 'asdasdasdasdasd'
28
+ }
29
+ },
30
+ watch: {
31
+ codeContent: {
32
+ handler(value) {
33
+ this.$nextTick(() => {
34
+ if (value) {
35
+ if (this.type == 'qrcode') {
36
+ new QRCode(this.$refs.qrcodeEl, {
37
+ width: this.size * 2,
38
+ height: this.size * 2 // 高度
39
+ }).makeCode(value) // 二维码内容 // https://h5-dev.shijiplus.com/shop-events
40
+ } else {
41
+ const img = new Image()
42
+ img.src = value
43
+ this.$refs.qrcodeEl.append(img)
44
+ }
45
+ } else {
46
+ this.$refs.qrcodeEl.innerHTML = ''
47
+ }
48
+ })
49
+ },
50
+ deep: true,
51
+ immediate: true
52
+ }
53
+ },
54
+ data() {
55
+ const timeStamp = new Date().getTime()
56
+ return {
57
+ myRef: String(timeStamp)
58
+ }
59
+ },
60
+ methods: {
61
+ saveCode(name) {
62
+ return new Promise((resolve, reject) => {
63
+ if (this.type != 'qrcode') {
64
+ var a = document.createElement('a')
65
+ var event = new MouseEvent('click')
66
+ a.download = `${name || '二维码'}.png`
67
+ a.href = this.codeContent
68
+ a.dispatchEvent(event)
69
+ resolve()
70
+ } else {
71
+ html2canvas(this.$refs[this.myRef], {
72
+ allowTaint: false,
73
+ // taintTest: false,
74
+ dpi: window.devicePixelRatio * 4,
75
+ useCORS: true,
76
+ scale: 6
77
+ // width: 200,
78
+ // height: 200
79
+ })
80
+ .then((canvas) => {
81
+ var a = document.createElement('a')
82
+ var event = new MouseEvent('click')
83
+ a.download = `${name || '二维码'}.png`
84
+ a.href = canvas.toDataURL('image/png')
85
+ a.dispatchEvent(event)
86
+ resolve()
87
+ })
88
+ .catch((err) => {
89
+ console.error('savecode error', err)
90
+ reject(err)
91
+ })
92
+ }
93
+ })
94
+ }
95
+ }
96
+ }
97
+ </script>
98
+ <style lang="less" scoped>
99
+ .plus-qr-code {
100
+ width: fit-content;
101
+ .qrcodeEl {
102
+ overflow: hidden;
103
+ /deep/img {
104
+ display: block;
105
+ width: 100%;
106
+ height: 100%;
107
+ }
108
+ }
109
+ }
110
+ </style>
@@ -0,0 +1,126 @@
1
+ <template>
2
+ <Select
3
+ ref="select"
4
+ filterable
5
+ clearable
6
+ remote
7
+ label-in-value
8
+ :placeholder="placeholder"
9
+ @on-change="valueChange"
10
+ @on-open-change="openChange"
11
+ :remote-method="remoteMethod"
12
+ :loading="loading"
13
+ >
14
+ <Option
15
+ v-for="(option, index) in options"
16
+ :value="option[valueKey]"
17
+ :key="index"
18
+ :label="option.showLabel"
19
+ />
20
+ </Select>
21
+ </template>
22
+ <script>
23
+ import { throttle } from '../../../libs/util'
24
+ export default {
25
+ name: 'plus-remote-selector',
26
+ model: {
27
+ prop: 'modelValue',
28
+ event: 'change'
29
+ },
30
+ props: {
31
+ modelValue: [Number, String],
32
+ showName: {
33
+ type: [String, Number],
34
+ default: ''
35
+ },
36
+ valueKey: {
37
+ type: String,
38
+ default: 'id'
39
+ },
40
+ labelKeys: {
41
+ type: [String, Array],
42
+ default: 'name'
43
+ },
44
+ placeholder: {
45
+ default: '输入关键字搜索'
46
+ },
47
+ remoteFun: Function
48
+ },
49
+ watch: {
50
+ modelValue: {
51
+ handler(val) {
52
+ if (val) {
53
+ this.$nextTick(() => {
54
+ this.$refs.select.$data.query = this.showName
55
+ })
56
+ }
57
+ },
58
+ immediate: true
59
+ }
60
+ },
61
+ data() {
62
+ return {
63
+ loading: false,
64
+ options: [],
65
+ keyword: null
66
+ }
67
+ },
68
+ methods: {
69
+ valueChange(e) {
70
+ if (e) {
71
+ this.$emit('change', e.value)
72
+ this.$emit('change-option', { ...e })
73
+ this.$refs.select.$data.query = e.label
74
+ } else {
75
+ this.$emit('change', null)
76
+ this.$emit('change-option', {})
77
+ }
78
+ },
79
+ openChange(e) {
80
+ if (!e) {
81
+ this.$refs.select.isFocused = false
82
+ if (this.showName) {
83
+ this.$nextTick(() => {
84
+ this.$refs.select.$data.query = this.showName
85
+ })
86
+ }
87
+ }
88
+ },
89
+ remoteMethod(query) {
90
+ const fun = () => {
91
+ this.searchLoading = true
92
+ const result = this.remoteFun(query)
93
+ if (result instanceof Promise) {
94
+ result
95
+ .then((resp) => {
96
+ if (resp.data) {
97
+ resp.data.forEach((item) => {
98
+ item.showLabel = ''
99
+ if (this.labelKeys) {
100
+ let tempKeys = this.labelKeys
101
+ if (typeof tempKeys == 'string') {
102
+ tempKeys = this.labelKeys.split(',')
103
+ }
104
+ tempKeys.forEach((key) => {
105
+ item.showLabel += item[key]
106
+ })
107
+ }
108
+ })
109
+ this.options = resp.data
110
+ }
111
+ })
112
+ .catch((err) => {
113
+ console.log('-------remoteMethod-------', err)
114
+ })
115
+ .finally(() => {
116
+ this.searchLoading = false
117
+ })
118
+ } else if (!result) {
119
+ throw Error('remoteFun must return promise')
120
+ }
121
+ }
122
+ throttle(fun, 1000)
123
+ }
124
+ }
125
+ }
126
+ </script>
@@ -0,0 +1,58 @@
1
+ <template>
2
+ <div :id="scrollId" class="scroll-wrap">
3
+ <slot>
4
+ <div class="empty-wrap">暂无数据</div>
5
+ </slot>
6
+ <div v-if="showLoadingBar" class="i-flex-wrap justify-center loading-bar">
7
+ {{ loadText }}
8
+ </div>
9
+ </div>
10
+ </template>
11
+ <script>
12
+ export default {
13
+ props: {
14
+ loadText: {
15
+ default: '数据加载中...'
16
+ }
17
+ },
18
+ data() {
19
+ return { scrollId: null, showLoadingBar: false }
20
+ },
21
+ mounted() {
22
+ this.scrollId = new Date().getTime()
23
+ this.$nextTick(() => {
24
+ const scrollEle = document.getElementById(this.scrollId)
25
+ scrollEle.addEventListener('scroll', () => {
26
+ if (
27
+ scrollEle.scrollTop > 0 &&
28
+ scrollEle.scrollHeight -
29
+ (scrollEle.scrollTop + scrollEle.clientHeight) <
30
+ 1
31
+ ) {
32
+ this.showLoadingBar = true
33
+ this.$emit('on-reach-bottom')
34
+ console.log('已滑动到底部')
35
+ // 执行到达底部后的操作
36
+ }
37
+ })
38
+ })
39
+ }
40
+ }
41
+ </script>
42
+ <style lang="less" scoped>
43
+ .scroll-wrap {
44
+ overflow: auto;
45
+ .empty-wrap {
46
+ display: flex;
47
+ width: 100%;
48
+ height: 100%;
49
+ align-content: center;
50
+ align-items: center;
51
+ justify-items: center;
52
+ justify-content: center;
53
+ }
54
+ .loading-bar {
55
+ display: none;
56
+ }
57
+ }
58
+ </style>