Compare commits

...

5 Commits

Author SHA1 Message Date
b4c47fcc26 Merge branch 'dev/1.0' of http://git.aigc-quickapp.com/Uniapp/lucky_shop into temp221
# Conflicts:
#	components-diy/diy-form.vue
2026-09-02 11:58:46 +08:00
b31c133d8e chore:表单修改边距 2026-09-02 11:44:19 +08:00
aafd888596 chore:表单横幅缩小 2026-09-02 10:51:46 +08:00
ff3c2a0d9b chore:97数字跳动的显示正常 2026-09-01 18:26:36 +08:00
33f54eb63c chore:后台数字跳动可以自定义文字大小颜色 2026-09-01 15:56:30 +08:00
4 changed files with 118 additions and 37 deletions

View File

@@ -202,8 +202,7 @@ const localDevConfig = ({
// })['2724']; // 生物菌肥
// })['2811']; // 选择要使用的环境配置
// })['local-11']; // 选择要使用的环境配置
})['2811']; // 2811
// })['local-1']; // 本地
})['2811']; // 本地
// })['local-2']; // 本地
// })['local-11']; // 本地
// })['1-test']; // test

View File

@@ -1,36 +1,25 @@
<template>
<template>
<view :style="componentStyle" data-component-name="diy-digit">
<scroll-view :class="['graphic-nav', value.showStyle == 'fixed' ? 'fixed-layout' : value.showStyle]"
:scroll-x="value.showStyle == 'singleSlide'">
<view class="uni-scroll-view-content">
<view v-for="(item, index) in value.list" :key="index"
:class="['graphic-nav-item', value.mode, value.mode === 'text' ? 'newright' : '']"
:style="{ width: (100 / value.rowCount + '%') + ';' }">
<view style="display:flex;">
<view :style="{
'line-height': '1.2;',
'font-size': (value.font.titlesize * 2 + 'rpx') + ';',
'font-weight': '600;',
'color': value.font.titlecolor + ';'
}">
:style="itemStyle">
<view :style="innerWrapStyle">
<view :style="innerRowStyle">
<uv-count-to :ref="`countTo-${index}`" :autoplay="true" :startVal="30" :endVal="item.title"
:decimals="getvalue(item.title)" decimal="."></uv-count-to>
<text :style="{
'margin-left': '4rpx;',
'font-size': (value.font.unitsize * 2 + 'rpx') + ';',
'font-weight': value.font.weight + ';',
'color': value.font.unitcolor + ';'
}">{{ item.unit }}</text>
:decimals="getvalue(item.title)" decimal="."
:color="value.font.titlecolor"
:fontSize="titleFontSize"
:bold="isBold(value.font.weight)"></uv-count-to>
<text :style="unitStyle">{{ item.unit }}</text>
</view>
</view>
<view class="graphic-text">
<text :style="{
'font-size': (value.font.descsize * 2 + 'rpx') + ';',
'font-weight': value.font.weight + ';',
'color': value.font.desccolor + ';'
}">{{ item.desc }}</text>
<view class="graphic-text">
<text :style="descStyle">{{ item.desc }}</text>
</view>
</view>
</view>
</view>
</scroll-view>
<ns-login ref="login"></ns-login>
@@ -54,10 +43,20 @@ export default {
pageWidth: '',
indicatorDots: false,
swiperCurrent: 0
// #ifndef MP
,windowWidth: 375
// #endif
}
},
created() {
// 组件创建时的逻辑
// #ifndef MP
try {
let info = uni.getSystemInfoSync();
this.windowWidth = info.windowWidth || info.screenWidth || 375;
if (this.windowWidth > 960) this.windowWidth = 375;
} catch (e) { }
// #endif
},
watch: {
componentRefresh(newValue) {
@@ -65,6 +64,42 @@ export default {
}
},
computed: {
// 全部返回字符串:WeChat 小程序的 style="{{obj}}" 对象绑定不会被运行时正确解析为内联 CSS
//(参考 diy-graphic-nav.vue:那里同样用字符串拼接 style="{{'width:...%'}}",能正常生效)。
// 字符串既能被 MP 直接当 cssText,也能被 H5 的 CSSOM 正确解析。
itemStyle() {
return 'width:' + (100 / this.value.rowCount) + '%;';
},
innerWrapStyle() {
return 'display:flex;justify-content:center;align-items:center;width:100%;';
},
innerRowStyle() {
return 'display:flex;align-items:baseline;justify-content:center;width:100%;line-height:1.2;';
},
unitStyle() {
// #ifdef MP
return 'margin-left:4rpx;font-size:' + (this.value.font.unitsize * 2) + 'rpx;font-weight:' + this.value.font.weight + ';color:' + this.value.font.unitcolor + ';';
// #endif
// #ifndef MP
return 'margin-left:' + this.rpxToPx(4) + 'px;font-size:' + this.rpxToPx((Number(this.value.font.unitsize) || 12) * 2) + 'px;font-weight:' + this.value.font.weight + ';color:' + this.value.font.unitcolor + ';';
// #endif
},
descStyle() {
// #ifdef MP
return 'font-size:' + (this.value.font.descsize * 2) + 'rpx;font-weight:' + this.value.font.weight + ';color:' + this.value.font.desccolor + ';';
// #endif
// #ifndef MP
return 'font-size:' + this.rpxToPx((Number(this.value.font.descsize) || 12) * 2) + 'px;font-weight:' + this.value.font.weight + ';color:' + this.value.font.desccolor + ';';
// #endif
},
titleFontSize() {
// #ifdef MP
return this.value.font.titlesize || 22;
// #endif
// #ifndef MP
return this.rpxToPx((Number(this.value.font.titlesize) || 22) * 2);
// #endif
},
componentStyle() {
let style = '';
style += 'background-image:url(' + this.$util.img(this.value.imageUrl) + ');background-size:100% 100%;';
@@ -83,11 +118,25 @@ export default {
}
},
methods: {
// #ifndef MP
// rpx -> px:H5 行内样式里的 rpx 不生效,统一换算成 px
rpxToPx(rpx) {
let num = Number(rpx) || 0;
if (!num) return 0;
return Math.round((num * (this.windowWidth || 375) / 750) * 100) / 100;
},
// #endif
// 获取小数位数
getvalue(value) {
return value % 1 !== 0 ? 2 : 0;
},
// 是否加粗
isBold(weight) {
return weight === 'bold' || (weight && Number(weight) >= 600);
},
// 页面跳转
redirectTo(item) {
if (!item.wap_url || this.$util.getCurrRoute() != this.$util.MEMBER_PAGE_URL || this.storeToken) {
@@ -257,4 +306,5 @@ export default {
}
}
}
</style>
</style>

View File

@@ -7,7 +7,11 @@
r=function(){var o=this.value.show_banner...this.$mp.data...})
报 "Cannot read properties of undefined (reading 'show_banner')"。 -->
<view v-if="value && value.show_banner && value.form_banner" class="form-banner is-card-overlap" :style="bannerStyle + bannerBleedStyle">
<image :src="$util.img(value.form_banner)" mode="widthFix" class="banner-img" />
<!-- 固定高度容器:默认 180rpx ≈ 页面 1/8,由 formConfig.bannerHeight 控制。
图片用 mode="aspectFill" 居中裁剪填充,使横幅只占页面八分之一(与设计图一致)。 -->
<view class="banner-img-wrap" :style="bannerImgWrapStyle">
<image :src="$util.img(value.form_banner)" mode="aspectFill" class="banner-img" />
</view>
</view>
<!-- 卡片容器:仅在后台配置了 banner 图片时启用,让表单浮在 banner 之上(参考左图布局)。
无 banner 时不渲染 .form-card,保持原有平铺行为,零外溢。 -->
@@ -136,6 +140,14 @@ export default {
padding: `0 ${this._num(this.mergedFormConfig && this.mergedFormConfig.bannerPaddingX, 0)}rpx`
});
},
// Banner 图片包裹层高度(rpx)。固定高度使图片用 mode="aspectFill" 居中裁剪填充,
// 保证横幅只占页面 1/8 左右(默认 180rpx ≈ 1334rpx 屏高的 13.5%,接近 1/8)。
// 后台可配 formConfig.bannerHeight(camelCase)/ banner_height(snake_case)。
bannerImgWrapStyle() {
return this.$util.objToStyle({
height: `${this._num(this.mergedFormConfig && this.mergedFormConfig.bannerHeight, 180)}rpx`
});
},
// 表单风格:优先读显式 form_style(classic / card),未设置时回退到隐式判定(看 show_banner && form_banner)
// - classic:经典风格,平铺无 banner 卡片
// - card :卡片浮起风格,banner + 卡片浮起 + 容器内缩
@@ -270,6 +282,9 @@ export default {
// 通用全局配置(与后端 design.js getDefaultFormData().formConfig 字段名一致)
const base = {
formPaddingX: pick('formPaddingX', 'form_padding_x'),
// Banner 高度(rpx)。后台可配,默认 180rpx ≈ 页面 1/8 高度(适配主流手机屏高)
// 配合 mode="aspectFill" 居中裁剪,保证横幅只占页面八分之一左右
bannerHeight: pick('bannerHeight', 'banner_height'),
bannerPaddingX: pick('bannerPaddingX', 'banner_padding_x'),
tipPaddingX: pick('tipPaddingX', 'tip_padding_x'),
rowPaddingY: pick('rowPaddingY', 'row_padding_y'),
@@ -488,8 +503,19 @@ export default {
z-index: 1;
}
// 横幅图片固定高度容器:默认 180rpx ≈ 页面 1/8,与 bannerImgWrapStyle 默认值一致。
// 后台可通过 formConfig.bannerHeight / banner_height 覆盖。
// 配合 mode="aspectFill" 使图片居中裁剪填充,跨端一致呈现"只占页面八分之一"的视觉效果。
.banner-img-wrap {
width: 100%;
height: 180rpx;
overflow: hidden;
position: relative;
}
.banner-img {
width: 100%;
height: 100%;
display: block;
}
}

View File

@@ -6,7 +6,7 @@
<view :style="themeColor">
<!-- #endif -->
<!-- 顶部图条:位于 navbar 之下、表单卡片之上。宽度 calc(100% - 2*containerInset) 水平居中,
留下与卡片等宽的左右对称留白(默认容器内缩 50rpx ≈ 屏宽 6.7%,即内容宽 87%)。
留下与卡片等宽的左右对称留白(默认容器内缩 30rpx ≈ 屏宽 1.3%,即内容宽 97.3%,与参考图一致)。
图片由后台 form_config.bg_image / bgImage 下发;未配置时不渲染,保持原来的纯白布局。 -->
<view v-if="bgImage" class="formdata-bg" :style="bgLayerStyle"></view>
<!--
@@ -231,13 +231,15 @@ export default {
return raw ? this.$util.img(raw) : '';
},
// 容器左右内缩(rpx)。后台 form_config.container_inset / containerInset 可调;
// 默认 50rpx,在 750rpx 屏宽下左右各留 50rpx ≈ 6.7%,内容宽 ≈ 87%,
// 与参考图一致;CSS .system-form-wrap 中也写了这个默认 padding(防 H5 computed 未及时就绪时也生效)
// 默认 30rpx,在 750rpx 屏宽下左右各留 30rpx ≈ 4%,内容宽 ≈ 92%。
// ⚠️ 改这里才生效:本 computed 的返回值通过 containerStyle 内联样式作用于 .system-form-wrap,
// 内联样式优先级高于 SCSS 类选择器,会覆盖下方 SCSS 里的 padding(SCSS 仅作首屏兜底)。
// ⚠️ 后台优先级最高:若 form_config.containerInset / container_inset 下发了数值,会覆盖此默认值。
containerInset() {
const fc = (this.detail && this.detail.form_config) || {};
const raw = fc.containerInset !== undefined ? fc.containerInset : fc.container_inset;
const n = parseInt(raw);
return isNaN(n) ? 50 : Math.min(150, Math.max(0, n));
return isNaN(n) ? 30 : Math.min(150, Math.max(0, n));
},
// 顶部图条高度(rpx)。后台 form_config.bg_image_height 可调;clamp 80-600
bgImageHeight() {
@@ -993,8 +995,10 @@ page {
overflow: visible;
margin: 0 0 60rpx 0;
/* ===== 表单卡片:唯一保留白底的区域 =====
87% 宽居中 + 16rpx 圆角 + 白底,对应红色框范围(从图条底部到页面底部) */
padding: 0 50rpx;
92% 宽居中(左右各留 30rpx ≈ 4%) + 16rpx 圆角 + 白底,对应红色框范围(从图条底部到页面底部)。
⚠️ 注意:此 padding 仅为首屏兜底(H5 computed 尚未就绪时生效),
运行中会被 containerStyle 内联样式覆盖,实际值由 containerInset computed 决定 */
padding: 0 30rpx;
box-sizing: border-box;
background-color: #ffffff;
border-radius: 16rpx;
@@ -1028,7 +1032,9 @@ page {
overflow: visible;
margin: 0 0 60rpx 0;
// ===== 表单卡片:默认就是「白底圆角、左右内缩居中」(参考图效果),不依赖后台配置 =====
padding: 0 50rpx;
// 左右各留 30rpx(≈ 4% 屏宽),与 H5/MP/APP 端保持一致;后台可通过 form_config.container_inset 调整
// ⚠️ 注意:此 padding 仅为首屏兜底,运行中会被 containerStyle 内联样式覆盖(同 H5/MP/APP 端)
padding: 0 30rpx;
box-sizing: border-box;
background-color: #ffffff;
border-radius: 16rpx;
@@ -1044,7 +1050,7 @@ page {
*/
.form-card {}
// 穿透 diy-form 包装层:消除其自带的 10rpx 圆角与白色背景,
// 穿透 diy-form 包装层:消除其自带的 30rpx 圆角与白色背景,
// 让 form 内容区域保持与原始 ns-newform 接入时一致的视觉
.system-form-wrap ::v-deep .diy-from {
background: transparent;
@@ -1109,11 +1115,11 @@ page {
::v-deep .mescroll-totop {
/* #ifdef H5 */
right: 27rpx !important;
right: 230rpx !important;
bottom: 120rpx !important;
/* #endif */
/* #ifdef MP */
right: 27rpx !important;
right: 230rpx !important;
bottom: 180rpx !important;
/* #endif */
}