cloud-web-corejs 1.0.281 → 1.1.0-dev.5
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 +6 -2
- package/src/components/VabUpload/image-viewer.vue +442 -442
- package/src/components/VabUpload/index.vue +44 -2
- package/src/components/VabUpload/mixins.js +126 -19
- package/src/components/VabUpload/view.vue +247 -209
- package/src/components/baseTabs/mixins.js +181 -181
- package/src/components/bizTab/BizBillActions.vue +129 -0
- package/src/components/bizTab/BizTabListPage.vue +391 -0
- package/src/components/bizTab/README.md +378 -0
- package/src/components/bizTab/billTableUtil.js +48 -0
- package/src/components/bizTab/billValidators.js +136 -0
- package/src/components/bizTab/bizBillDetailMixin.js +705 -0
- package/src/components/bizTab/index.js +24 -0
- package/src/components/excelExport/exportFieldDialog.vue +23 -12
- package/src/components/excelExport/exportItemConfigUtil.js +30 -0
- package/src/components/excelExport/mixins.js +3 -3
- package/src/components/mobile/statusTag/mixins.js +1 -61
- package/src/components/mobile/wf/content.vue +1662 -1556
- package/src/components/mobile/wf/mixins/wfModifyDialogMixin.js +8 -6
- package/src/components/table/config.js +78 -78
- package/src/components/table/index.js +1276 -1276
- package/src/components/table/plugins/cell-area/index.js +1055 -0
- package/src/components/table/plugins/cell-area/index.scss +77 -0
- package/src/components/table/plugins/cell-area/util.js +224 -0
- package/src/components/table/tableForm.vue +330 -330
- package/src/components/table/tableFormMixin.js +318 -318
- package/src/components/table/vxeFilter/index.js +163 -163
- package/src/components/table/vxeFilter/mixin.js +316 -316
- package/src/components/wf/content.vue +1188 -1188
- package/src/components/wf/wf.js +40 -20
- package/src/components/wf/wfActionDropdown.vue +1 -1
- package/src/components/wf/wfActionItems.js +1 -1
- 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
- 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
- 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
- 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
- package/src/components/xform/form-designer/designer.js +15 -0
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-widget.vue +269 -269
- package/src/components/xform/form-designer/form-widget/container-widget/detail-temp-widget.vue +132 -0
- package/src/components/xform/form-designer/form-widget/container-widget/detail-widget.vue +250 -250
- package/src/components/xform/form-designer/form-widget/dialog/fileReferenceDialog.vue +319 -320
- package/src/components/xform/form-designer/form-widget/dialog/formDialog.vue +365 -365
- package/src/components/xform/form-designer/form-widget/dialog/searchFormDialog.vue +554 -555
- package/src/components/xform/form-designer/form-widget/dialog/vabSearchDialog.vue +409 -409
- package/src/components/xform/form-designer/form-widget/field-widget/a-link-widget.vue +150 -132
- package/src/components/xform/form-designer/form-widget/field-widget/date-range-widget.vue +114 -114
- package/src/components/xform/form-designer/form-widget/field-widget/date-widget.vue +154 -154
- package/src/components/xform/form-designer/form-widget/field-widget/form-item-wrapper.vue +47 -1
- package/src/components/xform/form-designer/form-widget/field-widget/mixins/date-limit-mixin.js +178 -178
- package/src/components/xform/form-designer/form-widget/field-widget/mixins/time-limit-mixin.js +77 -77
- package/src/components/xform/form-designer/form-widget/field-widget/select-export-item-button-widget.vue +6 -0
- package/src/components/xform/form-designer/form-widget/field-widget/select-widget.vue +139 -139
- package/src/components/xform/form-designer/form-widget/field-widget/time-range-widget.vue +106 -106
- package/src/components/xform/form-designer/form-widget/field-widget/time-widget.vue +134 -134
- package/src/components/xform/form-designer/form-widget/field-widget/vabUpload-widget.vue +1 -0
- package/src/components/xform/form-designer/setting-panel/form-setting.vue +39 -39
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/data-table-editor.vue +10 -10
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/exportItemColumns-dialog.vue +438 -432
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/table-column-dialog.vue +2103 -2103
- package/src/components/xform/form-designer/setting-panel/property-editor/container-detail/detail-temp-edito.vue +90 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/container-grid/gutter-editor.vue +82 -82
- package/src/components/xform/form-designer/setting-panel/property-editor/container-list-h5/list-h5-editor.vue +19 -5
- package/src/components/xform/form-designer/setting-panel/property-editor/container-table/table-dynamicField-editor.vue +8 -8
- package/src/components/xform/form-designer/setting-panel/property-editor/dropdownFlag-editor.vue +137 -137
- package/src/components/xform/form-designer/setting-panel/property-editor/field-button/search-dialog-event-editor.vue +237 -237
- package/src/components/xform/form-designer/setting-panel/property-editor/field-date/date-defaultValue-editor.vue +43 -43
- package/src/components/xform/form-designer/setting-panel/property-editor/field-date-range/date-range-defaultValue-editor.vue +43 -43
- package/src/components/xform/form-designer/setting-panel/property-editor/field-import-button/import2-button-editor.vue +96 -96
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/select-export-item-button-editor.vue +51 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-time/time-defaultValue-editor.vue +42 -42
- package/src/components/xform/form-designer/setting-panel/property-editor/field-time-range/time-range-defaultValue-editor.vue +43 -43
- package/src/components/xform/form-designer/setting-panel/property-editor/formScriptEnabled-editor.vue +158 -158
- package/src/components/xform/form-designer/setting-panel/property-editor/h5Span-editor.vue +51 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/itemStyle-editor.vue +39 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/name-editor.vue +188 -188
- package/src/components/xform/form-designer/setting-panel/property-editor/styleTempClass-editor.vue +51 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/textFlag-editor.vue +347 -347
- package/src/components/xform/form-designer/setting-panel/propertyRegister.js +4 -0
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +59 -3
- package/src/components/xform/form-render/container-item/data-table-mixin.js +151 -93
- package/src/components/xform/form-render/container-item/detail-h5-item.vue +183 -32
- package/src/components/xform/form-render/container-item/detail-temp-item.vue +110 -0
- package/src/components/xform/form-render/container-item/h5-card-pane-item.vue +160 -140
- package/src/components/xform/form-render/container-item/list-h5-item.vue +1688 -1700
- package/src/components/xform/form-render/index.vue +153 -147
- package/src/components/xform/form-render/indexMixin.js +12 -0
- package/src/components/xform/lang/en-US.js +10 -0
- package/src/components/xform/lang/zh-CN.js +12 -0
- package/src/components/xform/mixins/defaultHandle.js +707 -707
- package/src/components/xform/styles/h5.scss +1992 -0
- package/src/components/xform/utils/textMaskUtil.js +182 -179
- package/src/components/xform/utils/treeTableUtil.js +1292 -1265
- package/src/components/xform/utils/util.js +56 -11
- package/src/index.js +9 -4
- package/src/layout/components/Sidebar/default.vue +1 -1
- package/src/layout/components/extractedCode/viewDialog.vue +7 -7
- package/src/router/index.js +21 -0
- package/src/router/modules/customer.js +71 -14
- package/src/store/modules/permission.js +17 -18
- package/src/utils/pdfUtil.js +429 -429
- package/src/utils/resolveViewComponent.js +142 -16
- package/src/views/bd/project/branch/bd_branch/edit.vue +145 -0
- package/src/views/bd/project/branch/bd_branch/list.vue +72 -0
- package/src/views/bd/project/branch/bd_branch/menuKindDialog.vue +106 -0
- package/src/views/bd/project/branch/bd_branch/mixins/edit.js +189 -0
- package/src/views/bd/project/branch/bd_branch/mixins/list.js +124 -0
- package/src/views/bd/project/branch/bd_branch/mixins/menuKindDialog.js +85 -0
- package/src/views/bd/project/branch/form_script/list.vue +31 -0
- package/src/views/bd/project/branch/form_template/list.vue +30 -0
- package/src/views/bd/project/branch/menu_kind/list.vue +31 -0
- package/src/views/bd/project/common/form_script/list.vue +16 -0
- package/src/views/bd/project/common/form_template/list.vue +15 -0
- package/src/views/bd/project/common/menu_kind/list.vue +15 -0
- package/src/views/bd/project/core/branchContext.js +100 -0
- package/src/views/bd/project/core/branchPage.js +78 -0
- package/src/views/bd/project/core/branchPageWrap.vue +225 -0
- package/src/views/bd/project/core/branchScope.js +44 -0
- package/src/views/bd/project/core/branchSearchPage.js +285 -0
- package/src/views/bd/project/core/branchSelect.vue +85 -0
- package/src/views/bd/project/core/branchTreeBar.vue +81 -0
- package/src/views/bd/project/core/httpBranchPatch.js +58 -0
- package/src/views/bd/project/datatable/menu_kind/list.vue +15 -0
- package/src/views/bd/project/datatable/table_model/list.vue +15 -0
- package/src/views/bd/setting/bd_company_env/dialog.vue +174 -174
- package/src/views/bd/setting/table_model/edit.vue +1066 -1066
- package/src/views/bd/setting/table_model/mixins/edit.js +1455 -1455
- package/src/views/bd/setting/table_model/mixins/zdDialog.js +148 -148
- package/src/views/demo/bizTab/bill/billConfig.js +41 -0
- package/src/views/demo/bizTab/bill/detail.vue +436 -0
- package/src/views/demo/bizTab/bill/list.vue +288 -0
- package/src/views/demo/bizTab/bill/productDialog.vue +176 -0
- package/src/views/demo/bizTab/simple/billApi.js +123 -0
- package/src/views/demo/bizTab/simple/detail.vue +407 -0
- package/src/views/demo/bizTab/simple/list.vue +217 -0
- package/src/views/demo/bizTab/standalone/index.vue +121 -0
- package/src/views/demo/bizTab/wf/billConfig.js +44 -0
- package/src/views/demo/bizTab/wf/detail.vue +661 -0
- package/src/views/demo/bizTab/wf/list.vue +242 -0
- package/src/views/support/form-dialog-demo/demoPickerDialog.vue +72 -0
- package/src/views/support/form-dialog-demo/index.vue +537 -0
- package/src/views/user/file_view_ins/list.vue +3 -3
- package/src/views/user/home/default.vue +1 -1
- package/src/views/user/home/default2.vue +1 -1
- package/src/views/user/home/index.vue +8 -6
- package/src/views/user/home/wjl/content.vue +1569 -0
- package/src/views/user/notify_message/dialog.vue +7 -5
- package/src/views/user/outLink/cc_form_view.vue +188 -0
- package/src/views/user/outLink/form_view.vue +2 -2
- package/src/views/user/outLink/index.vue +4 -4
- package/src/views/user/outLink/view.vue +3 -3
- package/src/views/user/role/edit.vue +632 -632
- package/src/views/user/role/list.vue +260 -260
- package/src/views/user/wf/iframe/index.vue +3 -3
- package/src/views/user/wf/iframe/index2.vue +3 -3
- package/src/views/user/wf/wf_manage/list.vue +1112 -1116
- package/src/views/user/wf/wf_manage/list2.vue +9 -13
- package/src/views/user/wf/wf_manage/wfContentDialog.vue +8 -5
- package/src/components/xform/form-designer/form-widget/field-widget/dropdown-menu-widget.vue +0 -106
- package/src/components/xform/form-designer/form-widget/field-widget/tableexportbuttonwidget.vue +0 -99
- package/src/components/xform/form-render/container-item/list-h5-item2.vue +0 -1340
- package/src/utils/wf.js +0 -766
package/src/components/wf/wf.js
CHANGED
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
import {getToken} from "../../utils/auth";
|
|
3
3
|
import settingConfig from "@/settings.js";
|
|
4
4
|
import {selectDialogMixins} from "../../mixins/selectDialog";
|
|
5
|
-
import {
|
|
5
|
+
import {requireViewAsync} from "@base/utils/resolveViewComponent";
|
|
6
6
|
import {getWfButtonNames, loadWfButtonNames} from "./wfButtonName";
|
|
7
7
|
import {isWfAutoConfirm, loadWfAutoConfirm} from "./wfAutoConfirm";
|
|
8
8
|
|
|
9
9
|
let configUtil = {
|
|
10
10
|
baseUrl: process.env.VUE_APP_BASE_API,
|
|
11
11
|
getToken,
|
|
12
|
-
// 归属自己 / 包内组件本地渲染;归属别家子应用(remote
|
|
13
|
-
//
|
|
12
|
+
// 归属自己 / 包内组件本地渲染;归属别家子应用(remote)、缺文件或 chunk 加载失败时
|
|
13
|
+
// 解析为 null,不抛错崩溃。返回 Promise,调用方必须 await。
|
|
14
|
+
// 归属解析见 @base/utils/resolveViewComponent。
|
|
14
15
|
requireView: (url) => {
|
|
15
|
-
return
|
|
16
|
+
return requireViewAsync(url);
|
|
16
17
|
},
|
|
17
18
|
};
|
|
18
19
|
|
|
@@ -198,11 +199,12 @@ wfIndexMixin = {
|
|
|
198
199
|
modalStrictly: true,
|
|
199
200
|
});
|
|
200
201
|
},
|
|
201
|
-
openWfModifyDialog() {
|
|
202
|
+
async openWfModifyDialog() {
|
|
202
203
|
let row = this.paramData;
|
|
203
204
|
let url = row.url + ".vue";
|
|
204
205
|
this.showModifyDialog = true;
|
|
205
|
-
|
|
206
|
+
// await 之后再 $openEditView:它是 200ms 定时放行,冷启动拉 chunk 常超过它
|
|
207
|
+
this.content = await configUtil.requireView(url);
|
|
206
208
|
this.$openEditView("showBillEdit");
|
|
207
209
|
},
|
|
208
210
|
modfyDialogClose() {
|
|
@@ -828,8 +830,23 @@ wfContentMixin = {
|
|
|
828
830
|
},
|
|
829
831
|
});
|
|
830
832
|
},
|
|
833
|
+
/**
|
|
834
|
+
* 提醒只是主流程前面的一道增强,不能让它把主流程带崩或卡死:
|
|
835
|
+
* - 放行只允许一次(go 自带闸门),成功/异常各分支共用一个出口;
|
|
836
|
+
* - 确认框点取消 = 放弃本次操作,什么都不做,但 MessageBox 的 reject 必须吃掉,
|
|
837
|
+
* 否则是一条 unhandled rejection;
|
|
838
|
+
* - error 分支绝不能抛异常。request.js 是先调 config.error(e) 再 removeModel(config),
|
|
839
|
+
* 这里一抛,isLoading 的全屏遮罩就永远关不掉、整页被锁死。而网络失败/超时时
|
|
840
|
+
* e.response 本就是 undefined,老写法 e.response.status 必崩 —— 故 status 取值判空。
|
|
841
|
+
*/
|
|
831
842
|
handleReminderContent(scriptType, callback){
|
|
832
843
|
let that = getTarget(this);
|
|
844
|
+
let called = false;
|
|
845
|
+
const go = () => {
|
|
846
|
+
if (called) return
|
|
847
|
+
called = true;
|
|
848
|
+
callback && callback();
|
|
849
|
+
};
|
|
833
850
|
that.$http({
|
|
834
851
|
url: this.current_prefix + "/wf/getReminderContent",
|
|
835
852
|
data: {
|
|
@@ -841,23 +858,25 @@ wfContentMixin = {
|
|
|
841
858
|
isLoading: true,
|
|
842
859
|
errorMsg: false,
|
|
843
860
|
success: (res) => {
|
|
844
|
-
if(res.objx){
|
|
845
|
-
that.$baseConfirm(res.objx).then(() => {
|
|
846
|
-
callback && callback();
|
|
847
|
-
});
|
|
861
|
+
if(res && res.objx){
|
|
862
|
+
that.$baseConfirm(res.objx).then(go).catch(() => {});
|
|
848
863
|
}else{
|
|
849
|
-
|
|
864
|
+
go();
|
|
850
865
|
}
|
|
851
866
|
},
|
|
852
867
|
error: (e) => {
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
type: 'error',
|
|
859
|
-
});
|
|
868
|
+
let status = e && e.response ? e.response.status : null;
|
|
869
|
+
if(status === 404){
|
|
870
|
+
// 后端没部署这个接口,等同于「没有提醒」,静默放行
|
|
871
|
+
go();
|
|
872
|
+
return
|
|
860
873
|
}
|
|
874
|
+
/* 其余错误只提示不放行:提醒内容可能是必须让人看到的业务警告,
|
|
875
|
+
接口挂了就悄悄跳过等于把它吞掉。用户重试即可。 */
|
|
876
|
+
that.$errorMsg({
|
|
877
|
+
content: (e && e.message) || this.$t2('获取提醒内容失败', 'components.wf.reminderError'),
|
|
878
|
+
type: 'error',
|
|
879
|
+
}).catch(() => {});
|
|
861
880
|
},
|
|
862
881
|
});
|
|
863
882
|
},
|
|
@@ -1983,11 +2002,12 @@ wfModifyMixin = {
|
|
|
1983
2002
|
this.openWfModifyDialog(this.code);
|
|
1984
2003
|
},
|
|
1985
2004
|
methods: {
|
|
1986
|
-
openWfModifyDialog() {
|
|
2005
|
+
async openWfModifyDialog() {
|
|
1987
2006
|
let row = this.paramData;
|
|
1988
2007
|
let url = row.url + ".vue";
|
|
1989
2008
|
this.showModifyDialog = true;
|
|
1990
|
-
|
|
2009
|
+
// await 之后再 $openEditView:它是 200ms 定时放行,冷启动拉 chunk 常超过它
|
|
2010
|
+
this.content = await configUtil.requireView(url);
|
|
1991
2011
|
this.$openEditView("showBillEdit");
|
|
1992
2012
|
},
|
|
1993
2013
|
modfyDialogClose() {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
/* 详情标题栏里不收进下拉、直接平铺成独立按钮的操作。
|
|
12
12
|
顺序按 getWfActionItems 的定义序,不按这里的书写序。 */
|
|
13
|
-
export const HEADER_STANDALONE_KEYS = ["agree", "
|
|
13
|
+
export const HEADER_STANDALONE_KEYS = ["agree", "manual", "reject"];
|
|
14
14
|
|
|
15
15
|
export function getWfActionItems(vm) {
|
|
16
16
|
let wfInfo = (vm && vm.wfInfo) || {};
|
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
# xform H5 —— P0 实现规格
|
|
2
|
+
|
|
3
|
+
> 日期:2026-08-25
|
|
4
|
+
> 上位文档:`2026-08 xform 移动端布局对齐 bill_setting 方案.md`(决策 1/2/4/5 + 缺陷 5.1/5.2)
|
|
5
|
+
> 状态:**规格已细化,未编码**
|
|
6
|
+
> P0 边界:纯样式 + 一个字段选项。**不改数据结构、不改提交、不改取数**,可独立上线。
|
|
7
|
+
|
|
8
|
+
P0 交付 4 件事:
|
|
9
|
+
|
|
10
|
+
1. 根类 `.xform-h5` 由 form-render 输出(决策 1)
|
|
11
|
+
2. 包内样式基线 `src/components/xform/styles/h5.scss`(决策 2)
|
|
12
|
+
3. 字段排布 CSS 复刻 + 字段级 `h5Span` 半宽选项(决策 4/5)
|
|
13
|
+
4. 卡片皮肤微调 + 修 5.1(customClass 漏绑)/ 5.2(m2 死规则)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 一、根类落地
|
|
18
|
+
|
|
19
|
+
### 1.1 现状
|
|
20
|
+
|
|
21
|
+
`form-render/index.vue:13-22`:
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<el-form
|
|
25
|
+
:label-position="labelPosition"
|
|
26
|
+
:size="size"
|
|
27
|
+
:class="[customClass]"
|
|
28
|
+
class="render-form"
|
|
29
|
+
...
|
|
30
|
+
>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`customClass` 来自 `form-render/indexMixin.js:335`,只取 `formConfig.customClass`。
|
|
34
|
+
`formConfig` 是 computed(`indexMixin.js:303`,返回 `this.formJsonObj.formConfig`),可直接用。
|
|
35
|
+
|
|
36
|
+
### 1.2 改法
|
|
37
|
+
|
|
38
|
+
`indexMixin.js` 新增 computed(紧挨 `customClass` 放):
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
/** H5 版式根类:所有 H5 样式都收在 .xform-h5 作用域下,见 styles/h5.scss */
|
|
42
|
+
h5RootClass() {
|
|
43
|
+
return !!this.formConfig && this.formConfig.layoutType === "H5"
|
|
44
|
+
? "xform-h5"
|
|
45
|
+
: "";
|
|
46
|
+
},
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`index.vue` 的 el-form:
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
:class="[customClass, h5RootClass]"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 1.3 为什么不复用现有两个开关
|
|
56
|
+
|
|
57
|
+
| 现有开关 | 加在哪 | 为什么不够 |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `.designer-view.h5-layout` | `views/user/form/vform/render.vue:4` | 只有这一个宿主壳会加。表单还从 `formDialog` / `formDrawer` / `outLink/form_view` / 微前端子应用渲染,那几条路径拿不到根类 —— 现有 `formDialog.vue:319`、`searchFormDialog.vue:488`、`fileReferenceDialog.vue:277` 里的 `::v-deep .H5 .h5-fixed-bottom-btns` 补丁就是漂移证据 |
|
|
60
|
+
| `#app.mobileApp` | `App.vue:2`,UA 判定 | 与 layoutType 正交:H5 表单会在 PC 浏览器里预览,PC 表单也会在手机上打开 |
|
|
61
|
+
|
|
62
|
+
宿主壳的 `.h5-layout` 与 `.mobileApp` **都保持不动**,只是不再依赖它们。
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 二、样式基线文件
|
|
67
|
+
|
|
68
|
+
### 2.1 位置与引入
|
|
69
|
+
|
|
70
|
+
- 新建:`src/components/xform/styles/h5.scss`
|
|
71
|
+
- 引入:`form-render/index.vue` 的 `<style lang="scss">`(**必须非 scoped** —— 要穿透到各
|
|
72
|
+
field-widget 内部的 `.el-form-item`):
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<style lang="scss">
|
|
76
|
+
@import "../styles/h5.scss";
|
|
77
|
+
</style>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
> 现有 `index.vue` 底部那个 `<style lang="scss" scoped>` 块保留不动,新增一个非 scoped 块。
|
|
81
|
+
|
|
82
|
+
- 变量(`$baseColor` 等)由 vue.config 的 sass `additionalData` 注入的 `styles/global.scss` 提供,
|
|
83
|
+
两个应用的 vue.config 已约定一致,直接用即可。
|
|
84
|
+
|
|
85
|
+
### 2.2 特异度策略(**必读,否则样式会随机失效**)
|
|
86
|
+
|
|
87
|
+
现有 H5 样式写在 `resources/css/style.scss` 的裸类名下(`.h5-detail-wrap .h5-item ...`),
|
|
88
|
+
它经 `src/styles/index.scss` 全局引入。新文件通过组件 `<style>` 注入,
|
|
89
|
+
**两者的加载先后在 webpack 下不可靠**,不能靠「后写覆盖先写」。
|
|
90
|
+
|
|
91
|
+
因此本文所有覆盖规则遵守两条硬约束:
|
|
92
|
+
|
|
93
|
+
1. 凡是要覆盖 style.scss 同名规则的选择器,**特异度必须严格更高**。
|
|
94
|
+
现有典型是 `.h5-detail-wrap .h5-item .el-form-item__label`(0,3,0),
|
|
95
|
+
新规则写 `.xform-h5 .h5-detail-wrap .h5-item .el-form-item__label`(0,4,0)即可稳压。
|
|
96
|
+
2. 凡是对方带 `!important` 的(下表标注),**本方也必须带 `!important`**,特异度再高也压不过。
|
|
97
|
+
|
|
98
|
+
### 2.3 必须覆盖的现有规则对照
|
|
99
|
+
|
|
100
|
+
| 现有规则(`style.scss` 行号) | 现值 | 目标值 | 覆盖要点 |
|
|
101
|
+
|---|---|---|---|
|
|
102
|
+
| `.h5-detail-wrap .h5-item .el-form-item__label`(13860 附近)的 `&:after{display:none}` | 冒号被关掉 | `content:":"` 显示 | **这条最容易踩**:要先把 `display` 打开再给 content |
|
|
103
|
+
| 同上 `line-height: 38px` / `text-align:left !important` | 38px | 1.4,左对齐保持 | `text-align` 对方带 `!important`,本方也要带 |
|
|
104
|
+
| `.h5-item .el-input .el-input__inner`(13868 附近) | `height:38px!important; line-height:38px!important; border-radius:8px` | 无边框、右对齐、贴合 48px 行 | 三条都要 `!important` 回压 |
|
|
105
|
+
| `.h5-detail-wrap{padding-bottom:68px}`(13765) | 给 fixed 底栏让位 | P0 暂留(骨架改到 P1) | P0 不动,避免与 P1 冲突 |
|
|
106
|
+
| `.h5-form-box .form-widget-list.m2`(13806) | 死规则 | 删除 | 见 五、5.2 |
|
|
107
|
+
| `.h5-form-box .el-upload-list__item{width:102px}`(13818 起) | 102px | P2 统一为 74px | P0 不动 |
|
|
108
|
+
|
|
109
|
+
### 2.4 规则清单
|
|
110
|
+
|
|
111
|
+
按块给出,实现时逐块落。**全部包在 `.xform-h5 { }` 内。**
|
|
112
|
+
|
|
113
|
+
**块 A —— 变量**
|
|
114
|
+
|
|
115
|
+
```scss
|
|
116
|
+
$xformH5HeaderHeight: 38px; // 标题栏
|
|
117
|
+
$xformH5FooterHeight: 56px; // 底部动作栏(P1 用)
|
|
118
|
+
$xformH5DialogChrome: 73px; // 弹框 header+padding 占位(P1 用)
|
|
119
|
+
$xformH5RowHeight: 48px; // 字段行高
|
|
120
|
+
$xformH5LabelWidth: 80px; // 标签宽
|
|
121
|
+
$xformH5RowBorder: #f3f3f3; // 行分隔线
|
|
122
|
+
$xformH5CardRadius: 12px;
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
> 这几个常量正是为了收掉 bill_setting 散在 4 处 5 个值的 `calc(100vh - N)`(见上位文档 5.4)。
|
|
126
|
+
> **不要把 bill_setting 的具体数值抄过来**,以本表为准。
|
|
127
|
+
|
|
128
|
+
**块 B —— 分组卡片(对齐 `.c-item / .tit`)**
|
|
129
|
+
|
|
130
|
+
```scss
|
|
131
|
+
.xform-h5 {
|
|
132
|
+
.h5-item {
|
|
133
|
+
background: #fff;
|
|
134
|
+
border-radius: $xformH5CardRadius;
|
|
135
|
+
margin: 12px 8px 0;
|
|
136
|
+
padding-bottom: 6px;
|
|
137
|
+
overflow: hidden;
|
|
138
|
+
|
|
139
|
+
.h5-title {
|
|
140
|
+
line-height: 45px;
|
|
141
|
+
padding: 0 12px;
|
|
142
|
+
border-bottom: 1px solid #f6f6f6;
|
|
143
|
+
position: relative;
|
|
144
|
+
b { font-size: 14px; font-weight: 600; color: #323232; }
|
|
145
|
+
&::after { // 左侧竖色条,对齐 bill_setting 的 .tit>b::before
|
|
146
|
+
content: "";
|
|
147
|
+
position: absolute;
|
|
148
|
+
left: 0; top: 16px;
|
|
149
|
+
width: 4px; height: 13px;
|
|
150
|
+
background: $baseColor;
|
|
151
|
+
border-radius: 4px;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**块 C —— 字段行(核心,决策 4 的 CSS 复刻)**
|
|
159
|
+
|
|
160
|
+
```scss
|
|
161
|
+
.xform-h5 .h5-detail-wrap .h5-item .h5-form-box {
|
|
162
|
+
padding: 12px;
|
|
163
|
+
|
|
164
|
+
.form-widget-list { display: flex; flex-wrap: wrap; }
|
|
165
|
+
.field-wrapper { width: 100%; }
|
|
166
|
+
.field-wrapper.h5-half { width: 50%; }
|
|
167
|
+
|
|
168
|
+
.el-form-item {
|
|
169
|
+
display: flex;
|
|
170
|
+
align-items: flex-start;
|
|
171
|
+
min-height: $xformH5RowHeight;
|
|
172
|
+
padding: 6px 0;
|
|
173
|
+
margin-bottom: 0;
|
|
174
|
+
border-bottom: 1px solid $xformH5RowBorder;
|
|
175
|
+
|
|
176
|
+
.el-form-item__label {
|
|
177
|
+
width: $xformH5LabelWidth;
|
|
178
|
+
padding: 0 5px 0 0;
|
|
179
|
+
margin: 0;
|
|
180
|
+
line-height: 1.4;
|
|
181
|
+
height: auto;
|
|
182
|
+
overflow: hidden;
|
|
183
|
+
text-align: left !important; // 压 style.scss 的 !important
|
|
184
|
+
color: #808080;
|
|
185
|
+
&::after {
|
|
186
|
+
display: inline !important; // style.scss 把它 display:none 了
|
|
187
|
+
content: ":";
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.el-form-item__content {
|
|
192
|
+
flex: 1;
|
|
193
|
+
line-height: 1.4;
|
|
194
|
+
text-align: right;
|
|
195
|
+
word-break: break-word;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
&:last-child { border-bottom: none; }
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**块 D —— 输入控件归一(去边框、右对齐)**
|
|
204
|
+
|
|
205
|
+
```scss
|
|
206
|
+
.xform-h5 .h5-detail-wrap .h5-item .h5-form-box .el-form-item__content {
|
|
207
|
+
.el-input, .el-select { width: 100% !important; }
|
|
208
|
+
|
|
209
|
+
.el-input .el-input__inner,
|
|
210
|
+
.el-textarea .el-textarea__inner {
|
|
211
|
+
height: auto !important;
|
|
212
|
+
line-height: 1.4 !important;
|
|
213
|
+
min-height: 34px;
|
|
214
|
+
border: none !important;
|
|
215
|
+
border-radius: 0 !important;
|
|
216
|
+
padding: 0;
|
|
217
|
+
text-align: right;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.el-input .el-input__suffix,
|
|
221
|
+
.el-input .el-input__prefix {
|
|
222
|
+
.el-input__icon { line-height: 34px !important; }
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.el-radio-group .el-radio,
|
|
226
|
+
.el-checkbox-group .el-checkbox {
|
|
227
|
+
margin: 0 0 0 8px;
|
|
228
|
+
.el-radio__label, .el-checkbox__label { padding-left: 4px; }
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**块 E —— 必填星号与校验错误位**
|
|
234
|
+
|
|
235
|
+
字段行改成 flex 后,Element 的必填星号(`.el-form-item__label::before`)和错误提示会错位,
|
|
236
|
+
必须显式定位(bill_setting 的 `&:before{position:absolute}` 是同一处理):
|
|
237
|
+
|
|
238
|
+
```scss
|
|
239
|
+
.xform-h5 .h5-detail-wrap .h5-item .h5-form-box .el-form-item {
|
|
240
|
+
position: relative;
|
|
241
|
+
&.is-required .el-form-item__label::before {
|
|
242
|
+
position: absolute;
|
|
243
|
+
left: -8px;
|
|
244
|
+
margin: 0;
|
|
245
|
+
}
|
|
246
|
+
.el-form-item__error {
|
|
247
|
+
position: static;
|
|
248
|
+
text-align: right;
|
|
249
|
+
padding-top: 2px;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**块 F —— 半宽相邻行的分隔线**
|
|
255
|
+
|
|
256
|
+
两个半宽字段并排时,块 C 的 `border-bottom` 会各画一条、视觉上是一条;
|
|
257
|
+
但当一行只有一个半宽字段(末尾落单)时右半边缺线。P0 接受该表现,
|
|
258
|
+
如需补齐在 `.field-wrapper.h5-half` 上加 `&:nth-child(odd):last-child { width: 100%; }`。
|
|
259
|
+
**该行为需 UI 确认**(见 六、待确认)。
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 三、`h5Span` 字段选项
|
|
264
|
+
|
|
265
|
+
### 3.1 数据落点
|
|
266
|
+
|
|
267
|
+
`hasConfig`(`designer.js:1082`)判断属性面板显不显示某编辑器,
|
|
268
|
+
读的是 **widgetsConfig 里原型 widget 的 options**,不是当前实例。
|
|
269
|
+
所以 `h5Span` 必须进原型。
|
|
270
|
+
|
|
271
|
+
字段原型共 42 个(`grep -c "formItemFlag: !0"`),另有 extension 通过
|
|
272
|
+
`addBasicFieldSchema` / `addAdvancedFieldSchema` / `addCustomWidgetSchema` 动态注册的。
|
|
273
|
+
|
|
274
|
+
**推荐做法:一处后处理,而不是 42 处手工展开 `...defaultH5Config`。**
|
|
275
|
+
|
|
276
|
+
在 `widgetsConfig.js` 尾部(`customFields` 声明之后、`add*Schema` 函数之前)加:
|
|
277
|
+
|
|
278
|
+
```js
|
|
279
|
+
/** H5 版式:所有表单字段统一具备 h5Span(整宽/半宽),见 docs/2026-08 xform H5 P0 实现规格.md */
|
|
280
|
+
export const defaultH5Config = {
|
|
281
|
+
h5Span: "full", // 'full' | 'half'
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
function applyH5FieldDefaults(schema) {
|
|
285
|
+
if (!schema || !schema.formItemFlag || !schema.options) return schema;
|
|
286
|
+
if (!Object.prototype.hasOwnProperty.call(schema.options, "h5Span")) {
|
|
287
|
+
Object.assign(schema.options, defaultH5Config);
|
|
288
|
+
}
|
|
289
|
+
return schema;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
[basicFields, advancedFields, businessFields, customFields].forEach((list) =>
|
|
293
|
+
list.forEach(applyH5FieldDefaults)
|
|
294
|
+
);
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
并在四个注册函数里各补一行(保证 extension 注册的组件也有):
|
|
298
|
+
|
|
299
|
+
```js
|
|
300
|
+
export function addBasicFieldSchema(fieldSchema) {
|
|
301
|
+
basicFields.push(applyH5FieldDefaults(fieldSchema));
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
> **TDZ 注意**:文件头部已有一条血泪注释(`widgetsConfig.js:1-6`)——
|
|
306
|
+
> Babel 转译后 `const` 提升会丢 TDZ,`...xxx` 展开 undefined。
|
|
307
|
+
> 本方案用的是**函数调用**而非展开,且放在所有数组声明之后,不踩这个坑。
|
|
308
|
+
> 但 `defaultH5Config` 的声明位置仍需在 `applyH5FieldDefaults` 之前。
|
|
309
|
+
|
|
310
|
+
### 3.2 老表单兼容(**必读**)
|
|
311
|
+
|
|
312
|
+
`upgradeWidgetConfig`(`designer.js:1114`)给老表单补新增 options 时:
|
|
313
|
+
|
|
314
|
+
```js
|
|
315
|
+
Object.keys(newWidget.options).forEach((ck) => {
|
|
316
|
+
if (!oldWidget.options.hasOwnProperty(ck)) {
|
|
317
|
+
let value = newWidget.options[ck];
|
|
318
|
+
let nullValue = Array.isArray(value) ? [] : null;
|
|
319
|
+
oldWidget.options[ck] = nullValue; // ← 补 null,不是补默认值
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
两条推论:
|
|
325
|
+
|
|
326
|
+
1. **老表单在设计器里打开后,`h5Span` 是 `null`,不是 `"full"`。**
|
|
327
|
+
2. **运行时渲染根本不跑这段**(它只在 `form-designer/indexMixin.js:456` 的
|
|
328
|
+
`upgradeFormJson` 里调),数据库存的老 formJson 里压根没有 `h5Span` 键,运行时读到 `undefined`。
|
|
329
|
+
|
|
330
|
+
所以渲染侧与编辑器侧**一律只判等于 `'half'`,绝不判「不等于 full」**:
|
|
331
|
+
|
|
332
|
+
```js
|
|
333
|
+
// 正确
|
|
334
|
+
field.options.h5Span === "half"
|
|
335
|
+
// 错误:null / undefined 会被当成 half,老表单全变两列
|
|
336
|
+
field.options.h5Span !== "full"
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### 3.3 属性面板挂点
|
|
340
|
+
|
|
341
|
+
三步,全部是既有机制,无需改框架:
|
|
342
|
+
|
|
343
|
+
1. **注册属性名 → 编辑器名**:`setting-panel/propertyRegister.js` 的 `COMMON_PROPERTIES`
|
|
344
|
+
里,「字段」区块(`labelWidth` / `labelHidden` 附近)加一行:
|
|
345
|
+
|
|
346
|
+
```js
|
|
347
|
+
h5Span: "h5Span-editor",
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
2. **新建编辑器组件**:`setting-panel/property-editor/h5Span-editor.vue`。
|
|
351
|
+
该目录由 `property-editor/index.js` 的 `require.context('./', true, /\w+\.vue$/)`
|
|
352
|
+
**自动收集并按 `comp.name` 注册**,不需要手工 import。
|
|
353
|
+
→ 组件的 `name` 必须严格等于 `"h5Span-editor"`。
|
|
354
|
+
|
|
355
|
+
3. **显示条件**:仅 `formConfig.layoutType === 'H5'` 时显示(参照
|
|
356
|
+
`container-grid-col/grid-col-span-editor.vue` 的 `formConfig` computed 写法)。
|
|
357
|
+
|
|
358
|
+
### 3.4 编辑器组件骨架
|
|
359
|
+
|
|
360
|
+
以 `fixedQuery-editor.vue` 为模板(同为「条件显示 + tooltip」型):
|
|
361
|
+
|
|
362
|
+
```html
|
|
363
|
+
<template>
|
|
364
|
+
<!-- 仅 H5 版式下显示:PC/Pad 版式该选项无作用 -->
|
|
365
|
+
<el-form-item
|
|
366
|
+
v-if="showEditor"
|
|
367
|
+
:label="i18nt('designer.setting.h5Span')"
|
|
368
|
+
class="form-item-label-top"
|
|
369
|
+
>
|
|
370
|
+
<el-tooltip
|
|
371
|
+
:enterable="false"
|
|
372
|
+
effect="dark"
|
|
373
|
+
:content="i18nt('designer.setting.h5SpanHelp')"
|
|
374
|
+
placement="top"
|
|
375
|
+
popper-class="tooltip-skin"
|
|
376
|
+
>
|
|
377
|
+
<el-radio-group v-model="optionModel.h5Span" size="mini">
|
|
378
|
+
<el-radio-button label="full">{{ i18nt('designer.setting.h5SpanFull') }}</el-radio-button>
|
|
379
|
+
<el-radio-button label="half">{{ i18nt('designer.setting.h5SpanHalf') }}</el-radio-button>
|
|
380
|
+
</el-radio-group>
|
|
381
|
+
</el-tooltip>
|
|
382
|
+
</el-form-item>
|
|
383
|
+
</template>
|
|
384
|
+
|
|
385
|
+
<script>
|
|
386
|
+
import i18n from "../../../../../components/xform/utils/i18n";
|
|
387
|
+
|
|
388
|
+
export default {
|
|
389
|
+
name: "h5Span-editor",
|
|
390
|
+
mixins: [i18n],
|
|
391
|
+
props: {
|
|
392
|
+
designer: Object,
|
|
393
|
+
selectedWidget: Object,
|
|
394
|
+
optionModel: Object,
|
|
395
|
+
},
|
|
396
|
+
computed: {
|
|
397
|
+
showEditor() {
|
|
398
|
+
return (
|
|
399
|
+
!!this.designer &&
|
|
400
|
+
!!this.designer.formConfig &&
|
|
401
|
+
this.designer.formConfig.layoutType === "H5"
|
|
402
|
+
);
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
};
|
|
406
|
+
</script>
|
|
407
|
+
|
|
408
|
+
<style scoped></style>
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
> 老表单打开时 `optionModel.h5Span` 是 `null`(见 3.2),两个 radio 都不选中 ——
|
|
412
|
+
> 这是**可接受**表现(等价于整宽),用户点一次即定值。
|
|
413
|
+
> 不要在 editor 里 `created` 时自动写 `"full"`,那会把所有老表单标记成已修改。
|
|
414
|
+
|
|
415
|
+
### 3.5 i18n 词条
|
|
416
|
+
|
|
417
|
+
- `src/components/xform/lang/zh-CN.js`,`designer.setting` 下(`fixedQuery` 在 347 行附近,就近放):
|
|
418
|
+
|
|
419
|
+
```js
|
|
420
|
+
h5Span: "H5 占宽",
|
|
421
|
+
h5SpanFull: "整宽",
|
|
422
|
+
h5SpanHalf: "半宽",
|
|
423
|
+
h5SpanHelp: "仅 H5 版式生效。半宽时两个字段并排一行,对应移动端的紧凑两列版式。",
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
- `src/components/xform/lang/en-US.js` 同结构补 4 条(`fixedQuery` 在 193 行附近)。
|
|
427
|
+
|
|
428
|
+
### 3.6 渲染落点
|
|
429
|
+
|
|
430
|
+
`form-item-wrapper.vue:11-15` 现状:
|
|
431
|
+
|
|
432
|
+
```html
|
|
433
|
+
<div
|
|
434
|
+
class="field-wrapper"
|
|
435
|
+
:class="{ 'design-time-bottom-margin': !!this.designer }"
|
|
436
|
+
v-show="!field.options.hidden || designState === true"
|
|
437
|
+
>
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
改为(注意 3.2 的判等口径):
|
|
441
|
+
|
|
442
|
+
```html
|
|
443
|
+
<div
|
|
444
|
+
class="field-wrapper"
|
|
445
|
+
:class="[
|
|
446
|
+
{ 'design-time-bottom-margin': !!this.designer },
|
|
447
|
+
field.options.h5Span === 'half' ? 'h5-half' : '',
|
|
448
|
+
]"
|
|
449
|
+
v-show="!field.options.hidden || designState === true"
|
|
450
|
+
>
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
> `form-item-wrapper` 是所有字段的公共入口,改这里一处即全量生效(设计器与运行时同一组件)。
|
|
454
|
+
> `.h5-half` 只在 `.xform-h5` 作用域内有样式(块 C),PC 下是个无害的空 class。
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## 四、卡片皮肤微调
|
|
459
|
+
|
|
460
|
+
按块 B 落即可。另需修 `h5-card-pane-item.vue`(缺陷 5.1):
|
|
461
|
+
|
|
462
|
+
现状 `h5-card-pane-item.vue:2`:
|
|
463
|
+
|
|
464
|
+
```html
|
|
465
|
+
<div class="h5-item">
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
组件里定义了 `customClass` computed 却从未使用,
|
|
469
|
+
而设计器侧 `h5-card-pane-widget.vue:2` 是绑了的 —— 导致设计器配的 class 到运行期丢失。改为:
|
|
470
|
+
|
|
471
|
+
```html
|
|
472
|
+
<div class="h5-item" :class="[customClass]">
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## 五、删除死代码
|
|
478
|
+
|
|
479
|
+
**5.2**:`resources/css/style.scss:13806` 的
|
|
480
|
+
|
|
481
|
+
```scss
|
|
482
|
+
.form-widget-list {
|
|
483
|
+
&.m2 { ... }
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
`form-widget-list` 的 class 是写死在 `transition-group` 上的,
|
|
488
|
+
customClass 落在 `.grid-cell` 或 `el-form-item` 上,这条选择器**永远命中不了**。
|
|
489
|
+
两列布局由块 C 的 `.field-wrapper.h5-half` 接管,此规则整块删除。
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## 六、自测清单
|
|
494
|
+
|
|
495
|
+
设计器侧:
|
|
496
|
+
|
|
497
|
+
1. 版式切 PC → 字段属性面板**无**「H5 占宽」;切 H5 → 出现;
|
|
498
|
+
2. 新建字段默认「整宽」;打开老表单,该字段两个 radio 均未选中,点一次能存住;
|
|
499
|
+
3. 选「半宽」后,设计器画布内两个半宽字段并排(设计器与运行时共用 form-item-wrapper,应一致)。
|
|
500
|
+
|
|
501
|
+
运行时侧(同一张表单分别以 PC / H5 版式渲染):
|
|
502
|
+
|
|
503
|
+
4. PC 版式下 DOM 根 `el-form` **不含** `xform-h5`,全部 H5 样式不生效(回归底线);
|
|
504
|
+
5. H5 版式下:字段行高 48px、标签宽 80px 且带冒号、值右对齐、输入框无边框无圆角;
|
|
505
|
+
6. 必填字段星号不与标签文字重叠;
|
|
506
|
+
7. 触发校验,错误文案在值下方右对齐,不把行撑破/不遮挡下一行;
|
|
507
|
+
8. 长文本值换行后行高自适应,不溢出卡片;
|
|
508
|
+
9. 半宽字段两列不错位;末尾落单的半宽字段表现符合 六、待确认 1 的结论;
|
|
509
|
+
10. 卡片圆角 12、标题左侧竖色条位置正确;
|
|
510
|
+
11. 从 `formDialog` / `formDrawer` / `outLink/form_view` 三条路径打开同一张 H5 表单,样式一致
|
|
511
|
+
(这是决策 1 的验证点 —— 旧的 `.h5-layout` 在这三条路径下拿不到)。
|
|
512
|
+
|
|
513
|
+
回归:
|
|
514
|
+
|
|
515
|
+
12. `npm run lint`;
|
|
516
|
+
13. `npm run test:unit`(P0 无逻辑分支,主要看没有误伤既有用例)。
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## 七、待确认
|
|
521
|
+
|
|
522
|
+
1. **末尾落单的半宽字段**是撑满整行还是留半行空白?(块 F)
|
|
523
|
+
2. **`h5Span` 的默认值**在 UI 上要不要给老表单显式回填 `"full"`?
|
|
524
|
+
本规格选择「不回填」,理由见 3.4 注释。若产品要求面板必须有选中态,
|
|
525
|
+
则应在 `upgradeWidgetConfig` 之外单独做一次性迁移,而不是在 editor 里写。
|
|
526
|
+
3. 块 D 把输入框边框全去掉后,**可编辑字段与只读字段在视觉上不可区分**
|
|
527
|
+
(bill_setting 也是这个表现,靠 `showSaveButton` 整表切换编辑/只读)。
|
|
528
|
+
若需要区分,建议 P1 给可编辑态加一条下划线而不是恢复边框。
|