refactor(formdata.vue): update default styles and config merging logic
- Adjusted the merging order of form configuration to prioritize frontend defaults when backend configurations are absent. - Clarified comments regarding the purpose of new visual styles and their application. - Modified the hideInnerBanner logic to ensure consistent behavior with the updated form styles.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]" :style="rowCellStyle">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'align-left']" :style="item._boxAlignStyle">
|
||||
<input
|
||||
@@ -24,7 +24,7 @@
|
||||
<view :class="['order-cell', 'flex-box', 'textarea', { 'vertical-layout': mode === 'vertical' }]">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'align-left']" :style="item._boxAlignStyle">
|
||||
<!-- 所有平台统一通过 formConfig.textareaRows / item.value.rows 控制显示行数:
|
||||
@@ -52,7 +52,7 @@
|
||||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'box-flex', 'align-right']">
|
||||
<text v-if="item.val != ''">{{ item.val }}</text>
|
||||
@@ -68,7 +68,7 @@
|
||||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'check-group-box', 'align-left', 'option-layout-' + (item.value.option_layout || 'vertical')]">
|
||||
<checkbox-group @change="checkboxChange($event, index)" :style="item._optionLayoutStyle">
|
||||
@@ -97,7 +97,7 @@
|
||||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'radio-group-box', 'align-left', 'option-layout-' + (item.value.option_layout || 'vertical')]">
|
||||
<radio-group @change="radioChange($event, index)" :style="item._optionLayoutStyle">
|
||||
@@ -126,7 +126,7 @@
|
||||
<view :class="['order-cell', 'flex-box', { 'vertical-layout': mode === 'vertical' }]">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'img-boxs', 'align-left']" :style="item._boxAlignStyle">
|
||||
<view v-for="(v, k) in item.img_lists" :key="k" class="img-box" @tap="uploadImg(index)">
|
||||
@@ -145,7 +145,7 @@
|
||||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'box-flex', 'align-right']">
|
||||
<picker
|
||||
@@ -167,7 +167,7 @@
|
||||
<view :class="['order-cell', 'flex-box', { 'vertical-layout': mode === 'vertical' }]">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'date-boxs', 'align-center']" :style="item._boxAlignStyle">
|
||||
<view class="date-box">
|
||||
@@ -206,7 +206,7 @@
|
||||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'box-flex', 'align-right']">
|
||||
<picker
|
||||
@@ -228,7 +228,7 @@
|
||||
<view :class="['order-cell', 'flex-box', { 'vertical-layout': mode === 'vertical' }]">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'date-boxs', 'align-center']" :style="item._boxAlignStyle">
|
||||
<view class="date-box">
|
||||
@@ -267,7 +267,7 @@
|
||||
<view :class="['order-cell', { 'vertical-layout': mode === 'vertical' }]">
|
||||
<view class="name" :style="item._labelStyle">
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text>
|
||||
<text class="tit">{{ item.value.title }}</text><text v-if="requiredPosition === 'after'" class="required required-after" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'box-flex', 'align-right']">
|
||||
<pick-regions
|
||||
@@ -283,6 +283,29 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 信息卡片(展示型组件,与 addon/form 新版 INFO_CARD 对齐)
|
||||
- 无标签/必填/校验/存储/导出,verify() 跳过
|
||||
- 内容存 value.content(富文本 HTML),rich-text 跨端渲染
|
||||
- 容器底色 value.bg_color;底部分割线 show_divider + divider_* 五参数
|
||||
- 老数据兼容:content 为空但存在 title/items 时按旧结构渲染 -->
|
||||
<view v-if="item.controller == 'InfoCard'" class="info-card-wrap" :style="item._infoCardWrapStyle">
|
||||
<rich-text v-if="item._infoCardHasContent" class="info-card-content" :nodes="item.value.content"></rich-text>
|
||||
<template v-else-if="item.value.title || (item.value.items && item.value.items.length)">
|
||||
<view v-if="item.value.title" class="info-card-title" :style="{ fontSize: ((item.value.title_font_size || 36) / 2) + 'px', color: item.value.title_color || '#1f2937', fontWeight: 700 }">
|
||||
{{ item.value.title }}
|
||||
</view>
|
||||
<view v-if="item.value.items && item.value.items.length" class="info-card-items">
|
||||
<view
|
||||
v-for="(it, iidx) in item.value.items"
|
||||
:key="iidx"
|
||||
class="info-card-item"
|
||||
:style="{ fontSize: ((item.value.item_font_size || 26) / 2) + 'px', color: item.value.item_color || '#6b7280' }"
|
||||
>{{ it }}</view>
|
||||
</view>
|
||||
</template>
|
||||
<view v-if="item.value.show_divider == 1" class="info-card-divider" :style="item._infoCardDividerStyle"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -546,6 +569,10 @@ export default {
|
||||
requiredColor() {
|
||||
return this.config.requiredColor;
|
||||
},
|
||||
// 必填星号位置(before=标签前(默认)/ after=标签后;与后端 form_config.required_position 对齐)
|
||||
requiredPosition() {
|
||||
return this.config.requiredPosition === 'after' ? 'after' : 'before';
|
||||
},
|
||||
checkedColor() {
|
||||
return this.config.checkedColor;
|
||||
},
|
||||
@@ -607,6 +634,50 @@ export default {
|
||||
optStyle['gap'] = '20rpx';
|
||||
}
|
||||
this.$set(item, '_optionLayoutStyle', optStyle);
|
||||
|
||||
// 信息卡片:容器底色 + 空白判定 + 分割线样式(与后台 design.js 的
|
||||
// getInfoCardContainerStyle / getInfoCardDividerStyle 对齐;数值单位为 px 直出,
|
||||
// 与编辑器输入单位一致,375 宽屏上与后台 PC 预览视觉一致)
|
||||
if (item.controller == 'InfoCard') {
|
||||
// 容器:bg_color 配置且非 transparent 时输出底色 + 圆角 + 内边距
|
||||
const wrapStyle = {};
|
||||
const bg = itemValue.bg_color;
|
||||
if (bg && bg !== 'transparent') {
|
||||
wrapStyle['background-color'] = bg;
|
||||
wrapStyle['border-radius'] = '6px';
|
||||
wrapStyle['padding'] = '8px 10px';
|
||||
}
|
||||
this.$set(item, '_infoCardWrapStyle', wrapStyle);
|
||||
// 空白判定:去标签 + + 去空白后为空 → 不渲染富文本(与后台一致,避免空白块)
|
||||
const raw = itemValue.content == null ? '' : String(itemValue.content);
|
||||
const textOnly = raw.replace(/<[^>]+>/g, '').replace(/ /gi, ' ').replace(/\s/g, '');
|
||||
this.$set(item, '_infoCardHasContent', !!textOnly);
|
||||
// 分割线:border-top 渲染支持 solid/dashed/dotted/double;
|
||||
// 宽度 calc(w% - 2*px),w<100 且 px=0 时 margin auto 居中(与后台同规则)
|
||||
if (itemValue.show_divider == 1) {
|
||||
const h = parseInt(itemValue.divider_height);
|
||||
const mt = parseInt(itemValue.divider_margin_top);
|
||||
let w = parseInt(itemValue.divider_width);
|
||||
let px = parseInt(itemValue.divider_padding_x);
|
||||
if (!Number.isFinite(w) || w <= 0 || w > 100) w = 100;
|
||||
if (!Number.isFinite(px) || px < 0) px = 0;
|
||||
const dStyle = {
|
||||
height: '0',
|
||||
'border-top': (Number.isFinite(h) && h > 0 ? h : 1) + 'px ' + (itemValue.divider_style || 'solid') + ' ' + (itemValue.divider_color || '#f0f0f0'),
|
||||
'margin-top': (Number.isFinite(mt) && mt >= 0 ? mt : 8) + 'px',
|
||||
'margin-left': px + 'px',
|
||||
'margin-right': px + 'px',
|
||||
width: 'calc(' + w + '% - ' + (px * 2) + 'px)'
|
||||
};
|
||||
if (w < 100 && px === 0) {
|
||||
dStyle['margin-left'] = 'auto';
|
||||
dStyle['margin-right'] = 'auto';
|
||||
}
|
||||
this.$set(item, '_infoCardDividerStyle', dStyle);
|
||||
} else {
|
||||
this.$set(item, '_infoCardDividerStyle', {});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 容器样式(提供给外部 diy-form 使用)
|
||||
@@ -793,7 +864,12 @@ export default {
|
||||
verify() {
|
||||
for (let i = 0; i < this.formData.length; i++) {
|
||||
let item = this.formData[i];
|
||||
|
||||
|
||||
// 信息卡片:不参与必填/校验(设计如此:仅展示活动/事件描述)
|
||||
if (item.controller == 'InfoCard') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.controller == 'Text') {
|
||||
if (item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: this.$lang('components.ns-newform.pleaseInput', { title: item.value.title }) });
|
||||
@@ -1170,6 +1246,11 @@ export default {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* 必填星号位置=标签后(required_position=after):margin 方向反转,与标签前视觉对称 */
|
||||
.required.required-after {
|
||||
margin-right: 0;
|
||||
margin-left: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.box {
|
||||
@@ -1526,6 +1607,55 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 信息卡片(与 addon/form/shop/view/public/css/form.css 的 .form-info-card* 对齐)
|
||||
// 展示型组件:富文本内容 + 可选底部分割线;不参与数据校验/存储
|
||||
.info-card-wrap {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 4rpx 0 2rpx;
|
||||
|
||||
// 富文本内容(编辑器产出的 p/strong/em/u/span/a/img/video/hr/iframe)
|
||||
.info-card-content {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
line-height: 1.7;
|
||||
word-break: break-all;
|
||||
|
||||
::v-deep p { margin: 0; }
|
||||
::v-deep p + p { margin-top: 6rpx; }
|
||||
::v-deep img { max-width: 100%; }
|
||||
::v-deep video { max-width: 100%; display: block; }
|
||||
::v-deep hr { border: none; border-top: 1px solid #e0e0e0; margin: 16rpx 0; }
|
||||
::v-deep a { color: #1278FE; }
|
||||
}
|
||||
|
||||
// 底部分割线:线样式/颜色/粗细/上边距/宽度/左右边距由内联 _infoCardDividerStyle 控制
|
||||
.info-card-divider {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// 老数据结构(title + items)兜底渲染
|
||||
.info-card-title {
|
||||
line-height: 1.4;
|
||||
// 字号 / 颜色由模板内联 style 控制
|
||||
}
|
||||
|
||||
.info-card-items {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.info-card-item {
|
||||
line-height: 1.6;
|
||||
word-break: break-all;
|
||||
// 字号 / 颜色由模板内联 style 控制
|
||||
|
||||
& + .info-card-item {
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Reference in New Issue
Block a user