shijiplus-web-plugin 0.1.34 → 0.1.36

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.
@@ -0,0 +1,402 @@
1
+ <template>
2
+ <div class="plus-upload">
3
+ <div class="i-flex-wrap">
4
+ <div
5
+ class="demo-upload-list"
6
+ :key="item.id"
7
+ v-for="(item, index) in uploadList"
8
+ >
9
+ <template v-if="item.status === 'finished'">
10
+ <img @click="handleView(item.name)" :src="item.url" />
11
+ <Icon
12
+ v-if="!disabled"
13
+ @click.native="handleRemove(item, index)"
14
+ type="md-close-circle"
15
+ size="16"
16
+ color=""
17
+ />
18
+ </template>
19
+ <template v-else-if="item.showProgress">
20
+ <p class="f-s-14 f-w-400">上传中</p>
21
+ <Progress
22
+ :percent="item.percentage"
23
+ :stroke-width="4"
24
+ hide-info
25
+ ></Progress>
26
+ </template>
27
+ </div>
28
+ <Upload
29
+ v-if="!disabled"
30
+ ref="upload"
31
+ :show-upload-list="false"
32
+ :default-file-list="defaultFiles"
33
+ :on-success="handleSuccess"
34
+ :format="['jpg', 'jpeg', 'png', 'gif']"
35
+ accept="image/*"
36
+ :headers="headers"
37
+ :max-size="fileMaxSize"
38
+ :on-format-error="handleFormatError"
39
+ :on-exceeded-size="handleMaxSize"
40
+ :on-progress="handleProgress"
41
+ :before-upload="handleBeforeUpload"
42
+ :disabled="disabled"
43
+ multiple
44
+ type="drag"
45
+ :action="action || baseUrl + 'api/open/common/image/uploadDefaultImage'"
46
+ :class="{ hideUpload: remainderCount <= 0 }"
47
+ >
48
+ <div class="icon-wrap">
49
+ <Icon :type="'ios-add'" size="40"></Icon>
50
+ <p class="f-s-14 f-w-400">{{ imgTitle }}</p>
51
+ </div>
52
+ </Upload>
53
+ </div>
54
+ <p v-if="defaultHint" style="color: #ccc; line-height: 20px">
55
+ 最多上传{{ maxUploadFiles }}张图片,文件格式为png,jepg,jpg,或gif
56
+ </p>
57
+ <p v-if="hintText" class="f-s-12 f-w-400 upload-tips">{{ hintText }}</p>
58
+ <p class="f-s-12 f-w-400 upload-tips">
59
+ <slot name="tips"></slot>
60
+ </p>
61
+ <edit-modal title="查看图片" :show="visible">
62
+ <img
63
+ slot="editslot"
64
+ :src="imgName"
65
+ v-if="visible"
66
+ style="max-height: 100%; width: 100%"
67
+ />
68
+ <Row slot="bottom" type="flex" justify="center">
69
+ <Button @click="visible = false">关闭</Button>
70
+ </Row>
71
+ </edit-modal>
72
+ </div>
73
+ </template>
74
+ <script>
75
+ import config from '@/config'
76
+ import store from '@/store'
77
+ import Emitter from 'iview/src/mixins/emitter'
78
+ const baseUrl = config.plusApiV5Domain()
79
+ let authHeader = {}
80
+ authHeader[config.tokenHeaderName] = store.state.user.token
81
+ authHeader['token'] = store.state.user.token
82
+ authHeader['app_name'] = 'op'
83
+ export default {
84
+ name: 'upload-file',
85
+ mixins: [Emitter],
86
+ props: {
87
+ imgTitle: {
88
+ type: String,
89
+ default: '添加图片'
90
+ },
91
+ defaultHint: {
92
+ type: Boolean,
93
+ default: false
94
+ },
95
+ disabled: {
96
+ type: Boolean,
97
+ default: false
98
+ },
99
+ hintText: {
100
+ type: String,
101
+ default: ''
102
+ },
103
+ showImgList: {
104
+ default: () => {
105
+ return undefined
106
+ }
107
+ },
108
+ imagePath: {
109
+ default: undefined
110
+ },
111
+ addIconType: {
112
+ default: 'ios-camera'
113
+ },
114
+ maxUploadFiles: {
115
+ default: 1
116
+ },
117
+ maxSize: {
118
+ default: 200
119
+ },
120
+ sizeUnit: {
121
+ default: 1024
122
+ },
123
+ sizeUnitStr: {
124
+ default: 'MB'
125
+ },
126
+ action: {
127
+ default: ''
128
+ }
129
+ },
130
+ data() {
131
+ return {
132
+ headers: authHeader,
133
+ baseUrl,
134
+ imgName: '',
135
+ visible: false,
136
+ remainderCount: this.maxUploadFiles,
137
+ uploadList: [],
138
+ defaultFiles: []
139
+ }
140
+ },
141
+ computed: {
142
+ fileMaxSize() {
143
+ return this.maxSize * this.sizeUnit
144
+ }
145
+ },
146
+ watch: {
147
+ imagePath(value) {
148
+ this.uploadList = []
149
+ this.$refs.upload.clearFiles()
150
+ this.remainderCount = this.maxUploadFiles
151
+ if (!this.$isEmpty(value)) {
152
+ if (!this.$isEmpty(this.uploadList)) {
153
+ this.uploadList.push({
154
+ name: value,
155
+ url: value,
156
+ status: 'finished'
157
+ })
158
+ } else {
159
+ this.uploadList = [{ name: value, url: value, status: 'finished' }]
160
+ }
161
+ this.defaultFiles = this.$deepCopy(this.uploadList)
162
+ this.remainderCount -= this.uploadList.length
163
+ }
164
+ },
165
+ showImgList: {
166
+ deep: true,
167
+ immediate: true,
168
+ handler(value) {
169
+ this.$nextTick(() => {
170
+ if (this.$refs.upload && this.$refs.upload.fileList.length > 0) {
171
+ let uploadingImgs = this.$refs.upload.fileList.filter((item) => {
172
+ return item.status === 'uploading' // 不用改变status值
173
+ })
174
+ if (uploadingImgs.length > 0) {
175
+ return
176
+ }
177
+ }
178
+ this.remainderCount = this.maxUploadFiles
179
+ this.uploadList = []
180
+ if (!this.$isEmpty(value)) {
181
+ value.forEach((item, index) => {
182
+ this.uploadList.push({
183
+ name: item,
184
+ url: item,
185
+ status: 'finished'
186
+ })
187
+ })
188
+ }
189
+ this.defaultFiles = this.$deepCopy(this.uploadList)
190
+ this.remainderCount -= this.uploadList.length
191
+ })
192
+ }
193
+ }
194
+ },
195
+ methods: {
196
+ handleView(name) {
197
+ this.imgName = name
198
+ this.visible = true
199
+ },
200
+ handleRemove(file, index) {
201
+ this.$refs.upload.fileList.splice(index, 1)
202
+ this.uploadList = this.$refs.upload.fileList
203
+ this.remainderCount++
204
+ if (
205
+ !this.$isEmpty(this._events) &&
206
+ typeof this._events['on-remove'] === 'object'
207
+ ) {
208
+ this.$emit('on-remove', { index: index, target: this })
209
+ } else {
210
+ if (
211
+ this.maxUploadFiles === 1 &&
212
+ this.$containKey(this.$options.propsData, 'imagePath')
213
+ ) {
214
+ this.$emit('on-remove', { index: index, target: this })
215
+ } else {
216
+ this.showImgList.splice(index, 1)
217
+ }
218
+ }
219
+ this.dispatch('FormItem', 'on-form-change', this.uploadList)
220
+ },
221
+ handleSuccess(res, file) {
222
+ if (this.action) {
223
+ // 对新露的上传接口做兼容, 他用的是其他字段
224
+ res.data.path = res.data.accessURL
225
+ }
226
+ if (!res.data) {
227
+ console.log(res)
228
+ file.status = 'fail'
229
+ this.$Notice.error({
230
+ title: `上传失败`,
231
+ desc: res.codex + ':' + res.message
232
+ })
233
+ this.uploadList.forEach((item, index) => {
234
+ if (item.status == 'fail') {
235
+ this.uploadList.splice(index, 1)
236
+ }
237
+ })
238
+ this.remainderCount++
239
+ return
240
+ }
241
+ if (!res.data.path) {
242
+ console.log(res)
243
+ file.status = 'fail'
244
+ this.$Notice.error({
245
+ title: `上传失败`,
246
+ desc: res.message
247
+ })
248
+ this.uploadList.forEach((item, index) => {
249
+ if (item.status == 'fail') {
250
+ this.uploadList.splice(index, 1)
251
+ }
252
+ })
253
+ this.remainderCount++
254
+ return
255
+ }
256
+ file.url = res.data.path
257
+ file.name = res.data.path
258
+ file.status = 'finished'
259
+ this.uploadList = this.$refs.upload.fileList
260
+ if (
261
+ !this.$isEmpty(this._events) &&
262
+ typeof this._events['on-upload-complete'] === 'object'
263
+ ) {
264
+ this.$emit('on-upload-complete', { res: res, file: file, target: this })
265
+ } else {
266
+ if (this.maxUploadFiles === 1) {
267
+ if (this.$containKey(this.$options.propsData, 'imagePath')) {
268
+ this.$emit('on-upload-complete', {
269
+ res: res,
270
+ file: file,
271
+ target: this
272
+ })
273
+ } else {
274
+ this.showImgList.splice(0, this.showImgList.length)
275
+ this.showImgList.push(res.data.path)
276
+ }
277
+ } else {
278
+ this.showImgList.push(res.data.path)
279
+ }
280
+ }
281
+ this.dispatch('FormItem', 'on-form-change', this.uploadList)
282
+ },
283
+ handleFormatError(file) {
284
+ this.remainderCount++
285
+ this.$Notice.warning({
286
+ title: '文件格式错误',
287
+ desc: '只能上传 jpeg, jpg 或 png 文件.'
288
+ })
289
+ },
290
+ handleMaxSize(file) {
291
+ this.remainderCount++
292
+ console.log('-------handleMaxSize----------')
293
+ this.$Notice.warning({
294
+ title: `文件超过${this.fileMaxSize / this.sizeUnit}${this.sizeUnitStr}`,
295
+ desc: `文件不能大于 ${this.fileMaxSize / this.sizeUnit}${
296
+ this.sizeUnitStr
297
+ }`
298
+ })
299
+ },
300
+ handleBeforeUpload() {
301
+ var check = true
302
+ if (this.remainderCount <= 0) {
303
+ this.$Notice.warning({
304
+ title: `只能上传 ${this.maxUploadFiles} 张图片.`
305
+ })
306
+ check = false
307
+ } else {
308
+ this.remainderCount--
309
+ }
310
+ return check
311
+ },
312
+ // 图片上传进度
313
+ handleProgress(event, file, fileList) {
314
+ if (file) {
315
+ file.showProgress = true
316
+ file.status = 'uploading'
317
+ file.percentage = event.percent || 100
318
+ const hasThisUrl =
319
+ this.uploadList.filter((item) => {
320
+ return item.uid == file.uid
321
+ }).length > 0
322
+ if (!hasThisUrl) {
323
+ // file.url = file.response.result
324
+ this.uploadList.push(file)
325
+ }
326
+ }
327
+ }
328
+ },
329
+ mounted() {}
330
+ }
331
+ </script>
332
+ <style lang="less" scoped>
333
+ .hideUpload {
334
+ display: none !important;
335
+ }
336
+ .demo-upload-list {
337
+ position: relative;
338
+ display: flex;
339
+ flex-direction: column;
340
+ align-items: center;
341
+ justify-content: center;
342
+ width: 112px;
343
+ height: 112px;
344
+ border: 1px solid #dcdee2;
345
+ border-radius: 4px;
346
+ margin-right: 16px;
347
+ .f-s-14 {
348
+ margin-bottom: 12px;
349
+ color: #515a6e;
350
+ }
351
+ .ivu-icon-md-close-circle {
352
+ position: absolute;
353
+ top: 8px;
354
+ right: 8px;
355
+ background-color: #fff;
356
+ border-radius: 50%;
357
+ }
358
+ }
359
+ .demo-upload-list img {
360
+ display: block;
361
+ margin: auto;
362
+ width: 104px;
363
+ height: 104px;
364
+ border-radius: 4px;
365
+ object-fit: contain;
366
+ }
367
+ .plus-upload {
368
+ .upload-tips {
369
+ color: #9ea7b4;
370
+ margin-top: 12px;
371
+ }
372
+ .ivu-progress {
373
+ line-height: 1;
374
+ width: ~'calc(100% - 16px)';
375
+ }
376
+ .ivu-upload {
377
+ display: inline-block;
378
+ width: 112px;
379
+ height: 112px;
380
+ background: #f8f8f9;
381
+ border-radius: 4px;
382
+ }
383
+ /deep/.ivu-upload-drag {
384
+ width: 112px;
385
+ height: 112px;
386
+ background: #f8f8f9;
387
+ .icon-wrap {
388
+ display: flex;
389
+ flex-direction: column;
390
+ align-items: center;
391
+ justify-content: center;
392
+ background: transparent;
393
+ width: 112px;
394
+ height: 112px;
395
+ .f-s-14 {
396
+ margin-top: 12px;
397
+ color: #515a6e;
398
+ }
399
+ }
400
+ }
401
+ }
402
+ </style>
@@ -17,6 +17,7 @@ const install = (vue, opts = {}) => {
17
17
  vue.prototype.$addYears = addYears
18
18
  vue.prototype.$getDateFromString = getDateFromString
19
19
  vue.prototype.$formatterDateString = formatterDateString
20
+ vue.prototype.$dealDate = dealDate
20
21
  vue.prototype.$dateDiff = dateDiff
21
22
  vue.prototype.$beautyWeekDay = beautyWeekDay
22
23
  Date.prototype.addDays = function (days) {
@@ -34,6 +35,18 @@ const install = (vue, opts = {}) => {
34
35
  }
35
36
  }
36
37
 
38
+ function dealDate(fromtime) {
39
+ const myDate = new Date(fromtime)
40
+ const year = myDate.getFullYear() // 获取完整的年份(4位,1970-????)
41
+ let month = myDate.getMonth() // 获取当前月份(0-11,0代表1月) // 所以获取当前月份是myDate.getMonth()+1;
42
+ let date = myDate.getDate() // 获取当前日(1-31)
43
+ month = prefixZero(month + 1)
44
+ date = prefixZero(date)
45
+ return `${year}-${month}-${(date)}`
46
+ }
47
+ const prefixZero = (num) => {
48
+ return (Array(2).join(0) + num).slice(-2)
49
+ }
37
50
  function formatterDateString(dateStr, fmt = 'yyyy-MM-dd') {
38
51
  if (!dateStr) {
39
52
  return '--'
@@ -43,6 +43,7 @@ const install = (vue, opts = {}) => {
43
43
  })
44
44
  return result
45
45
  }
46
+ vue.prototype.$isEqual = isEqual
46
47
  }
47
48
 
48
49
  function convertNumberToString(obj) {
@@ -57,6 +58,30 @@ function convertNumberToString(obj) {
57
58
  })
58
59
  return obj
59
60
  }
61
+ function isEqual(obj1, obj2) {
62
+ // 判断类型是否相等
63
+ if (typeof obj1 !== typeof obj2) {
64
+ return false
65
+ }
66
+ // 如果是基本类型直接比较值
67
+ if (typeof obj1 !== 'object' || obj1 === null || obj2 === null) {
68
+ return obj1 === obj2
69
+ }
70
+ // 获取两个对象的属性名数组
71
+ const keys1 = Object.keys(obj1)
72
+ const keys2 = Object.keys(obj2)
73
+ // 属性数量不相等,返回false
74
+ if (keys1.length !== keys2.length) {
75
+ return false
76
+ }
77
+ // 比较每个属性的值
78
+ for (let key of keys1) {
79
+ if (!isEqual(obj1[key], obj2[key])) {
80
+ return false
81
+ }
82
+ }
83
+ return true
84
+ }
60
85
  function objValueFromArr(arr, key) {
61
86
  let tempValues = []
62
87
  arr.forEach(item => {
@@ -23,9 +23,19 @@ const install = (vue, opts = {}) => {
23
23
  vComp.$el.parentNode.removeChild(vComp.$el)
24
24
  }
25
25
  }
26
- vue.prototype.$getComponentInstance = (component) => {
26
+ vue.prototype.$getComponentInstance = (component, options) => {
27
+ const defaultConfig = {
28
+ props: {}
29
+ }
30
+ const { props } = Object.assign(Object.assign({}, defaultConfig), options)
27
31
  const ComponentClass = Vue.extend(component)
28
- const instance = new ComponentClass({ store: opts.store })
32
+ const instance = new ComponentClass({
33
+ store: opts.store,
34
+ props,
35
+ propsData: {
36
+ props: props
37
+ }
38
+ })
29
39
  instance.$mount()
30
40
  document.body.appendChild(instance.$el)
31
41
  return instance
package/src/index.js CHANGED
@@ -5,6 +5,9 @@ import ExtentionPlugin from './extentionPlugin'
5
5
  import importDirective from './directive'
6
6
  import PlusComp from './components/plus-comp'
7
7
  import BeginEndDatePicker from './components/begin-end-date-picker'
8
+ import UploadFileSingle from './components/upload-file/upload-file-single'
9
+ import UploadFile from './components/upload-file/upload-file'
10
+ import UploadFileInput from './components/upload-file/upload-file-input'
8
11
 
9
12
  console.log('--------web-tool---index.js----------')
10
13
 
@@ -19,6 +22,9 @@ export default {
19
22
  install(vue, opts = {}) {
20
23
  vue.use(PlusComp)
21
24
  vue.component('BeginEndDatePicker', BeginEndDatePicker)
25
+ vue.component('UploadFileSingle', UploadFileSingle)
26
+ vue.component('UploadFile', UploadFile)
27
+ vue.component('UploadFileInput', UploadFileInput)
22
28
  /**
23
29
  * 注册指令
24
30
  */