cloud-web-corejs 1.0.280 → 1.1.0-dev.10

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 (193) hide show
  1. package/package.json +6 -2
  2. package/src/components/VabUpload/image-viewer.vue +442 -442
  3. package/src/components/VabUpload/index.vue +45 -3
  4. package/src/components/VabUpload/mixins.js +174 -34
  5. package/src/components/VabUpload/previewGroup.js +128 -0
  6. package/src/components/VabUpload/view.vue +248 -209
  7. package/src/components/baseTabs/mixins.js +181 -181
  8. package/src/components/bizTab/BizBillActions.vue +129 -0
  9. package/src/components/bizTab/BizTabListPage.vue +391 -0
  10. package/src/components/bizTab/README.md +378 -0
  11. package/src/components/bizTab/billTableUtil.js +48 -0
  12. package/src/components/bizTab/billValidators.js +136 -0
  13. package/src/components/bizTab/bizBillDetailMixin.js +705 -0
  14. package/src/components/bizTab/index.js +24 -0
  15. package/src/components/excelExport/exportFieldDialog.vue +23 -12
  16. package/src/components/excelExport/exportItemConfigUtil.js +30 -0
  17. package/src/components/excelExport/mixins.js +3 -3
  18. package/src/components/excelImport/index.vue +156 -156
  19. package/src/components/jsonImport/index.vue +1 -1
  20. package/src/components/langImport/index.vue +1 -1
  21. package/src/components/mobile/statusTag/mixins.js +1 -61
  22. package/src/components/mobile/wf/addTaskUserdialog.vue +23 -3
  23. package/src/components/mobile/wf/content.vue +1705 -1556
  24. package/src/components/mobile/wf/deleteTaskUserDialog.vue +22 -3
  25. package/src/components/mobile/wf/mixins/wfModifyDialogMixin.js +8 -6
  26. package/src/components/mobile/wf/selectUserDialog.vue +122 -0
  27. package/src/components/mobile/wf/setCandidateDialog.vue +25 -4
  28. package/src/components/mobile/wf/urgingDialog.vue +26 -3
  29. package/src/components/mobile/wf/wfModifyDialog.vue +4 -0
  30. package/src/components/obsUpload/index.vue +1 -1
  31. package/src/components/table/config.js +78 -78
  32. package/src/components/table/index.js +1276 -1276
  33. package/src/components/table/plugins/cell-area/index.js +1055 -0
  34. package/src/components/table/plugins/cell-area/index.scss +77 -0
  35. package/src/components/table/plugins/cell-area/util.js +224 -0
  36. package/src/components/table/tableForm.vue +330 -330
  37. package/src/components/table/tableFormMixin.js +318 -318
  38. package/src/components/table/vxeFilter/index.js +163 -163
  39. package/src/components/table/vxeFilter/mixin.js +316 -316
  40. package/src/components/wf/content.vue +1188 -1188
  41. package/src/components/wf/wf.js +40 -20
  42. package/src/components/wf/wfActionDropdown.vue +1 -1
  43. package/src/components/wf/wfActionItems.js +1 -1
  44. package/src/components/xform/docs/2026-08 xform H5 P0 /345/256/236/347/216/260/350/247/204/346/240/274.md" +528 -0
  45. package/src/components/xform/docs/2026-08 xform H5 P1 /345/256/236/347/216/260/350/247/204/346/240/274.md" +412 -0
  46. package/src/components/xform/docs/2026-08 xform H5 P2 /345/256/236/347/216/260/350/247/204/346/240/274.md" +287 -0
  47. package/src/components/xform/docs/2026-08 xform /347/247/273/345/212/250/347/253/257/345/270/203/345/261/200/345/257/271/351/275/220 bill_setting /346/226/271/346/241/210.md" +400 -0
  48. package/src/components/xform/form-designer/designer.js +51 -52
  49. package/src/components/xform/form-designer/form-widget/container-widget/data-table-widget.vue +269 -269
  50. package/src/components/xform/form-designer/form-widget/container-widget/detail-h5-widget.vue +18 -2
  51. package/src/components/xform/form-designer/form-widget/container-widget/detail-temp-widget.vue +132 -0
  52. package/src/components/xform/form-designer/form-widget/container-widget/detail-widget.vue +250 -250
  53. package/src/components/xform/form-designer/form-widget/container-widget/h5-card-pane-widget.vue +23 -2
  54. package/src/components/xform/form-designer/form-widget/container-widget/h5-card-widget.vue +30 -1
  55. package/src/components/xform/form-designer/form-widget/dialog/fileReferenceDialog.vue +319 -320
  56. package/src/components/xform/form-designer/form-widget/dialog/formDialog.vue +365 -365
  57. package/src/components/xform/form-designer/form-widget/dialog/importDialog.vue +185 -185
  58. package/src/components/xform/form-designer/form-widget/dialog/searchFormDialog.vue +554 -555
  59. package/src/components/xform/form-designer/form-widget/dialog/vabSearchDialog.vue +409 -409
  60. package/src/components/xform/form-designer/form-widget/field-widget/a-link-widget.vue +150 -132
  61. package/src/components/xform/form-designer/form-widget/field-widget/date-range-widget.vue +114 -114
  62. package/src/components/xform/form-designer/form-widget/field-widget/date-widget.vue +154 -154
  63. package/src/components/xform/form-designer/form-widget/field-widget/form-item-wrapper.vue +47 -1
  64. package/src/components/xform/form-designer/form-widget/field-widget/mixins/date-limit-mixin.js +178 -178
  65. package/src/components/xform/form-designer/form-widget/field-widget/mixins/time-limit-mixin.js +77 -77
  66. package/src/components/xform/form-designer/form-widget/field-widget/select-export-item-button-widget.vue +6 -0
  67. package/src/components/xform/form-designer/form-widget/field-widget/select-widget.vue +139 -139
  68. package/src/components/xform/form-designer/form-widget/field-widget/singleUpload-widget.vue +1 -1
  69. package/src/components/xform/form-designer/form-widget/field-widget/time-range-widget.vue +106 -106
  70. package/src/components/xform/form-designer/form-widget/field-widget/time-widget.vue +134 -134
  71. package/src/components/xform/form-designer/form-widget/field-widget/vabUpload-widget.vue +3 -2
  72. package/src/components/xform/form-designer/indexMixin.js +35 -1
  73. package/src/components/xform/form-designer/setting-panel/form-setting.vue +39 -39
  74. package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/data-table-editor.vue +10 -10
  75. package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/exportItemColumns-dialog.vue +438 -432
  76. package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/table-column-dialog.vue +2103 -2103
  77. package/src/components/xform/form-designer/setting-panel/property-editor/container-detail/detail-temp-edito.vue +90 -0
  78. package/src/components/xform/form-designer/setting-panel/property-editor/container-grid/gutter-editor.vue +82 -82
  79. package/src/components/xform/form-designer/setting-panel/property-editor/container-list-h5/list-h5-editor.vue +833 -846
  80. package/src/components/xform/form-designer/setting-panel/property-editor/container-table/table-dynamicField-editor.vue +8 -8
  81. package/src/components/xform/form-designer/setting-panel/property-editor/dropdownFlag-editor.vue +137 -137
  82. package/src/components/xform/form-designer/setting-panel/property-editor/field-button/search-dialog-event-editor.vue +237 -237
  83. package/src/components/xform/form-designer/setting-panel/property-editor/field-date/date-defaultValue-editor.vue +43 -43
  84. package/src/components/xform/form-designer/setting-panel/property-editor/field-date-range/date-range-defaultValue-editor.vue +43 -43
  85. package/src/components/xform/form-designer/setting-panel/property-editor/field-import-button/import2-button-editor.vue +96 -96
  86. package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/select-export-item-button-editor.vue +51 -0
  87. package/src/components/xform/form-designer/setting-panel/property-editor/field-time/time-defaultValue-editor.vue +42 -42
  88. package/src/components/xform/form-designer/setting-panel/property-editor/field-time-range/time-range-defaultValue-editor.vue +43 -43
  89. package/src/components/xform/form-designer/setting-panel/property-editor/formScriptEnabled-editor.vue +158 -158
  90. package/src/components/xform/form-designer/setting-panel/property-editor/h5Span-editor.vue +51 -0
  91. package/src/components/xform/form-designer/setting-panel/property-editor/itemStyle-editor.vue +39 -0
  92. package/src/components/xform/form-designer/setting-panel/property-editor/name-editor.vue +188 -188
  93. package/src/components/xform/form-designer/setting-panel/property-editor/styleTempClass-editor.vue +51 -0
  94. package/src/components/xform/form-designer/setting-panel/property-editor/textFlag-editor.vue +347 -347
  95. package/src/components/xform/form-designer/setting-panel/propertyRegister.js +12 -0
  96. package/src/components/xform/form-designer/toolbar-panel/index.vue +884 -874
  97. package/src/components/xform/form-designer/toolbar-panel/indexMixin.js +14 -0
  98. package/src/components/xform/form-designer/widget-panel/index.vue +11 -7
  99. package/src/components/xform/form-designer/widget-panel/indexMixin.js +30 -6
  100. package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +112 -4
  101. package/src/components/xform/form-render/container-item/data-table-mixin.js +151 -93
  102. package/src/components/xform/form-render/container-item/detail-h5-item.vue +204 -34
  103. package/src/components/xform/form-render/container-item/detail-temp-item.vue +110 -0
  104. package/src/components/xform/form-render/container-item/h5-card-pane-item.vue +160 -140
  105. package/src/components/xform/form-render/container-item/list-h5-item.vue +1913 -1699
  106. package/src/components/xform/form-render/index.vue +153 -147
  107. package/src/components/xform/form-render/indexMixin.js +35 -3
  108. package/src/components/xform/lang/en-US.js +14 -0
  109. package/src/components/xform/lang/zh-CN.js +17 -0
  110. package/src/components/xform/mixins/defaultHandle.js +707 -707
  111. package/src/components/xform/styles/h5.scss +2238 -0
  112. package/src/components/xform/utils/textMaskUtil.js +182 -179
  113. package/src/components/xform/utils/treeTableUtil.js +1292 -1265
  114. package/src/components/xform/utils/util.js +56 -11
  115. package/src/directive/append-to-body/index.js +48 -0
  116. package/src/index.js +13 -4
  117. package/src/layout/components/Sidebar/default.vue +1655 -1655
  118. package/src/layout/components/extractedCode/viewDialog.vue +7 -7
  119. package/src/router/index.js +48 -27
  120. package/src/router/modules/customer.js +71 -14
  121. package/src/store/modules/permission.js +17 -18
  122. package/src/utils/assetUrl.js +19 -0
  123. package/src/utils/pdfUtil.js +429 -429
  124. package/src/utils/resolveViewComponent.js +142 -16
  125. package/src/utils/vab.js +1283 -1279
  126. package/src/views/bd/project/branch/bd_branch/edit.vue +145 -0
  127. package/src/views/bd/project/branch/bd_branch/list.vue +72 -0
  128. package/src/views/bd/project/branch/bd_branch/menuKindDialog.vue +106 -0
  129. package/src/views/bd/project/branch/bd_branch/mixins/edit.js +189 -0
  130. package/src/views/bd/project/branch/bd_branch/mixins/list.js +124 -0
  131. package/src/views/bd/project/branch/bd_branch/mixins/menuKindDialog.js +85 -0
  132. package/src/views/bd/project/branch/form_script/list.vue +31 -0
  133. package/src/views/bd/project/branch/form_template/list.vue +30 -0
  134. package/src/views/bd/project/branch/menu_kind/list.vue +31 -0
  135. package/src/views/bd/project/common/form_script/list.vue +16 -0
  136. package/src/views/bd/project/common/form_template/list.vue +15 -0
  137. package/src/views/bd/project/common/menu_kind/list.vue +15 -0
  138. package/src/views/bd/project/core/branchContext.js +100 -0
  139. package/src/views/bd/project/core/branchPage.js +78 -0
  140. package/src/views/bd/project/core/branchPageWrap.vue +225 -0
  141. package/src/views/bd/project/core/branchScope.js +44 -0
  142. package/src/views/bd/project/core/branchSearchPage.js +285 -0
  143. package/src/views/bd/project/core/branchSelect.vue +85 -0
  144. package/src/views/bd/project/core/branchTreeBar.vue +81 -0
  145. package/src/views/bd/project/core/httpBranchPatch.js +58 -0
  146. package/src/views/bd/project/datatable/menu_kind/list.vue +15 -0
  147. package/src/views/bd/project/datatable/table_model/list.vue +15 -0
  148. package/src/views/bd/setting/bd_company_env/dialog.vue +174 -174
  149. package/src/views/bd/setting/form_template/edit.vue +378 -356
  150. package/src/views/bd/setting/form_template/formDesignerDialog.vue +6 -0
  151. package/src/views/bd/setting/form_template/formTemplateType.js +43 -0
  152. package/src/views/bd/setting/form_template/list.vue +304 -303
  153. package/src/views/bd/setting/form_template/mixins/edit.js +344 -280
  154. package/src/views/bd/setting/form_template/mixins/list.js +748 -721
  155. package/src/views/bd/setting/table_model/edit.vue +1066 -1066
  156. package/src/views/bd/setting/table_model/mixins/edit.js +1455 -1455
  157. package/src/views/bd/setting/table_model/mixins/zdDialog.js +148 -148
  158. package/src/views/demo/bizTab/bill/billConfig.js +41 -0
  159. package/src/views/demo/bizTab/bill/detail.vue +436 -0
  160. package/src/views/demo/bizTab/bill/list.vue +288 -0
  161. package/src/views/demo/bizTab/bill/productDialog.vue +176 -0
  162. package/src/views/demo/bizTab/simple/billApi.js +123 -0
  163. package/src/views/demo/bizTab/simple/detail.vue +407 -0
  164. package/src/views/demo/bizTab/simple/list.vue +217 -0
  165. package/src/views/demo/bizTab/standalone/index.vue +121 -0
  166. package/src/views/demo/bizTab/wf/billConfig.js +44 -0
  167. package/src/views/demo/bizTab/wf/detail.vue +661 -0
  168. package/src/views/demo/bizTab/wf/list.vue +242 -0
  169. package/src/views/support/form-dialog-demo/demoPickerDialog.vue +72 -0
  170. package/src/views/support/form-dialog-demo/index.vue +537 -0
  171. package/src/views/user/file_view_ins/list.vue +970 -970
  172. package/src/views/user/form/vform/designer.vue +823 -821
  173. package/src/views/user/home/default.vue +1117 -1117
  174. package/src/views/user/home/default2.vue +1 -1
  175. package/src/views/user/home/index.vue +103 -101
  176. package/src/views/user/home/wjl/content.vue +1569 -0
  177. package/src/views/user/notify_message/dialog.vue +139 -137
  178. package/src/views/user/outLink/cc_form_view.vue +188 -0
  179. package/src/views/user/outLink/form_view.vue +202 -202
  180. package/src/views/user/outLink/index.vue +110 -110
  181. package/src/views/user/outLink/view.vue +3 -3
  182. package/src/views/user/role/edit.vue +632 -632
  183. package/src/views/user/role/list.vue +260 -260
  184. package/src/views/user/wf/iframe/index.vue +51 -51
  185. package/src/views/user/wf/iframe/index2.vue +64 -64
  186. package/src/views/user/wf/wf_manage/list.vue +1112 -1116
  187. package/src/views/user/wf/wf_manage/list2.vue +871 -875
  188. package/src/views/user/wf/wf_manage/wfContentDialog.vue +134 -131
  189. package/src/views/user/wf/wf_obj_config/importItemDialog.vue +1 -1
  190. package/src/components/xform/form-designer/form-widget/field-widget/dropdown-menu-widget.vue +0 -106
  191. package/src/components/xform/form-designer/form-widget/field-widget/tableexportbuttonwidget.vue +0 -99
  192. package/src/components/xform/form-render/container-item/list-h5-item2.vue +0 -1340
  193. package/src/utils/wf.js +0 -766
@@ -0,0 +1,412 @@
1
+ # xform H5 —— P1 实现规格
2
+
3
+ > 日期:2026-08-25
4
+ > 上位文档:`2026-08 xform 移动端布局对齐 bill_setting 方案.md`(决策 3 / 6 / 8)
5
+ > 前置:`2026-08 xform H5 P0 实现规格.md`(根类 `.xform-h5` 与样式基线文件必须先落地)
6
+ > 状态:**规格已细化,未编码**
7
+ > P1 边界:**要改 vue 模板结构**(加滚动容器、按钮分流、卡片 DOM),有回归面,故与 P0 分期。
8
+
9
+ P1 交付 3 件事:
10
+
11
+ 1. 骨架改 flex 列 + 内部滚动区,底栏回到流内(决策 3)
12
+ 2. 底栏胶囊皮肤 + 溢出收「更多」(决策 8)
13
+ 3. `list-h5` 明细卡片皮肤 + 行级变更标记(决策 6)
14
+
15
+ **依赖**:三项的样式全部写进 P0 建的 `src/components/xform/styles/h5.scss`,
16
+ 沿用 P0 §2.2 的特异度策略(更高特异度 + 对方带 `!important` 己方也带)。
17
+
18
+ ---
19
+
20
+ ## 一、骨架滚动
21
+
22
+ ### 1.1 现状
23
+
24
+ `detail-h5-item.vue` 的 DOM:
25
+
26
+ ```html
27
+ <container-item-wrapper :widget="widget"> <!-- .container-wrapper -->
28
+ <div class="h5-detail-wrap grid-container" :class="[customClass]" :ref="widget.id">
29
+ <div class="h5-header">{{ widget.options.label }}</div>
30
+ <div> <!-- ← 裸 div,未来的滚动容器 -->
31
+ <transition-group class="form-widget-list"> panes(内容) </transition-group>
32
+ </div>
33
+ <div class="h5-fixed-bottom-btns">
34
+ <transition-group class="form-widget-list"> widgetList(按钮) </transition-group>
35
+ </div>
36
+ </div>
37
+ </container-item-wrapper>
38
+ ```
39
+
40
+ 样式(`style.scss`):`.h5-detail-wrap{padding-bottom:68px}` + `.h5-fixed-bottom-btns{position:fixed;bottom:0;height:56px!important}`。
41
+ 即**整页滚 + 底栏钉在视口底部**。
42
+
43
+ ### 1.2 现状是有 bug 的(改动的直接理由)
44
+
45
+ `formDialog.vue:319`、`searchFormDialog.vue:488`、`fileReferenceDialog.vue:277` 三处各写了:
46
+
47
+ ```scss
48
+ ::v-deep .H5 .h5-fixed-bottom-btns { bottom: 95px; }
49
+ ```
50
+
51
+ 意图是「弹框里把 fixed 底栏往上推」。但**三个文件都没有把 `H5` 这个类绑到任何元素上**
52
+ (`layoutType` 只存在 data 里,模板中无 `:class` 引用)——
53
+ 即这三条选择器**一条都没生效**,全是死补丁。
54
+
55
+ **所以当前真实表现是:H5 表单在这三个弹框里打开时,底栏 `position:fixed` 贴在屏幕底部,
56
+ 而不是弹框底部。** 骨架改成流内布局后此问题自然消失,三处补丁一并删除。
57
+
58
+ ### 1.3 目标 DOM
59
+
60
+ ```html
61
+ <container-item-wrapper :widget="widget">
62
+ <div class="h5-detail-wrap grid-container" :class="[customClass]" :ref="widget.id">
63
+ <div class="h5-header">{{ widget.options.label }}</div>
64
+ <div class="h5-detail-body"> <!-- 唯一滚动区 -->
65
+ <transition-group class="form-widget-list"> panes </transition-group>
66
+ </div>
67
+ <div class="h5-fixed-bottom-btns">…</div> <!-- 流内,不再 fixed -->
68
+ </div>
69
+ </container-item-wrapper>
70
+ ```
71
+
72
+ 模板改动只有一处:给那个裸 `<div>` 加 `class="h5-detail-body"`。
73
+
74
+ ### 1.4 样式(h5.scss 块 G)
75
+
76
+ ```scss
77
+ .xform-h5 {
78
+ height: 100%; // el-form.render-form 自身
79
+
80
+ .container-wrapper { height: 100%; } // container-item-wrapper 那层
81
+
82
+ .h5-detail-wrap {
83
+ display: flex;
84
+ flex-direction: column;
85
+ height: 100%;
86
+ min-height: 0; // 允许在 flex 父级下收缩
87
+ padding-bottom: 0 !important; // 压掉 style.scss:13765 的 68px 让位补丁
88
+ background: #f1f5fb;
89
+ }
90
+
91
+ .h5-header { flex: none; height: $xformH5HeaderHeight; line-height: $xformH5HeaderHeight; }
92
+
93
+ .h5-detail-body {
94
+ flex: 1;
95
+ min-height: 0; // ★ 没有这行 flex 子项不会滚,会把父级撑破
96
+ overflow-y: auto;
97
+ -webkit-overflow-scrolling: touch;
98
+ }
99
+
100
+ .h5-fixed-bottom-btns {
101
+ position: static !important; // 压掉 style.scss 的 position:fixed
102
+ flex: none;
103
+ height: $xformH5FooterHeight !important;
104
+ }
105
+ }
106
+ ```
107
+
108
+ > `min-height: 0` 是 flex 子项可滚动的必要条件(默认 `min-height:auto` 会被内容撑开,
109
+ > 结果是父级溢出而不是子级滚动)。这条**必写**。
110
+
111
+ ### 1.5 高度从哪来(本项最大的落地风险)
112
+
113
+ `height:100%` 要求父链每一层都有确定高度。父链是:
114
+
115
+ ```
116
+ 宿主容器 → el-form.render-form.xform-h5 → .container-wrapper → .h5-detail-wrap
117
+ ```
118
+
119
+ 后两层由块 G 补齐,**宿主那层是外部的**,分三类:
120
+
121
+ | 宿主 | 位置 | 现有高度 | 需要做什么 |
122
+ |---|---|---|---|
123
+ | 页面态 | `views/user/form/vform/render.vue` 的 `.designer-view` | `style.scss` 已有 `.designer-view{height:100%}` | 无需改,验证即可 |
124
+ | outLink 态 | `views/user/outLink/form_view.vue` scoped style | 已有 `.designer-view{height:calc(100vh - 33px)}` | 无需改,验证即可 |
125
+ | 弹框态 | `formDialog` / `searchFormDialog` / `fileReferenceDialog` 的 `.cont` | 各自 `calc(100vh - N)`,值不一 | **需逐个验证**;缺高度的补一行 |
126
+
127
+ **降级安全阀**:若某宿主确实拿不到高度,`height:100%` 会塌成 0(比现状更糟)。
128
+ 因此块 G 需要配一条兜底,二选一(实现时按真机结果定,见 六、待确认 1):
129
+
130
+ ```scss
131
+ // 方案 a:视口兜底(页面态友好,弹框里可能超出)
132
+ .xform-h5 .h5-detail-wrap { min-height: 100vh; }
133
+ // 方案 b:只在页面态兜底,弹框态不给(更保守)
134
+ .xform-h5:not(.in-dialog) .h5-detail-wrap { min-height: 100vh; }
135
+ ```
136
+
137
+ ### 1.6 要删的东西
138
+
139
+ 1. `formDialog.vue:319`、`searchFormDialog.vue:488`、`fileReferenceDialog.vue:277`
140
+ 三处 `::v-deep .H5 .h5-fixed-bottom-btns { bottom: 95px; }`(1.2 已证实是死补丁);
141
+ 2. `style.scss:13765` 的 `.h5-detail-wrap{padding-bottom:68px}` —— 块 G 用 `!important` 压住即可,
142
+ **P1 不直接删该行**(`components/mobile/*` 手写页也可能用到 `.h5-detail-wrap`),
143
+ 留到 P3 统一评估。
144
+
145
+ ---
146
+
147
+ ## 二、底栏胶囊 +「更多」
148
+
149
+ ### 2.1 胶囊样式(h5.scss 块 H)
150
+
151
+ ```scss
152
+ .xform-h5 .h5-fixed-bottom-btns {
153
+ background: #fff;
154
+ padding: 8px 13px;
155
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.06);
156
+
157
+ .form-widget-list, .el-form { display: flex; }
158
+ .field-wrapper { flex: 1; margin: 0 5px; }
159
+
160
+ .button-sty, .el-button {
161
+ width: 100%;
162
+ height: 40px;
163
+ border-radius: 30px;
164
+ padding: 0;
165
+ i { margin-right: 4px; }
166
+ }
167
+ }
168
+ ```
169
+
170
+ ### 2.2 溢出分流
171
+
172
+ - `widgetsConfig.js` 的 `detail-h5.options` 加 `maxVisibleButtons: 2`
173
+ (默认值 2,对齐 bill_setting 的两按钮胶囊布局;B 层已拍「先按默认做,真机再调」);
174
+ - 属性面板:`propertyRegister.js` 的 `COMMON_PROPERTIES` 加
175
+ `maxVisibleButtons: "maxVisibleButtons-editor"`,
176
+ 新建 `property-editor/maxVisibleButtons-editor.vue`(`el-input-number`,`name` 必须等于该编辑器名,
177
+ 由 `property-editor/index.js` 的 `require.context` 自动注册 —— 机制同 P0 §3.3);
178
+ - `detail-h5-item.vue` 加两个 computed 把 `widget.widgetList` 切开:
179
+
180
+ ```js
181
+ visibleButtons() {
182
+ let max = this.widget.options.maxVisibleButtons;
183
+ let list = this.widget.widgetList || [];
184
+ // 老表单该 option 为 null/undefined(见 P0 §3.2),退回「全部平铺」
185
+ if (!max || max <= 0 || list.length <= max) return list;
186
+ return list.slice(0, max);
187
+ },
188
+ overflowButtons() {
189
+ let max = this.widget.options.maxVisibleButtons;
190
+ let list = this.widget.widgetList || [];
191
+ if (!max || max <= 0 || list.length <= max) return [];
192
+ return list.slice(max);
193
+ },
194
+ ```
195
+
196
+ > **老表单口径同 P0 §3.2**:`upgradeWidgetConfig` 补的是 `null` 不是默认值,
197
+ > 运行时更是读到 `undefined` —— 所以判空必须退回「全部平铺」,
198
+ > 不能写成 `max = max || 2` 那样给老表单强行收起按钮。
199
+
200
+ 模板中把现有那个 `transition-group` 的遍历源从 `widget.widgetList` 换成 `visibleButtons`,
201
+ 后面追加:
202
+
203
+ ```html
204
+ <el-dropdown v-if="overflowButtons.length > 0" popper-class="xform-h5-dropdown">
205
+ <el-button class="button-sty more-btn" type="warning" plain>
206
+ {{ i18nt('designer.setting.h5MoreButton') }}
207
+ </el-button>
208
+ <el-dropdown-menu slot="dropdown">
209
+ <el-dropdown-item v-for="(subWidget, swIdx) in overflowButtons" :key="swIdx">
210
+ <component :is="subWidget.type + '-widget'" :field="subWidget" :designer="null"
211
+ :parent-list="widget.widgetList"
212
+ :index-of-parent-list="swIdx" :parent-widget="widget" />
213
+ </el-dropdown-item>
214
+ </el-dropdown-menu>
215
+ </el-dropdown>
216
+ ```
217
+
218
+ ### 2.3 ★ `el-dropdown-menu` 会被挪到 body 下
219
+
220
+ Element UI 的 `el-dropdown-menu` 走 popper,**默认 append-to-body**。
221
+ 菜单 DOM 一旦挪到 `<body>` 下,就**不在 `.xform-h5` 作用域内了** ——
222
+ 所有写在 `.xform-h5 { ... }` 里的规则对菜单内的按钮全部失效。
223
+
224
+ 处理:给 `popper-class="xform-h5-dropdown"`,菜单样式**单独写成顶层选择器**,
225
+ 不要嵌在 `.xform-h5` 里:
226
+
227
+ ```scss
228
+ /* 注意:不能嵌进 .xform-h5,菜单被 append 到 body 下了 */
229
+ .xform-h5-dropdown.el-dropdown-menu {
230
+ .el-dropdown-menu__item { margin: 8px 0; }
231
+ .button-sty, .el-button { width: 100%; height: 36px; border-radius: 30px; }
232
+ }
233
+ ```
234
+
235
+ > 这不是猜测:bill_setting 用的就是这个模式 —— 它给菜单加 `class="mobileApp_dropdown"`,
236
+ > 而 `style.scss:14538` 的 `.mobileApp_dropdown.el-dropdown-menu` 正是**顶层选择器**,
237
+ > 没有嵌在 `.mobileApp` 里面。
238
+
239
+ ### 2.4 按钮进下拉后的注意点
240
+
241
+ - **ref / refList 不受影响**:按钮仍在同一 Vue 组件树内,只是 DOM 位置变了,
242
+ `button-widget` 的 `ref="fieldEditor"` 与 `refMixin` 的注册照常;
243
+ - **事件照常**:`button-widget` 的 `@click.native="handleButtonWidgetClick"` 绑在 `el-button` 上,
244
+ 不依赖父容器;
245
+ - **`el-dropdown-item` 默认会吞点击后自动收起菜单**,这是期望行为;
246
+ - 若按钮 `options.hidden` 为真,`static-content-wrapper` 内部会 `v-show` 隐藏,
247
+ 此时 `el-dropdown-item` 会留一个空条目 —— **分流前应先过滤掉 hidden 的按钮**,
248
+ 否则「更多」里会出现空行(见 六、待确认 2)。
249
+
250
+ ---
251
+
252
+ ## 三、明细卡片皮肤
253
+
254
+ ### 3.1 先纠正一个预期
255
+
256
+ 上位方案里把这项描述成「`.h5-list-box .item` 是朴素列表行,要换成 `.pro-item` 卡片」。
257
+ 实际读代码后**差距比预期小**:`style.scss:14029` 起,`.h5-list-box .item` 已经是
258
+ 白底 + `radius 8` + `1px #eee` 边框 + 左侧 4px 竖条的卡片了。
259
+
260
+ 真正的差异只有 4 点:
261
+
262
+ | 项 | 现状(`.h5-list-box .item`) | 目标(bill_setting `.pro-item`) |
263
+ |---|---|---|
264
+ | 圆角 | 8px | 12px |
265
+ | 标题前缀 | 左侧 4px 竖条(`.t1::before`) | 5px 圆点(`inline-block` + `border-radius:50%`) |
266
+ | 右上角 | `.status` 徽标(梯形底色块) | 圆形箭头角标:20px 圆底 + `content:"\e6e0"`(element-icons) |
267
+ | 小字段区 | `.t2 > dl > dt/dd` | 同结构,字号 10-11px、`min-width:49%` 两列 |
268
+
269
+ 所以本项 **90% 是 CSS,模板只需加一个箭头角标元素**。
270
+
271
+ ### 3.2 `itemStyle` 选项
272
+
273
+ - `widgetsConfig.js` 的 `list-h5.options` 加 `itemStyle: "plain"`(`'plain' | 'card'`),
274
+ **默认 `plain` 保持存量表现不变**;
275
+ - 属性面板挂点同 2.2(`propertyRegister` 加一行 + 新建 editor,`require.context` 自动注册);
276
+ - `list-h5-item.vue` 的 `.h5-list-box > .item` 上加 class:
277
+
278
+ ```html
279
+ <div class="item" :class="{ 'h5-item-card': widget.options.itemStyle === 'card' }" …>
280
+ ```
281
+
282
+ > 判等口径同 P0 §3.2:只判 `=== 'card'`,老表单读到 `null`/`undefined` 时退回 plain。
283
+
284
+ - 箭头角标(仅 card 模式渲染,放在 `.t1` 内):
285
+
286
+ ```html
287
+ <i class="h5-item-arrow" v-if="widget.options.itemStyle === 'card'"></i>
288
+ ```
289
+
290
+ ### 3.3 样式(h5.scss 块 I)
291
+
292
+ ```scss
293
+ .xform-h5 .h5-list-box .item.h5-item-card {
294
+ border-radius: $xformH5CardRadius;
295
+
296
+ .t1 {
297
+ &::before { // 竖条 → 圆点
298
+ width: 5px !important;
299
+ height: 5px !important;
300
+ top: auto !important;
301
+ border-radius: 50% !important;
302
+ position: relative !important;
303
+ display: inline-block;
304
+ margin-right: 4px;
305
+ }
306
+ padding-right: 40px; // 给箭头角标让位
307
+ }
308
+
309
+ .h5-item-arrow {
310
+ position: absolute;
311
+ right: 12px;
312
+ top: 10px;
313
+ width: 20px;
314
+ height: 20px;
315
+ line-height: 20px;
316
+ text-align: center;
317
+ font-size: 12px;
318
+ border-radius: 50%;
319
+ background: rgba(42, 100, 148, 0.12);
320
+ &::before { content: "\e6e0"; font-family: element-icons !important; }
321
+ }
322
+
323
+ .t2 > dl { min-width: 49%; font-size: 11px; }
324
+ }
325
+ ```
326
+
327
+ ### 3.4 行级变更标记
328
+
329
+ `indexMixin.js:2556` 已有 `getCompareRowClass(subFormName, row)`,返回
330
+ `xform-compare-row-new` / `xform-compare-row-changed` / `""`,`data-table` 已在用
331
+ (`data-table-mixin.js:1573`)。list-h5 直接复用:
332
+
333
+ ```js
334
+ getRowCompareClass(row) {
335
+ let formRef = this.getFormRef();
336
+ if (!formRef || !formRef.isCompare || !formRef.getCompareRowClass) return "";
337
+ return formRef.getCompareRowClass(this.getListFieldName(), row);
338
+ },
339
+ ```
340
+
341
+ `subFormName` 取 list-h5 的字段名(`widget.options.name` / `keyName`,
342
+ 与 `data-table` 传给 `getCompareRowClass` 的口径保持一致 —— 实现时对齐
343
+ `data-table-mixin.js:1573` 那里的 `self.fieldKeyName`)。
344
+
345
+ 样式上给 `.xform-h5 .h5-list-box .item.xform-compare-row-changed` 加右上角
346
+ `el-icon-warning` 角标(对齐 bill_setting `.pro-item .t i.el-icon-warning`,色 `#ff731c`)。
347
+
348
+ > `getCompareRowClass` 内部先过 `isCompareSubTable(subFormName)`,
349
+ > 未参与对比的子表返回 `""`,不会满屏高亮 —— 这条保护已存在,不需重复实现。
350
+
351
+ ---
352
+
353
+ ## 四、i18n
354
+
355
+ `lang/zh-CN.js` 与 `lang/en-US.js` 的 `designer.setting` 下补:
356
+
357
+ ```js
358
+ h5MoreButton: "更多",
359
+ maxVisibleButtons: "底栏按钮数",
360
+ maxVisibleButtonsHelp: "仅 H5 版式生效。底部动作栏平铺显示的按钮个数,超出部分收进「更多」下拉。",
361
+ itemStyle: "明细行样式",
362
+ itemStyleHelp: "plain=朴素列表;card=卡片(带圆点标题与右侧箭头,点击进入明细详情)。",
363
+ ```
364
+
365
+ ---
366
+
367
+ ## 五、自测清单
368
+
369
+ 骨架:
370
+
371
+ 1. 页面态:内容区滚动时标题栏与底栏不动;
372
+ 2. 弹框态(`formDialog` / `searchFormDialog` / `fileReferenceDialog` 三条路径各验一次):
373
+ 底栏贴**弹框**底部而不是屏幕底部(**这是 1.2 那个现存 bug 的回归验证点**);
374
+ 3. outLink 态:高度正确,无双滚动条;
375
+ 4. 手机真机:聚焦输入框调起键盘,底栏不被顶飞、不遮挡当前输入行;
376
+ 5. 内容不足一屏时,底栏仍在底部而不是浮在内容下方;
377
+ 6. `.h5-detail-wrap` 未塌成 0 高(1.5 的降级安全阀验证)。
378
+
379
+ 底栏:
380
+
381
+ 7. 按钮数 ≤ 阈值:全部平铺,无「更多」;
382
+ 8. 按钮数 > 阈值:超出部分进「更多」,点击能正常触发原按钮逻辑;
383
+ 9. **「更多」菜单里的按钮样式正确**(2.3 的 append-to-body 验证点);
384
+ 10. 老表单(`maxVisibleButtons` 为 null/undefined):全部平铺,不出现「更多」;
385
+ 11. hidden 按钮不在「更多」里留空行(见 六、待确认 2)。
386
+
387
+ 明细:
388
+
389
+ 12. `itemStyle=plain`(默认):与改动前**像素级一致**(存量回归底线);
390
+ 13. `itemStyle=card`:圆角 12、标题圆点、右侧圆形箭头角标;
391
+ 14. 点卡片仍能打开「明细详情」弹框(`list-h5-item.vue:426`);
392
+ 15. 对比模式下变更行有角标、新增行有高亮;未参与对比的子表不高亮。
393
+
394
+ 回归:
395
+
396
+ 16. **PC 版式(layoutType≠H5)下 DOM 根不含 `xform-h5`,以上全部不生效**;
397
+ 17. `npm run lint`;`npm run test:unit`。
398
+
399
+ ---
400
+
401
+ ## 六、待确认
402
+
403
+ 1. **1.5 的降级安全阀取方案 a 还是 b?** 需要真机 + 三类宿主实测后定。
404
+ B 层已拍「先按默认做,真机再调」,实现时先取方案 a(`min-height:100vh`),
405
+ 若弹框态超出再换 b。
406
+ 2. **hidden 按钮的分流时机**:`visibleButtons` / `overflowButtons` 里要不要先
407
+ `filter(w => !w.options.hidden)`?倾向:要。但注意 `hidden` 可能被脚本运行时改,
408
+ computed 依赖 `widget.widgetList` 的深层属性能否触发重算需实测
409
+ (若不触发,退回「不过滤 + 菜单项 `v-if`」)。
410
+ 3. **`.h5-detail-wrap` 的 `padding-bottom:68px`(`style.scss:13765`)**
411
+ P1 只用 `!important` 压住不删。若 P3 决定回收 style.scss 存量 H5 样式,
412
+ 届时连同一并处理。