tianheng-ui 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 (31) hide show
  1. package/lib/tianheng-ui.js +13 -14
  2. package/package.json +1 -1
  3. package/packages/FormMaking/GenerateForm.vue +6 -1
  4. package/packages/FormMaking/GenerateFormItem.vue +7 -3
  5. package/packages/FormMaking/GenerateFormItemH5.vue +1 -1
  6. package/packages/FormMaking/WidgetConfig.vue +35 -48
  7. package/packages/FormMaking/WidgetTools.vue +538 -0
  8. package/packages/FormMaking/config/index.js +6 -0
  9. package/packages/FormMaking/custom/config.js +21 -24
  10. package/packages/FormMaking/custom/configs/button.vue +24 -25
  11. package/packages/FormMaking/custom/configs/cascader.vue +7 -7
  12. package/packages/FormMaking/custom/configs/checkbox.vue +23 -22
  13. package/packages/FormMaking/custom/configs/color.vue +3 -3
  14. package/packages/FormMaking/custom/configs/date.vue +3 -3
  15. package/packages/FormMaking/custom/configs/input.vue +3 -3
  16. package/packages/FormMaking/custom/configs/number.vue +3 -3
  17. package/packages/FormMaking/custom/configs/radio.vue +23 -19
  18. package/packages/FormMaking/custom/configs/rate.vue +3 -3
  19. package/packages/FormMaking/custom/configs/select.vue +25 -20
  20. package/packages/FormMaking/custom/configs/slider.vue +3 -3
  21. package/packages/FormMaking/custom/configs/switch.vue +3 -3
  22. package/packages/FormMaking/custom/configs/tabs.vue +12 -17
  23. package/packages/FormMaking/custom/configs/textarea.vue +3 -3
  24. package/packages/FormMaking/custom/configs/time.vue +3 -3
  25. package/packages/FormMaking/custom/configs/upload.vue +5 -5
  26. package/packages/FormMaking/custom/items/button.vue +35 -1
  27. package/packages/FormMaking/custom/items/checkbox.vue +1 -1
  28. package/packages/FormMaking/custom/mixins/index.js +12 -12
  29. package/packages/FormMaking/index.vue +91 -468
  30. package/packages/FormMaking/styles/index.scss +0 -21
  31. package/packages/FormMaking/util/request.js +9 -12
@@ -100,95 +100,20 @@
100
100
  <!-- 中间视图区 -->
101
101
  <el-container class="center-container" direction="vertical">
102
102
  <!-- 操作区 -->
103
- <el-header>
104
- <div class="client">
105
- <el-button
106
- v-if="tools.includes('monitor')"
107
- :class="{ active: client === 'monitor' }"
108
- type="text"
109
- size="medium"
110
- icon="el-icon-monitor"
111
- @click="client = 'monitor'"
112
- >
113
- 桌面端
114
- </el-button>
115
- <el-button
116
- v-if="tools.includes('mobile')"
117
- :class="{ active: client === 'mobile' }"
118
- type="text"
119
- size="medium"
120
- icon="el-icon-mobile"
121
- @click="client = 'mobile'"
122
- >
123
- 移动端
124
- </el-button>
125
- </div>
126
- <slot name="action"> </slot>
127
- <el-popover
128
- placement="bottom"
129
- trigger="hover"
130
- style="margin:0 10px;"
131
- >
132
- <el-button
133
- v-if="tools.includes('upload')"
134
- type="text"
135
- size="medium"
136
- icon="el-icon-upload2"
137
- slot="reference"
138
- >导入</el-button
139
- >
140
- <div>
141
- <el-upload
142
- action
143
- accept=".xlsx, .xls"
144
- :auto-upload="false"
145
- :show-file-list="false"
146
- :on-change="onExcelFileChange"
147
- >
148
- <el-button type="text" size="medium">导入EXCEL </el-button>
149
- </el-upload>
150
- <el-button
151
- type="text"
152
- size="medium"
153
- @click="dialog.import.visible = true"
154
- >导入JSON
155
- </el-button>
156
- </div>
157
- </el-popover>
158
-
159
- <el-button
160
- v-if="tools.includes('clearable')"
161
- type="text"
162
- size="medium"
163
- icon="el-icon-delete"
164
- @click="handleClear"
165
- >清空
166
- </el-button>
167
- <el-button
168
- v-if="tools.includes('preview')"
169
- type="text"
170
- size="medium"
171
- icon="el-icon-view"
172
- @click="handlePreview"
173
- >预览
174
- </el-button>
175
- <el-button
176
- v-if="tools.includes('generateJson')"
177
- type="text"
178
- size="medium"
179
- icon="el-icon-tickets"
180
- @click="handleGenerateJson"
181
- >生成JSON</el-button
182
- >
183
- <el-button
184
- v-if="tools.includes('generateCode')"
185
- type="text"
186
- size="medium"
187
- icon="el-icon-document"
188
- @click="handleGenerateCode"
189
- >生成代码</el-button
190
- >
191
- </el-header>
103
+ <WidgetTools
104
+ :baseConfig="baseConfig"
105
+ :permissions="permissions"
106
+ :client.sync="client"
107
+ :basicComponents="basicComponents"
108
+ :layoutComponents="layoutComponents"
109
+ :formData="widgetFormData"
110
+ :formValue="widgetValue"
111
+ :oauthConfig="oauthConfig"
112
+ :slotKeys="Object.keys($slots)"
113
+ @click="handleWidgetToolsChange"
114
+ >
115
+ <slot name="action"></slot>
116
+ </WidgetTools>
192
117
 
193
118
  <!-- 工作区 -->
194
119
  <el-main>
@@ -225,7 +150,6 @@
225
150
  <widget-config
226
151
  v-show="configTab == 'widget'"
227
152
  :data="widgetFormSelect"
228
- :remoteApis="remoteApis"
229
153
  :config="widgetFormData.config"
230
154
  @update="handleWidgetConfigUpdate"
231
155
  >
@@ -237,137 +161,6 @@
237
161
  </el-main>
238
162
  </el-container>
239
163
  </el-aside>
240
-
241
- <!-- 导入JSON -->
242
- <th-dialog
243
- title="导入JSON"
244
- :visible="dialog.import.visible"
245
- :modal-append-to-body="false"
246
- @on-close="dialog.import.visible = false"
247
- @on-affirm="handleUploadJson"
248
- @on-fullscreen="$refs.valueCodeEditor.resize()"
249
- >
250
- <el-alert
251
- type="info"
252
- title="JSON格式如下,直接复制生成的json覆盖此处代码点击确定即可"
253
- ></el-alert>
254
- <th-code-editor
255
- v-model="dialog.import.value"
256
- ref="valueCodeEditor"
257
- ></th-code-editor>
258
- </th-dialog>
259
-
260
- <!-- 预览 -->
261
- <th-dialog
262
- title="预览"
263
- v-model="dialog.preview.visible"
264
- :modal-append-to-body="false"
265
- @on-close="dialog.preview.visible = false"
266
- >
267
- <generate-form
268
- v-if="dialog.preview.visible"
269
- :data="widgetFormData"
270
- :value="widgetValue"
271
- :oauthConfig="oauthConfig"
272
- :remote="remoteFuncs"
273
- :slotKeys="slotKeys"
274
- :client="client"
275
- insite="true"
276
- @on-change="handleDataChange"
277
- ref="generateForm"
278
- >
279
- <template v-for="name in slotKeys" :slot="name">
280
- <slot :name="name" />
281
- </template>
282
- </generate-form>
283
-
284
- <template slot="footer">
285
- <el-button type="primary" @click="handleGetData"
286
- >获取数据</el-button
287
- >
288
- <el-button @click="handleReset">重置</el-button>
289
- </template>
290
- </th-dialog>
291
-
292
- <!-- 获取数据 -->
293
- <th-dialog
294
- title="获取数据"
295
- :visible="dialog.data.visible"
296
- :modal-append-to-body="false"
297
- @on-close="dialog.data.visible = false"
298
- @on-fullscreen="$refs.dataCodeEditor.resize()"
299
- >
300
- <th-code-editor
301
- v-model="dialog.data.value"
302
- ref="dataCodeEditor"
303
- ></th-code-editor>
304
-
305
- <template slot="footer">
306
- <el-button
307
- type="primary"
308
- class="json-btn"
309
- :data-clipboard-text="dialog.data.valueCopy"
310
- >复制数据</el-button
311
- >
312
- </template>
313
- </th-dialog>
314
-
315
- <!-- 生成json -->
316
- <th-dialog
317
- title="生成JSON"
318
- :visible="dialog.config.visible"
319
- :modal-append-to-body="false"
320
- @on-close="dialog.config.visible = false"
321
- @on-fullscreen="$refs.jsonCodeEditor.resize()"
322
- >
323
- <th-code-editor
324
- v-model="dialog.config.value"
325
- ref="jsonCodeEditor"
326
- ></th-code-editor>
327
-
328
- <template slot="footer">
329
- <el-button
330
- type="primary"
331
- class="json-btn"
332
- :data-clipboard-text="dialog.config.valueCopy"
333
- >复制数据</el-button
334
- >
335
- </template>
336
- </th-dialog>
337
-
338
- <!-- 生成代码 -->
339
- <th-dialog
340
- class="codeDialog"
341
- title="生成代码"
342
- :visible="dialog.code.visible"
343
- :showFooter="false"
344
- :modal-append-to-body="false"
345
- @on-close="dialog.code.visible = false"
346
- @on-fullscreen="handleDialogFullscreen"
347
- >
348
- <el-tabs
349
- type="border-card"
350
- style="box-shadow: none;"
351
- v-model="dialog.code.type"
352
- >
353
- <el-tab-pane label="Vue Component" name="vue">
354
- <th-code-editor
355
- v-model="dialog.code.valueVue"
356
- language="html"
357
- readonly
358
- ref="vueCodeEditor"
359
- ></th-code-editor>
360
- </el-tab-pane>
361
- <el-tab-pane label="HTML" name="html">
362
- <th-code-editor
363
- v-model="dialog.code.valueHtml"
364
- language="html"
365
- readonly
366
- ref="htmlCodeEditor"
367
- ></th-code-editor>
368
- </el-tab-pane>
369
- </el-tabs>
370
- </th-dialog>
371
164
  </el-container>
372
165
  </el-main>
373
166
  </el-container>
@@ -376,9 +169,9 @@
376
169
 
377
170
  <script>
378
171
  import Draggable from "vuedraggable";
379
- import Clipboard from "clipboard";
380
172
  import WidgetConfig from "./WidgetConfig";
381
173
  import FormConfig from "./FormConfig";
174
+ import WidgetTools from "./WidgetTools";
382
175
  import WidgetForm from "./WidgetForm";
383
176
  import GenerateForm from "./GenerateForm";
384
177
  import {
@@ -387,9 +180,7 @@ import {
387
180
  layoutComponents,
388
181
  baseConfig
389
182
  } from "./custom/config";
390
- import request from "./util/request";
391
183
  import generateCode from "./util/generateCode.js";
392
- import * as XLSX from "xlsx/xlsx.mjs";
393
184
 
394
185
  export default {
395
186
  name: "thFormMaking",
@@ -397,6 +188,7 @@ export default {
397
188
  Draggable,
398
189
  WidgetConfig,
399
190
  FormConfig,
191
+ WidgetTools,
400
192
  WidgetForm,
401
193
  GenerateForm
402
194
  },
@@ -413,19 +205,17 @@ export default {
413
205
  return {};
414
206
  }
415
207
  },
416
- tools: {
208
+ permissions: {
417
209
  type: Array,
418
- default: () => {
419
- return [
420
- "monitor",
421
- "mobile",
422
- "upload",
423
- "clearable",
424
- "preview",
425
- "generateCode",
426
- "generateJson"
427
- ];
428
- }
210
+ default: () => [
211
+ "monitor",
212
+ "mobile",
213
+ "upload",
214
+ "clearable",
215
+ "preview",
216
+ "generateCode",
217
+ "generateJson"
218
+ ]
429
219
  },
430
220
  basicFields: {
431
221
  type: Array,
@@ -459,9 +249,9 @@ export default {
459
249
  type: Array,
460
250
  default: () => ["grid", "filler", "divider"]
461
251
  },
462
- remoteApis: {
463
- type: Array,
464
- default: () => []
252
+ remoteFuncs: {
253
+ type: Object,
254
+ default: () => {}
465
255
  }
466
256
  },
467
257
  data() {
@@ -474,39 +264,7 @@ export default {
474
264
  widgetFormSelect: {},
475
265
  widgetValue: {},
476
266
  configTab: "widget",
477
- client: "monitor",
478
- dialog: {
479
- import: { visible: false, value: "" },
480
- preview: { visible: false, value: "" },
481
- data: { visible: false, value: "", valueCopy: "" },
482
- config: { visible: false, value: "", valueCopy: "" },
483
- code: { visible: false, valueHtml: "", valueVue: "", type: "vue" }
484
- },
485
- remoteFuncs: {
486
- func_test(resolve) {
487
- setTimeout(() => {
488
- const options = [
489
- { id: "1", name: "1111" },
490
- { id: "2", name: "2222" },
491
- { id: "3", name: "3333" }
492
- ];
493
-
494
- resolve(options);
495
- }, 2000);
496
- },
497
- funcGetToken(resolve) {
498
- request
499
- .get("http://tools-server.making.link/api/uptoken")
500
- .then(res => {
501
- resolve(res.uptoken);
502
- });
503
- },
504
- upload_callback(response, file, fileList) {
505
- console.log("callback", response, file, fileList);
506
- }
507
- },
508
- jsonClipboard: null,
509
- slotKeys: []
267
+ client: "monitor"
510
268
  };
511
269
  },
512
270
  computed: {
@@ -542,6 +300,41 @@ export default {
542
300
  val.config = Object.assign(this.baseConfig, val.config);
543
301
  }
544
302
  this.setJSON(val);
303
+ },
304
+ remoteFuncs(val) {
305
+ if (val) {
306
+ const props = val.props;
307
+ const options = val.options;
308
+
309
+ /**
310
+ * 支持外部接口转自定义事件(待完成)
311
+ */
312
+ // const _eventScript = options.map(item => {
313
+ // return {
314
+ // id: item[props.key],
315
+ // label: item[props.name],
316
+ // value: `
317
+ // const params = ${JSON.stringify(item.params)}
318
+ // const headers = ${JSON.stringify(item.headers || {})}
319
+ // const request = {
320
+ // url:"${item.url}",
321
+ // method:"${item.method}",
322
+ // data:params,
323
+ // headers:headers
324
+ // }
325
+ // this.hendleRemoteData(request)
326
+ // `
327
+ // };
328
+ // });
329
+ // this.widgetFormData.config.eventScript = this.widgetFormData.config.eventScript.concat(
330
+ // _eventScript
331
+ // );
332
+
333
+ const _remoteFuncs = options.map(item => {
334
+ return { ...item, id: item[props.key], label: item[props.name] };
335
+ });
336
+ this.widgetFormData.config.remoteFuncs = _remoteFuncs;
337
+ }
545
338
  }
546
339
  },
547
340
  created() {
@@ -550,6 +343,7 @@ export default {
550
343
  this.baseConfig,
551
344
  this.widgetFormData.config
552
345
  );
346
+
553
347
  if (this.widgetFormData.list && this.widgetFormData.list.length) {
554
348
  this.widgetFormSelect = this.widgetFormData.list[0];
555
349
  } else {
@@ -582,200 +376,11 @@ export default {
582
376
  });
583
377
  }
584
378
  },
585
- // 读取excel file
586
- readExcelFile(file) {
587
- //文件读取
588
- return new Promise(resolve => {
589
- let reader = new FileReader();
590
- reader.readAsBinaryString(file); //以二进制的方式读取
591
- reader.onload = ev => {
592
- resolve(ev.target.result);
593
- };
594
- });
595
- },
596
- // excel 文件上传 改变监听
597
- async onExcelFileChange(ev) {
598
- let file = ev.raw;
599
- if (!file) {
600
- console.log("文件打开失败");
601
- return;
602
- } else {
603
- let data = await this.readExcelFile(file);
604
- //XLSX 文档 https://www.npmjs.com/package/xlsx
605
- let workbook = XLSX.read(data, { type: "binary" }); //解析二进制格式数据
606
- let worksheet = workbook.Sheets[workbook.SheetNames[0]]; //获取第一个Sheet
607
-
608
- // console.log("XLSX.read => \n", workbook);
609
- // console.log("sheet_to_json => \n", XLSX.utils.sheet_to_json(worksheet));
610
- // console.log("sheet_to_csv => \n", XLSX.utils.sheet_to_csv(worksheet));
611
- // console.log("sheet_to_txt => \n", XLSX.utils.sheet_to_txt(worksheet));
612
- const xlsxDom = this.parseDom(XLSX.utils.sheet_to_html(worksheet));
613
- // console.log("sheet_to_html => \n", xlsxDom);
614
- const rowsDom = xlsxDom.getElementsByTagName("tr");
615
- console.log("rowsDom =>", rowsDom);
616
- let rowSpan = 0;
617
- for (let i = 0; i < rowsDom[0].childNodes.length; i++) {
618
- const col = rowsDom[0].childNodes[i];
619
- rowSpan += col.colSpan || 1;
620
- }
621
- console.log("rowSpan =>", rowSpan);
622
- const colSpan = 24 / rowSpan;
623
379
 
624
- let config = {
625
- list: [],
626
- config: this.baseConfig
627
- };
628
-
629
- for (const row of rowsDom) {
630
- const key =
631
- Date.parse(new Date()) + "_" + Math.ceil(Math.random() * 99999);
632
- let grid = this.getComponentsConfig("grid");
633
- grid.options.columns = [];
634
- grid.key = key;
635
- grid.model = "grid_" + key;
636
-
637
- const colsDom = row.childNodes;
638
- console.log("colsDom =>", colsDom);
639
- // continue;
640
- let span = 0;
641
- for (let i = 0; i < colsDom.length; i++) {
642
- if (i % 2 === 0) span = 0;
643
- else continue;
644
-
645
- const colKey =
646
- Date.parse(new Date()) + "_" + Math.ceil(Math.random() * 99999);
647
- const titleDom = colsDom[i];
648
- const valueDom = colsDom[i + 1];
649
- if (!titleDom.innerText && !valueDom.innerText) continue;
650
-
651
- if (valueDom) {
652
- span =
653
- ((titleDom.colSpan || 1) + (valueDom.colSpan || 1)) * colSpan;
654
-
655
- const data = this.getComponentsConfig("input");
656
- let name = titleDom.innerText;
657
- if (name.charAt(0) === "*") {
658
- name = name.slice(1);
659
- data.options.required = true;
660
- data.rules = data.rules || [];
661
- data.rules.push({
662
- required: true,
663
- message: "单行文本必须填写"
664
- });
665
- }
666
- data.name = name;
667
- data.options.defaultValue = valueDom.innerText;
668
- data.key = colKey;
669
- data.model = "input_" + colKey;
670
- grid.options.columns.push({ span: span, list: [data] });
671
- } else {
672
- span = titleDom.colSpan * colSpan;
673
-
674
- const data = this.getComponentsConfig("text");
675
- data.name = titleDom.innerText;
676
- data.options.defaultValue = titleDom.innerText;
677
- data.options.hideLabel = true;
678
- data.key = colKey;
679
- data.model = "text_" + colKey;
680
- grid.options.columns.push({ span: span, list: [data] });
681
- }
682
- }
683
- if (grid.options.columns.length) {
684
- config.list.push(grid);
685
- } else {
686
- const data = this.getComponentsConfig("filler");
687
- data.name = "";
688
- data.key = key;
689
- data.model = "filler_" + key;
690
- config.list.push(data);
691
- }
692
- }
693
- this.setJSON(config);
694
- }
695
- },
696
- getComponentsConfig(type) {
697
- let data = null;
698
- for (const item of this.basicComponents) {
699
- if (type === item.type) {
700
- data = JSON.parse(JSON.stringify(item));
701
- return data;
702
- }
703
- }
704
- for (const item of this.layoutComponents) {
705
- if (type === item.type) {
706
- data = JSON.parse(JSON.stringify(item));
707
- return data;
708
- }
709
- }
710
- return data;
711
- },
712
-
713
- parseDom(arg) {
714
- var objE = document.createElement("div");
715
- objE.innerHTML = arg;
716
- return objE.childNodes[2];
717
- },
718
-
719
- initClipboard() {
720
- if (!this.jsonClipboard) {
721
- this.jsonClipboard = new Clipboard(".json-btn");
722
- this.jsonClipboard.on("success", e => {
723
- this.$message.success("复制成功");
724
- });
725
- }
726
- },
727
380
  handleConfigSelect(value) {
728
381
  this.configTab = value;
729
382
  },
730
- handlePreview() {
731
- this.slotKeys = Object.keys(this.$slots);
732
- this.dialog.preview.visible = true;
733
- },
734
- handleGetData() {
735
- this.$refs.generateForm.getData().then(data => {
736
- this.dialog.data = {
737
- visible: true,
738
- value: JSON.stringify(data, null, 2),
739
- valueCopy: JSON.stringify(data, null, 2)
740
- };
741
- this.$nextTick(() => {
742
- this.initClipboard();
743
- });
744
- });
745
- },
746
- handleReset() {
747
- this.$refs.generateForm.reset();
748
- },
749
- handleGenerateJson() {
750
- this.dialog.config = {
751
- visible: true,
752
- value: JSON.stringify(this.widgetFormData, null, 2),
753
- valueCopy: JSON.stringify(this.widgetFormData, null, 2)
754
- };
755
- this.$nextTick(() => {
756
- this.initClipboard();
757
- });
758
- },
759
- handleGenerateCode() {
760
- this.dialog.code = {
761
- visible: true,
762
- valueHtml: generateCode(JSON.stringify(this.widgetFormData), "html"),
763
- valueVue: generateCode(JSON.stringify(this.widgetFormData), "vue"),
764
- type: "vue"
765
- };
766
- },
767
- handleUploadJson() {
768
- try {
769
- this.setJSON(JSON.parse(this.dialog.import.value));
770
- this.dialog.import.visible = false;
771
- } catch (e) {
772
- this.$message.error(e.message);
773
- }
774
- },
775
- handleDialogFullscreen() {
776
- this.$refs.vueCodeEditor.resize();
777
- this.$refs.htmlCodeEditor.resize();
778
- },
383
+
779
384
  handleClear() {
780
385
  this.widgetFormData = {
781
386
  list: [],
@@ -784,6 +389,30 @@ export default {
784
389
 
785
390
  this.widgetFormSelect = {};
786
391
  },
392
+ handleWidgetToolsChange(val, data) {
393
+ switch (val) {
394
+ case "mobile":
395
+ this.client = val;
396
+ break;
397
+ case "monitor":
398
+ this.client = val;
399
+ break;
400
+ case "import-excel":
401
+ case "import-json":
402
+ case "import-template":
403
+ this.setJSON(data);
404
+ break;
405
+ case "clear":
406
+ this.handleClear();
407
+ break;
408
+
409
+ default:
410
+ break;
411
+ }
412
+ },
413
+ handleWidgetConfigUpdate(val) {
414
+ this.widgetFormSelect = Object.assign(this.widgetFormSelect, val);
415
+ },
787
416
  clear() {
788
417
  this.handleClear();
789
418
  },
@@ -799,12 +428,6 @@ export default {
799
428
  if (json.list.length > 0) {
800
429
  this.widgetFormSelect = json.list[0];
801
430
  }
802
- },
803
- handleDataChange(field, value, data) {
804
- // console.log(field, value, data);
805
- },
806
- handleWidgetConfigUpdate(val) {
807
- this.widgetFormSelect = Object.assign(this.widgetFormSelect, val);
808
431
  }
809
432
  }
810
433
  };
@@ -100,32 +100,11 @@ $primary-background-color: #ecf5ff;
100
100
  border-left: 1px solid #e0e0e0;
101
101
  border-right: 1px solid #e0e0e0;
102
102
 
103
- .el-header {
104
- display: flex;
105
- align-items: center;
106
- height: 45px !important;
107
- line-height: 45px !important;
108
- // font-size: 18px;
109
- border-bottom: solid 2px #e4e7ed;
110
- text-align: right;
111
- }
112
-
113
103
  .el-main {
114
104
  padding: 0;
115
105
  position: relative;
116
106
  background: #fafafa;
117
107
  }
118
-
119
- .client {
120
- flex: 1;
121
- text-align: left;
122
- .el-button {
123
- color: #333;
124
- }
125
- .active {
126
- color: #409eff;
127
- }
128
- }
129
108
  }
130
109
 
131
110
  // 左侧字段区