vue2-client 1.8.238 → 1.8.241

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue2-client",
3
- "version": "1.8.238",
3
+ "version": "1.8.241",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint",
@@ -6,7 +6,7 @@
6
6
  compact>
7
7
  <a-input
8
8
  v-model="addressInput"
9
- :read-only="readOnly"
9
+ :read-only="readOnly || !this.addressObj.address"
10
10
  @change="change"
11
11
  style="flex: 1; width: auto; min-width: 0;"
12
12
  placeholder="请选择地址信息"/>
@@ -81,6 +81,7 @@ export default {
81
81
  type: String,
82
82
  default: undefined
83
83
  },
84
+ // outerContainerIndex,是为了XReport,返回外侧行的Index,每一行都有可能有图片,所以要知道是哪一个Index发出的事件
84
85
  outerContainerIndex: {
85
86
  type: [String, Number],
86
87
  default: undefined
@@ -96,10 +97,13 @@ export default {
96
97
  } else {
97
98
  this.uploadedFileList = list
98
99
  }
100
+ // 第三个参数‘created’,是因为XReport,有些图片上传需要外界自己控制上传下载的逻辑
101
+ // 如果在组件加载完成就emit的话,外侧组件会以为图片已经更新,会调用后端,造成性能浪费
102
+ // 所以外侧需要一个标识来判断,该emit事件是不是初始化的时候发出的
99
103
  if (this.outerContainerIndex !== undefined) {
100
- this.$emit('setFiles', this.uploadedFileList.filter(item => item.status === 'done'), this.outerContainerIndex)
104
+ this.$emit('setFiles', this.uploadedFileList.filter(item => item.status === 'done'), this.outerContainerIndex, 'created')
101
105
  } else {
102
- this.$emit('setFiles', this.uploadedFileList.filter(item => item.status === 'done').map(item => item.id))
106
+ this.$emit('setFiles', this.uploadedFileList.filter(item => item.status === 'done').map(item => item.id), undefined, 'created')
103
107
  }
104
108
  },
105
109
  methods: {
@@ -393,6 +393,7 @@
393
393
  :read-only="readOnly"
394
394
  v-model="searchResult"
395
395
  :resultKeys="{ address: attr.model, coords: `${attr.model}_lng_lat` }"
396
+ ref="addressSearchCombobox"
396
397
  searchResultType="Object"
397
398
  @onSelect="addressSearchComboboxSelect"
398
399
  @onDivisionsChange="onDivisionsChange"
@@ -583,6 +584,10 @@ export default {
583
584
  if (this.attr.keyName && (this.attr.keyName.toString().indexOf('async ') !== -1 || this.attr.keyName.toString().indexOf('function') !== -1)) {
584
585
  this.debouncedUpdateOptions()
585
586
  }
587
+ // 地址搜索框赋值
588
+ if (this.attr.type === 'addressSearch') {
589
+ this.$refs.addressSearchCombobox.addressInput = this.form[this.attr.model]
590
+ }
586
591
  },
587
592
  deep: true
588
593
  }
@@ -647,8 +652,8 @@ export default {
647
652
  this.initRadioValue()
648
653
  }
649
654
  },
650
- addressSearchComboboxSelect () {
651
- this.form = Object.assign(this.form, this.searchResult)
655
+ addressSearchComboboxSelect (data) {
656
+ this.form = Object.assign(this.form, JSON.parse(data))
652
657
  },
653
658
  onDivisionsChange (data) {
654
659
  this.emitFunc('addressSearchComboboxSelect', {
@@ -1,12 +1,16 @@
1
1
  <template>
2
2
  <div>
3
+ <!-- 骨架屏 -->
3
4
  <a-card v-if="showSkeleton">
4
5
  <a-skeleton active/>
5
6
  </a-card>
6
7
  <template v-if="noPadding">
7
8
  <!-- 主体表格 -->
8
9
  <XReportDesign
10
+ @updateImg="updateImg"
9
11
  v-if="scanFinish"
12
+ :use-oss-for-img="useOssForImg"
13
+ :display-only="displayOnly"
10
14
  :config="type === 'display' ? originalConfig : activeConfig"
11
15
  :slot-config-name="type === 'display' ? undefined : activatedSlotName"
12
16
  :for-display="type === 'display'"
@@ -23,7 +27,7 @@
23
27
  <!-- 用以包裹整个页面 -->
24
28
  <a-card v-if="!showSkeleton">
25
29
  <!-- 切换菜单 -->
26
- <a-radio-group v-model="type" default-value="a" button-style="solid" @change="tabChanged" v-show="!onlyDisplay">
30
+ <a-radio-group v-model="type" default-value="a" button-style="solid" @change="tabChanged" v-show="!onlyDisplay && editMode">
27
31
  <a-radio-button value="design" v-if="!onlyDisplay">
28
32
  设计
29
33
  </a-radio-button>
@@ -31,12 +35,15 @@
31
35
  预览
32
36
  </a-radio-button>
33
37
  </a-radio-group>
34
- <a-radio-button @click="saveConfig" style="border-radius: 0 4px 4px 0" v-if="!onlyDisplay">
38
+ <a-radio-button @click="saveConfig" style="border-radius: 0 4px 4px 0" v-if="showSaveButton">
35
39
  保存
36
40
  </a-radio-button>
37
41
  <!-- 主体表格 -->
38
42
  <XReportDesign
39
43
  v-if="scanFinish"
44
+ @updateImg="updateImg"
45
+ :use-oss-for-img="useOssForImg"
46
+ :display-only="displayOnly"
40
47
  :config="type === 'display' ? originalConfig : activeConfig"
41
48
  :slot-config-name="type === 'display' ? undefined : activatedSlotName"
42
49
  :for-display="type === 'display'"
@@ -78,60 +85,96 @@ export default {
78
85
  return []
79
86
  }
80
87
  },
88
+ // 控制用户权限,user和admin
81
89
  authority: {
82
90
  type: String,
83
91
  default: 'user'
84
92
  },
93
+ // 是否为编辑模式
94
+ editMode: {
95
+ type: Boolean,
96
+ default: true
97
+ },
98
+ // 配置名
85
99
  configName: {
86
100
  type: String,
87
101
  required: true
88
102
  },
103
+ // 插槽名
89
104
  activatedSlotName: {
90
105
  type: String,
91
106
  default: undefined
92
107
  },
108
+ // 本地配置,调试用
93
109
  localConfig: {
94
110
  type: Object,
95
111
  default: undefined
96
112
  },
113
+ // 兼容老版本配置
97
114
  dontFormat: {
98
115
  type: Boolean,
99
- default: false
116
+ default: true
100
117
  },
118
+ // 数据
101
119
  configData: {
102
120
  type: Object,
103
121
  default: undefined
104
122
  },
123
+ // 命名空间
105
124
  serverName: {
106
125
  type: String,
107
126
  default: 'af-system'
108
127
  },
128
+ // 只做展示
109
129
  displayOnly: {
110
130
  type: Boolean,
111
131
  default: false
112
132
  },
133
+ // 表格没有边距
113
134
  noPadding: {
114
135
  type: Boolean,
115
136
  default: false
116
137
  },
138
+ // 表格没有上边框,与noPadding搭配可以实现连续表格
117
139
  noTopBorder: {
118
140
  type: Boolean,
119
141
  default: false
120
142
  },
143
+ // 是否展示标题
121
144
  showTitle: {
122
145
  type: Boolean,
123
146
  default: true
124
147
  },
148
+ // 是否展示保存按钮
149
+ showSaveButton: {
150
+ type: Boolean,
151
+ default: true
152
+ },
153
+ // 是否将组件注册到外层提供的容器中,方便外侧统一保存
154
+ registerMap: {
155
+ type: Array,
156
+ default: undefined
157
+ },
158
+ // 图片是否使用OSS来保存
159
+ useOssForImg: {
160
+ type: Boolean,
161
+ default: true
162
+ }
125
163
  },
126
164
  components: {
127
165
  XReportDesign
128
166
  },
129
167
  data () {
130
168
  return {
169
+ // 控制骨架屏显隐
131
170
  showSkeleton: true,
171
+ // 配置
132
172
  config: undefined,
173
+ // 当前显示模式,编辑模式,预览模式
133
174
  type: 'design',
175
+ // 仅供展示,不可编辑
134
176
  onlyDisplay: false,
177
+ // 每行最大列数,非必要请勿更改,现在的设计器完全是基于每行12列来设计的
135
178
  maxColSpan: 12,
136
179
  // 定义是否完成配置的扫描,未完成不要渲染子组件
137
180
  scanFinish: false,
@@ -142,12 +185,20 @@ export default {
142
185
  originalConfig: null,
143
186
  // 扫描到的配置
144
187
  configFromWeb: {},
188
+ // 用于获取配置的锁
145
189
  timer: undefined,
190
+ // 是否包含图片
146
191
  hasImages: false,
147
- imageList: []
192
+ // 图片列表
193
+ imageList: [],
194
+ // 保存最原始的数据,用于判断哪些数据被更改了
195
+ dataCache: undefined,
196
+ // 判断哪些数据被更改了,存储对应的key
197
+ diff: []
148
198
  }
149
199
  },
150
200
  watch: {
201
+ // 如果配置名更改了,重新获取配置
151
202
  configName (val) {
152
203
  if (val) {
153
204
  getConfigByName(this.configName, undefined, res => {
@@ -156,6 +207,7 @@ export default {
156
207
  })
157
208
  }
158
209
  },
210
+ // 如果本地配置更改了,重新初始化
159
211
  localConfig (val) {
160
212
  if (val) {
161
213
  this.config = val
@@ -164,13 +216,71 @@ export default {
164
216
  }
165
217
  },
166
218
  methods: {
167
- saveConfig () {
168
- const tempDataKeys = Object.keys(this.activeConfig.tempData)
169
- tempDataKeys.forEach(key => {
170
- this.changeDeepObject(this.activeConfig.data, key, this.activeConfig.tempData[key])
219
+ // 向外暴露图片修改后的数据,某些外部需要自己管理图片的保存与修改
220
+ updateImg (data) {
221
+ this.$emit('updateImg', data)
222
+ },
223
+ // 导出数据,某些外部需要统一控制数据的变动
224
+ exportData () {
225
+ // 获取当前修改后的数据
226
+ let tempData
227
+ if (this.activeConfig === undefined || this.activeConfig === null) {
228
+ tempData = this.originalConfig.data
229
+ } else {
230
+ const tempDataKeys = Object.keys(this.activeConfig.tempData)
231
+ tempDataKeys.forEach(key => {
232
+ this.changeDeepObject(this.activeConfig.data, key, this.activeConfig.tempData[key])
233
+ })
234
+ tempData = this.activeConfig.data
235
+ }
236
+ // 对比数据的差异
237
+ this.diff = []
238
+ this.compareProps(tempData, this.dataCache)
239
+ this.diff.forEach(eachDiff => {
240
+ const arr = eachDiff.split('.')
241
+ let targetData = tempData[arr[0]]
242
+ if (arr.length !== 1) {
243
+ for (let i = 1; i < arr.length - 1; i++) {
244
+ const path = arr[i]
245
+ targetData = targetData[path]
246
+ }
247
+ }
248
+ // 将修改的数据,添加update = true属性
249
+ targetData.update = true
171
250
  })
172
- this.$emit('saveConfig', this.$refs.XReportDesign.activatedConfig)
251
+ return tempData
252
+ },
253
+ // 对比两个obj有哪里不同
254
+ compareProps (obj1, obj2, path = '') {
255
+ for (const key in obj1) {
256
+ // 如果一个是undefined
257
+ if (typeof obj2[key] === 'undefined') {
258
+ this.diff.push(path + key)
259
+ // 如果是数组长度不一样
260
+ } else if (obj1[key].length !== obj2[key].length) {
261
+ this.diff.push(path + key)
262
+ // 如果都是对象,并且存在同样的key,递归子key
263
+ } else if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') {
264
+ this.compareProps(obj1[key], obj2[key], path + key + '.')
265
+ // 如果不是obj,对比其数据
266
+ } else if (obj1[key] !== obj2[key]) {
267
+ this.diff.push(path + key)
268
+ }
269
+ }
270
+ },
271
+ // 正常的保存方法,当前修改内容会直接全部导出到外部
272
+ saveConfig () {
273
+ if (this.activeConfig === undefined || this.activeConfig === null) {
274
+ return this.originalConfig.data
275
+ } else {
276
+ const tempDataKeys = Object.keys(this.activeConfig.tempData)
277
+ tempDataKeys.forEach(key => {
278
+ this.changeDeepObject(this.activeConfig.data, key, this.activeConfig.tempData[key])
279
+ })
280
+ this.$emit('saveConfig', this.$refs.XReportDesign.activatedConfig)
281
+ }
173
282
  },
283
+ // 通过@@@分割临时变量,找到对应的key,并修改它的值
174
284
  changeDeepObject (obj, strPath, newVal) {
175
285
  const arr = strPath.split('@@@')
176
286
  if (obj[arr[0]] === undefined) {
@@ -302,6 +412,7 @@ export default {
302
412
  this.config.columns = newArr
303
413
  }
304
414
  },
415
+ // 路径中含有@@@的key,将其解析,并返回其数据
305
416
  getDeepObject (obj, strPath) {
306
417
  const arr = strPath.split('@@@')
307
418
  let result = obj[arr[0]]
@@ -566,6 +677,7 @@ export default {
566
677
  })
567
678
  })
568
679
 
680
+ // 使用定时器循环判断锁状态,用于多个插槽,要等待统一获取完成之后,再进行下一步初始化
569
681
  const timer = setInterval(() => {
570
682
  console.log('插槽下载进度,当前:' + count + '/' + total)
571
683
  if (count >= total) {
@@ -592,14 +704,18 @@ export default {
592
704
  },
593
705
  // 获取配置之后的初始化
594
706
  configInit () {
707
+ // 上锁,等待所有配置获取完成
595
708
  const lock = { status: true }
596
709
 
710
+ // 获取插槽
597
711
  this.getConfigAndJoin(this.config, lock)
598
712
 
713
+ // 用定时器循环查看锁状态
599
714
  this.timer = setInterval(() => {
600
715
  if (!lock.status) {
601
716
  clearInterval(this.timer)
602
717
  console.log('拼接完成', this.config)
718
+ // 将初始化好的配置拷贝一份留存
603
719
  this.originalConfig = Object.assign({}, this.config)
604
720
  if (!this.dontFormat) {
605
721
  // 扫描配置文件中有没有rowSpan,进行格式化调整
@@ -607,18 +723,23 @@ export default {
607
723
  }
608
724
  this.activeConfig = this.config
609
725
  this.showSkeleton = false
726
+ // 判断是否有动态Index
610
727
  this.activeConfig.columns.forEach(row => {
611
728
  row.forEach(cell => {
612
729
  if (cell.dynamicDataIndex === true) {
730
+ // 如果有动态index,取其函数,运行函数得到真实index保存
613
731
  // eslint-disable-next-line no-eval
614
732
  const func = eval('(' + cell.customFunctionForDynamicDataIndex + ')')
615
733
  cell.dataIndex = func(this.config)
616
734
  }
617
735
  })
618
736
  })
737
+ // 将数据复制到临时数据中,带有@@@的数据,我们将其整体作为一个key保存,当编辑完成后,再将其解析,回填到需要的数据中
619
738
  this.activeConfig.tempData = {}
739
+ // 是否有@@@深层引用
620
740
  this.activeConfig.columns.forEach(row => {
621
741
  row.forEach(cell => {
742
+ // 将@@@解析
622
743
  if (cell.dataIndex !== undefined && cell.dataIndex.indexOf('@@@') !== -1) {
623
744
  this.activeConfig.tempData[cell.dataIndex] = this.getDeepObject(this.activeConfig.data, cell.dataIndex)
624
745
  }
@@ -638,7 +759,7 @@ export default {
638
759
  this.originalConfig = Object.assign({}, this.config)
639
760
  this.originalConfig.data = JSON.parse(JSON.stringify(this.configData))
640
761
  this.type = 'display'
641
- this.onlyDisplay = true
762
+ // this.onlyDisplay = true
642
763
  this.showSkeleton = false
643
764
  this.$nextTick(() => {
644
765
  this.scanFinish = true
@@ -647,11 +768,14 @@ export default {
647
768
  },
648
769
  },
649
770
  beforeMount () {
771
+ // 如果只是展示
650
772
  if (this.displayOnly) {
651
773
  this.onlyDisplay = true
652
774
  this.type = 'display'
653
775
  }
776
+ // 如果有本地配置,优先使用本地配置
654
777
  if (this.localConfig) {
778
+ // 如果配置是json渲染器
655
779
  if (this.localConfig.designMode === 'json') {
656
780
  this.config = this.localConfig
657
781
  if (this.configData !== undefined) {
@@ -659,6 +783,7 @@ export default {
659
783
  }
660
784
  this.jsonConfigInit()
661
785
  } else {
786
+ // 如果配置是普通渲染器
662
787
  this.config = this.localConfig
663
788
  if (this.configData !== undefined) {
664
789
  this.config.data = this.configData
@@ -669,6 +794,7 @@ export default {
669
794
  this.configInit()
670
795
  }
671
796
  } else {
797
+ // 如果本地配置没有值,则从琉璃中获取
672
798
  getConfigByName(this.configName, this.serverName, res => {
673
799
  this.config = res
674
800
  if (this.config.designMode === 'json') {
@@ -687,6 +813,14 @@ export default {
687
813
  }
688
814
  })
689
815
  }
816
+ },
817
+ mounted () {
818
+ // 如果外界传来了registerMap,我们将本VM对象注册到map中
819
+ if (this.registerMap !== undefined) {
820
+ this.registerMap.push(this)
821
+ }
822
+ // 将原始数据备份保存
823
+ this.dataCache = JSON.parse(JSON.stringify(this.config.data))
690
824
  }
691
825
  }
692
826
  </script>