tianheng-ui 0.1.39 → 0.1.41

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 (28) hide show
  1. package/lib/theme-chalk/styles/feature.scss +2 -4
  2. package/lib/theme-chalk/styles/variable.scss +2 -0
  3. package/lib/tianheng-ui.js +13 -13
  4. package/package.json +1 -1
  5. package/packages/Dialog/index.vue +1 -4
  6. package/packages/FormMaking/GenerateForm.vue +1 -1
  7. package/packages/FormMaking/GenerateFormItem.vue +4 -5
  8. package/packages/FormMaking/GenerateFormItemH5.vue +2 -2
  9. package/packages/FormMaking/WidgetConfig.vue +83 -81
  10. package/packages/FormMaking/WidgetForm.vue +1 -0
  11. package/packages/FormMaking/WidgetFormItem.vue +8 -16
  12. package/packages/FormMaking/WidgetTools.vue +2 -3
  13. package/packages/FormMaking/custom/config.js +34 -5
  14. package/packages/FormMaking/custom/index.js +1 -1
  15. package/packages/FormMaking/custom/items/list_dev.vue +122 -0
  16. package/packages/FormMaking/custom/items/list_pro.vue +18 -0
  17. package/packages/FormMaking/custom/items/tableH5_pro.vue +4 -5
  18. package/packages/FormMaking/custom/items/upload.vue +1 -1
  19. package/packages/FormMaking/index.vue +6 -2
  20. package/packages/FormMaking/styles/index.scss +18 -18
  21. package/packages/TableMaking/WidgetTools.vue +3 -3
  22. package/packages/TableMaking/custom/items/search/index-h5.vue +13 -2
  23. package/packages/TableMaking/custom/items/search/index-pc.vue +12 -1
  24. package/packages/TableMaking/custom/items/table/index-pc.vue +23 -7
  25. package/packages/TableMaking/generateTable.vue +3 -3
  26. package/packages/TableMaking/widgetConfig.vue +181 -151
  27. package/packages/TableMaking/widgetTable.vue +20 -4
  28. package/packages/FormMaking/FormConfig.vue +0 -190
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tianheng-ui",
3
3
  "description": "A Vue.js project",
4
- "version": "0.1.39",
4
+ "version": "0.1.41",
5
5
  "author": "shu lang <403732931@qq.com>",
6
6
  "license": "MIT",
7
7
  "private": false,
@@ -2,7 +2,6 @@
2
2
  <el-dialog
3
3
  class="th-dialog"
4
4
  :class="[customClass]"
5
- :style="{'z-index':zIndex}"
6
5
  :visible.sync="visible"
7
6
  :width="width"
8
7
  :top="top"
@@ -88,9 +87,7 @@ export default {
88
87
  showFullscreen: { type: Boolean, default: true },
89
88
  fullscreenIcon: { type: String, default: "el-icon-full-screen" },
90
89
 
91
- showFooter: { type: Boolean, default: true },
92
-
93
- zIndex: Number
90
+ showFooter: { type: Boolean, default: true }
94
91
  },
95
92
  data() {
96
93
  return {
@@ -230,7 +230,7 @@ export default {
230
230
  }
231
231
 
232
232
  this.axios({
233
- url: `/api/lc/api/${remoteFunc.url}`,
233
+ url: remoteFunc.url,
234
234
  method: remoteFunc.method,
235
235
  headers: remoteFunc.headers,
236
236
  data: remoteFunc.params
@@ -85,17 +85,16 @@ export default {
85
85
  grid: "grid_pro",
86
86
  table: "table_pro",
87
87
  tableH5: "tableH5_pro",
88
+ list: "list_pro",
88
89
  tabs: "tabs_pro",
89
90
  blank: "blank_pro"
90
91
  };
91
92
  const keys = Object.keys(this.compsData);
92
93
  for (const key of keys) {
94
+ const element = this.compsData[key];
93
95
  if (proComponentsPath[key])
94
- this.compsData[
95
- key
96
- ].content = require(`./custom/items/${proComponentsPath[key]}`).default;
97
- else
98
- this.compsData[key].content = require(`./custom/items/${key}`).default;
96
+ element.content = require(`./custom/items/${proComponentsPath[key]}`).default;
97
+ else element.content = require(`./custom/items/${key}`).default;
99
98
  }
100
99
  },
101
100
  mounted() {
@@ -507,11 +507,11 @@
507
507
  <div
508
508
  class="tableH5-item"
509
509
  v-for="(column, columnIndex) in dataModel"
510
- :key="`table_h5_${columnIndex}`"
510
+ :key="`tableH5_${columnIndex}`"
511
511
  >
512
512
  <div
513
513
  v-for="(element, elementIndex) in widget.list"
514
- :key="`table_h5_${columnIndex}_${element.key}`"
514
+ :key="`tableH5_${columnIndex}_${element.key}`"
515
515
  >
516
516
  <genetate-form-item
517
517
  style="flex:1;"
@@ -3,10 +3,10 @@
3
3
  <div class="tabs th-sticky_top">
4
4
  <div
5
5
  v-for="(item, index) in tabsMenus"
6
- :key="index"
7
6
  class="tabs-item"
8
7
  :class="{ 'tabs-item__active': activeTab.value === item.value }"
9
- @click="handleTabsChange(item)"
8
+ :key="index"
9
+ @click="activeTab = item"
10
10
  >
11
11
  {{ item.title }}
12
12
  </div>
@@ -14,6 +14,7 @@
14
14
 
15
15
  <div v-if="activeTab.value === 'field'">
16
16
  <el-form
17
+ v-if="data.model"
17
18
  :model="data"
18
19
  label-position="left"
19
20
  label-width="80px"
@@ -132,6 +133,7 @@
132
133
  </el-collapse-item>
133
134
  </el-collapse>
134
135
  </el-form>
136
+ <th-empty v-else description="请从左侧拖拽来添加字段"></th-empty>
135
137
  </div>
136
138
  <div v-if="activeTab.value === 'form'">
137
139
  <el-form
@@ -264,17 +266,32 @@
264
266
  </el-collapse>
265
267
  </el-form>
266
268
  </div>
267
- <div v-if="activeTab.value === 'css'"></div>
269
+ <div v-if="activeTab.value === 'css'">
270
+ <el-form
271
+ :model="config"
272
+ label-position="left"
273
+ label-width="80px"
274
+ size="small"
275
+ :rules="formRules"
276
+ ref="formRef"
277
+ >
278
+ <el-collapse v-model="collapseValue">
279
+ <el-collapse-item title="form 样式" name="group-style_form">
280
+ </el-collapse-item>
281
+ </el-collapse>
282
+ </el-form>
283
+ <!-- <th-empty description="开发中,敬请期待..."></th-empty> -->
284
+ </div>
268
285
 
269
286
  <th-dialog
287
+ v-model="dialog.show"
270
288
  title="动作设置"
271
- v-model="eventsDialog.visible"
272
289
  :modal-append-to-body="false"
273
290
  @on-fullscreen="$refs.codeEditor && $refs.codeEditor.resize()"
274
291
  >
275
- <div class="eventsSetting">
276
- <div class="list">
277
- <div class="list-header">
292
+ <div class="eventsSetting th-flex_box th-is_border">
293
+ <div class="list th-flex_aside">
294
+ <div class="events-header">
278
295
  <div>动作库</div>
279
296
  <el-button
280
297
  type="text"
@@ -285,10 +302,14 @@
285
302
  >
286
303
  </div>
287
304
  <div
288
- class="list-item"
289
- v-for="(item, index) in eventsDialog.eventScript"
305
+ v-for="(item, index) in dialog.data"
306
+ class="list-item th-is_hover"
307
+ :class="{
308
+ 'th-is_active':
309
+ dialog.active && dialog.active.label === item.label
310
+ }"
290
311
  :key="item.key"
291
- @click="eventsDialog.active = item"
312
+ @click="dialog.active = item"
292
313
  >
293
314
  <div class="list-item-title">Function</div>
294
315
  <div class="list-item-value">{{ item.label }}</div>
@@ -302,16 +323,16 @@
302
323
  </el-popconfirm>
303
324
  </div>
304
325
  </div>
305
- <div class="detail" v-if="eventsDialog.active">
326
+ <div class="detail th-fiex_content" v-if="dialog.active">
306
327
  <div>
307
328
  <span>Function Name</span>
308
329
  <el-input
309
- v-model="eventsDialog.active.label"
330
+ v-model="dialog.active.label"
310
331
  placeholder="请输入动作名称"
311
332
  size="small"
312
333
  :disabled="
313
- eventsDialog.active.label === 'mounted' ||
314
- eventsDialog.active.label === 'refresh'
334
+ dialog.active.label === 'mounted' ||
335
+ dialog.active.label === 'refresh'
315
336
  "
316
337
  ></el-input>
317
338
  </div>
@@ -319,8 +340,8 @@
319
340
  <div>
320
341
  function(
321
342
  {{
322
- eventsDialog.active.label !== "mounted" &&
323
- eventsDialog.active.label !== "refresh"
343
+ dialog.active.label !== "mounted" &&
344
+ dialog.active.label !== "refresh"
324
345
  ? "item,value"
325
346
  : ""
326
347
  }}
@@ -351,7 +372,7 @@
351
372
  </div>
352
373
  <th-code-editor
353
374
  style="height:calc(100% - 48px)"
354
- v-model="eventsDialog.active.value"
375
+ v-model="dialog.active.value"
355
376
  :completions="aceCompletions"
356
377
  ref="codeEditor"
357
378
  ></th-code-editor>
@@ -360,7 +381,7 @@
360
381
  </div>
361
382
  </div>
362
383
  <span slot="footer" class="dialog-footer">
363
- <el-button size="small" @click="eventsDialog.visible = false"
384
+ <el-button size="small" @click="dialog.show = false"
364
385
  >取 消</el-button
365
386
  >
366
387
  <el-button type="primary" size="small" @click="handleEventDialogAffirm"
@@ -400,17 +421,20 @@ export default {
400
421
  { title: "样式设置", value: "css" }
401
422
  ],
402
423
  activeTab: {},
403
- validator: {
404
- type: null,
405
- required: null,
406
- pattern: null,
407
- range: null,
408
- length: null
409
- },
410
- eventsDialog: {
411
- visible: false,
412
- eventScript: [],
413
- active: null
424
+ collapseValue: [
425
+ "group-general",
426
+ "group-element",
427
+ "group-action",
428
+ "group-form",
429
+ "group-resultData",
430
+ "group-label",
431
+ "group-attributes",
432
+ "group-style_form"
433
+ ],
434
+ dialog: {
435
+ show: false,
436
+ data: [],
437
+ action: null
414
438
  },
415
439
  aceCompletions: [
416
440
  {
@@ -444,15 +468,6 @@ export default {
444
468
  score: 1
445
469
  }
446
470
  ],
447
- collapseValue: [
448
- "group-general",
449
- "group-element",
450
- "group-action",
451
- "group-form",
452
- "group-resultData",
453
- "group-label",
454
- "group-attributes"
455
- ],
456
471
  formRules: {
457
472
  model: [
458
473
  { required: true, message: "请填选组件字段", trigger: "change" }
@@ -474,17 +489,10 @@ export default {
474
489
  }
475
490
  },
476
491
  methods: {
477
- handleTabsChange(item) {
478
- if (!this.data.model)
479
- return this.$message.warning("请从左侧拖拽来添加组件");
480
-
481
- this.activeTab = item;
482
- },
483
-
484
492
  handleEventDialogShow() {
485
- this.eventsDialog = {
486
- visible: true,
487
- eventScript: deepClone(this.config.eventScript),
493
+ this.dialog = {
494
+ show: true,
495
+ data: deepClone(this.config.eventScript),
488
496
  active: null
489
497
  };
490
498
  },
@@ -495,34 +503,34 @@ export default {
495
503
  label: key,
496
504
  value: ""
497
505
  };
498
- this.eventsDialog.eventScript.push(dic);
499
- this.eventsDialog.active = dic;
506
+ this.dialog.data.push(dic);
507
+ this.dialog.active = dic;
500
508
  },
501
509
  handleEventDialogAffirm() {
502
- this.config.eventScript = this.eventsDialog.eventScript;
503
- this.eventsDialog = {
504
- visible: false,
505
- eventScript: [],
510
+ this.config.eventScript = this.dialog.data;
511
+ this.dialog = {
512
+ show: false,
513
+ data: [],
506
514
  active: null
507
515
  };
508
516
  },
509
517
  handleEventDialogDelete(item, index) {
510
518
  if (
511
- this.eventsDialog.active &&
512
- item.key === this.eventsDialog.active.key
519
+ this.dialog.active &&
520
+ item.key === this.dialog.active.key
513
521
  ) {
514
- this.eventsDialog.active = null;
522
+ this.dialog.active = null;
515
523
  }
516
- this.eventsDialog.eventScript.splice(index, 1);
524
+ this.dialog.data.splice(index, 1);
517
525
  },
518
526
  handleEventsCollapseClick(eventKey) {
519
527
  const eventScript = deepClone(this.config.eventScript);
520
528
  for (let i = 0; i < eventScript.length; i++) {
521
529
  const event = eventScript[i];
522
- if (event.key === eventKey) {
523
- this.eventsDialog = {
524
- visible: true,
525
- eventScript: eventScript,
530
+ if (event.id === eventKey) {
531
+ this.dialog = {
532
+ show: true,
533
+ data: eventScript,
526
534
  active: event
527
535
  };
528
536
  break;
@@ -577,6 +585,7 @@ export default {
577
585
  display: flex;
578
586
  align-items: center;
579
587
  height: 45px;
588
+ z-index: 10;
580
589
 
581
590
  .tabs-item {
582
591
  flex: 1;
@@ -599,8 +608,18 @@ export default {
599
608
 
600
609
  .eventsSetting {
601
610
  height: 100%;
602
- display: flex;
603
- border: 1px solid #eee;
611
+
612
+ .events-header {
613
+ position: sticky;
614
+ top: 0;
615
+ display: flex;
616
+ align-items: center;
617
+ justify-content: space-between;
618
+ padding: 5px;
619
+ line-height: 30px;
620
+ border-bottom: 1px solid #eee;
621
+ background: #f2f6fc;
622
+ }
604
623
 
605
624
  .list {
606
625
  width: 270px;
@@ -608,18 +627,6 @@ export default {
608
627
  overflow-y: overlay;
609
628
  border-right: 1px solid #eee;
610
629
 
611
- .list-header {
612
- position: sticky;
613
- top: 0;
614
- display: flex;
615
- align-items: center;
616
- justify-content: space-between;
617
- padding: 5px;
618
- line-height: 30px;
619
- border-bottom: 1px solid #eee;
620
- background: #f2f6fc;
621
- }
622
-
623
630
  .list-item {
624
631
  display: flex;
625
632
  // align-items: center;
@@ -640,14 +647,9 @@ export default {
640
647
  cursor: pointer;
641
648
  }
642
649
  }
643
-
644
- .list-item:hover {
645
- background-color: #f2f6fc;
646
- }
647
650
  }
648
651
 
649
652
  .detail {
650
- flex: 1;
651
653
  padding: 10px;
652
654
 
653
655
  > div:nth-child(1) {
@@ -121,6 +121,7 @@ export default {
121
121
  position: relative;
122
122
  width: 100%;
123
123
  height: calc(100% - 45px);
124
+ overflow-y: scroll;
124
125
 
125
126
  .form-empty {
126
127
  position: absolute;
@@ -4,9 +4,7 @@
4
4
  :class="{
5
5
  active: selectWidget.model == widget.model,
6
6
  isRequired: widget.options.required,
7
- isLayout: ['grid', 'tabs', 'table', 'tableH5', 'alliance'].includes(
8
- widget.type
9
- ),
7
+ isLayout: layoutElements.includes(widget.type),
10
8
  [`widget-form-list-${widget.type}`]: true,
11
9
  [widget.model]: true
12
10
  }"
@@ -28,13 +26,7 @@
28
26
  v-if="selectWidget.model == widget.model"
29
27
  class="widget-actions"
30
28
  :class="{
31
- 'widget-actions-col': [
32
- 'grid',
33
- 'tabs',
34
- 'table',
35
- 'tableH5',
36
- 'alliance'
37
- ].includes(widget.type)
29
+ 'widget-actions-col': layoutElements.includes(widget.type)
38
30
  }"
39
31
  >
40
32
  <div class="actions">
@@ -61,7 +53,8 @@ export default {
61
53
  data() {
62
54
  return {
63
55
  compsData: deepClone(compsData),
64
- selectWidget: this.select
56
+ selectWidget: this.select,
57
+ layoutElements: ["grid", "tabs", "table", "tableH5", "list", "alliance"]
65
58
  };
66
59
  },
67
60
  watch: {
@@ -89,17 +82,16 @@ export default {
89
82
  grid: "grid_dev",
90
83
  table: "table_dev",
91
84
  tableH5: "tableH5_dev",
85
+ list: "list_dev",
92
86
  tabs: "tabs_dev",
93
87
  blank: "blank_dev"
94
88
  };
95
89
  const keys = Object.keys(this.compsData);
96
90
  for (const key of keys) {
91
+ const element = this.compsData[key];
97
92
  if (devComponentsPath[key])
98
- this.compsData[
99
- key
100
- ].content = require(`./custom/items/${devComponentsPath[key]}`).default;
101
- else
102
- this.compsData[key].content = require(`./custom/items/${key}`).default;
93
+ element.content = require(`./custom/items/${devComponentsPath[key]}`).default;
94
+ else element.content = require(`./custom/items/${key}`).default;
103
95
  }
104
96
  },
105
97
  mounted() {},
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="widgetTools th-sticky_top">
2
+ <div class="widgetTools">
3
3
  <div class="left">
4
4
  <slot> </slot>
5
5
  </div>
@@ -215,7 +215,6 @@
215
215
  title="获取数据"
216
216
  :modal-append-to-body="false"
217
217
  :showFooter="false"
218
- :z-index="99999"
219
218
  @on-close="dialogResultData.show = false"
220
219
  @on-fullscreen="$refs.dataCodeEditor.resize()"
221
220
  >
@@ -506,7 +505,7 @@ export default {
506
505
  width: 100%;
507
506
  height: 45px;
508
507
  padding: 0 15px;
509
- z-index: 999;
508
+ border-bottom: solid 1px #e4e7ed;
510
509
 
511
510
  .left {
512
511
  }
@@ -489,7 +489,7 @@ export const basicComponents = [
489
489
  {
490
490
  name: "文件",
491
491
  type: "upload",
492
- icon: "icon-tupian",
492
+ icon: "th-icon-upload",
493
493
  options: {
494
494
  width: "",
495
495
  labelWidth: 100,
@@ -583,7 +583,7 @@ export const advanceComponents = [
583
583
  {
584
584
  name: "子表单",
585
585
  type: "table",
586
- icon: "icon-table",
586
+ icon: "th-icon-insertrowabove",
587
587
  options: {
588
588
  height: "",
589
589
  defaultValue: "",
@@ -615,7 +615,36 @@ export const advanceComponents = [
615
615
  {
616
616
  name: "子表单H5",
617
617
  type: "tableH5",
618
- icon: "icon-table",
618
+ icon: "th-icon-insertrowleft",
619
+ options: {
620
+ defaultValue: "",
621
+ columns: [],
622
+ customClass: "",
623
+ labelWidth: 100,
624
+ isLabelWidth: false,
625
+ dataBind: true,
626
+ validatorCheck: false,
627
+ validator: "",
628
+ paging: false,
629
+ pageSize: 5,
630
+ tableColumn: false,
631
+ hidden: false,
632
+ hideLabel: false,
633
+ disabled: false,
634
+ required: false,
635
+ isAdd: true,
636
+ addButtonText: "新增",
637
+ isDelete: true,
638
+ deleteButtonText: "删除",
639
+ deleteIndex: 0 // 可删除的最小索引
640
+ },
641
+ events: {},
642
+ rules: []
643
+ },
644
+ {
645
+ name: "子列表",
646
+ type: "list",
647
+ icon: "th-icon-orderedlist",
619
648
  options: {
620
649
  defaultValue: "",
621
650
  columns: [],
@@ -677,7 +706,7 @@ export const advanceComponents = [
677
706
  {
678
707
  name: "自定义区域",
679
708
  type: "blank",
680
- icon: "icon-zidingyishuju",
709
+ icon: "th-icon-code",
681
710
  options: {
682
711
  defaultType: "String",
683
712
  required: false
@@ -691,7 +720,7 @@ export const layoutComponents = [
691
720
  {
692
721
  name: "栅格布局",
693
722
  type: "grid",
694
- icon: "icon-grid-",
723
+ icon: "th-icon-layout",
695
724
  options: {
696
725
  gutter: 0,
697
726
  justify: "start",
@@ -20,7 +20,7 @@ const basicComponents = [
20
20
  "editor",
21
21
  "cascader"
22
22
  ];
23
- const advanceComponents = ["table", "tableH5", "tabs", "blank"];
23
+ const advanceComponents = ["table", "tableH5", "list", "tabs", "blank"];
24
24
  const layoutComponents = ["grid", "alliance", "filler", "divider"];
25
25
 
26
26
  module.exports = {
@@ -0,0 +1,122 @@
1
+ <template>
2
+ <div class="list">
3
+ <draggable
4
+ v-model="widget.options.columns"
5
+ :no-transition-on-drag="true"
6
+ v-bind="{
7
+ group: 'people',
8
+ ghostClass: 'ghost',
9
+ animation: 200,
10
+ handle: '.drag-widget'
11
+ }"
12
+ @add="handleWidgetAdd($event)"
13
+ >
14
+ <transition-group name="fade" tag="div" class="list">
15
+ <div
16
+ v-for="(element, elementIndex) in widget.options.columns"
17
+ class="list-item"
18
+ :key="element.key"
19
+ @click.stop="selectWidget = element"
20
+ >
21
+ <widget-form-item
22
+ :widget="element"
23
+ :widgetArray="widget.options.columns"
24
+ :widgetIndex="elementIndex"
25
+ :select.sync="selectWidget"
26
+ :config="config"
27
+ >
28
+ </widget-form-item>
29
+ </div>
30
+ </transition-group>
31
+ </draggable>
32
+ <div v-if="widget.options.isDelete" class="tools">
33
+ <el-button type="danger">{{ widget.options.deleteButtonText }}</el-button>
34
+ </div>
35
+ <div v-if="widget.options.isAdd" class="footer">
36
+ <el-button type="text" :disabled="widget.options.disabled">{{
37
+ widget.options.addButtonText
38
+ }}</el-button>
39
+ </div>
40
+ </div>
41
+ </template>
42
+
43
+ <script>
44
+ import { itemsComponent } from "../mixins/index";
45
+ import Draggable from "vuedraggable";
46
+ import WidgetFormItem from "../../WidgetFormItem.vue";
47
+ export default {
48
+ components: { Draggable, WidgetFormItem },
49
+ mixins: [itemsComponent],
50
+ data() {
51
+ return {
52
+ selectWidget: {}
53
+ };
54
+ },
55
+ watch: {
56
+ select(val) {
57
+ this.selectWidget = val;
58
+ },
59
+ selectWidget: {
60
+ handler(val) {
61
+ this.$emit("update:select", val);
62
+ },
63
+ deep: true
64
+ }
65
+ },
66
+ methods: {
67
+ handleWidgetAdd($event) {
68
+ const newIndex = $event.newIndex;
69
+ const oldIndex = $event.oldIndex;
70
+ const newComponent = JSON.parse(
71
+ JSON.stringify(this.widget.options.columns[newIndex])
72
+ );
73
+ const item = $event.item;
74
+ // 防止布局元素的嵌套拖拽
75
+ if (item.className.indexOf("no-put") >= 0) {
76
+ // 如果是列表中拖拽的元素需要还原到原来位置
77
+ item.tagName === "DIV" &&
78
+ this.widgetArray.splice(oldIndex, 0, newComponent);
79
+
80
+ this.widget.options.columns.splice(newIndex, 1);
81
+ return false;
82
+ }
83
+
84
+ if (!newComponent.key) {
85
+ const key =
86
+ Date.parse(new Date()) + "_" + Math.ceil(Math.random() * 99999);
87
+ newComponent.key = key;
88
+ newComponent.model = `${newComponent.type}_${key}`;
89
+ }
90
+ this.$set(this.widget.options.columns, newIndex, newComponent);
91
+ this.selectWidget = newComponent;
92
+ }
93
+ }
94
+ };
95
+ </script>
96
+
97
+ <style lang="scss" scoped>
98
+ .list {
99
+ background: #fff;
100
+
101
+ .list {
102
+ min-height: 50px;
103
+ border: 1px dashed #ccc;
104
+ .list-item {
105
+ width: 100%;
106
+ }
107
+ .list-item:nth-child(1) {
108
+ display: flex;
109
+ > div:first-child {
110
+ flex: 1;
111
+ }
112
+ }
113
+ }
114
+
115
+ .tools {
116
+ text-align: right;
117
+ }
118
+ .footer {
119
+ text-align: center;
120
+ }
121
+ }
122
+ </style>