feat(form): add captcha and form behavior support
实现表单行为相关功能,新增验证码输入模块,支持表单登录校验、提交次数限制、表单开放状态判断,补充多语言文案,优化空状态展示逻辑
This commit is contained in:
@@ -7,5 +7,18 @@ export const lang = {
|
||||
submitSuccess: 'Submitted successfully',
|
||||
// Form information not available
|
||||
noFormInfo: 'Form information not available',
|
||||
// Behavior settings
|
||||
// Captcha input placeholder
|
||||
captchaPlaceholder: 'Please enter the captcha',
|
||||
// Captcha required
|
||||
captchaRequired: 'Please enter the captcha',
|
||||
// Captcha error
|
||||
captchaError: 'Incorrect captcha, please try again',
|
||||
// Submit limit reached
|
||||
submitLimit: 'Submission limit reached',
|
||||
// Form not open
|
||||
notOpen: 'The form is not open yet',
|
||||
// Login required
|
||||
loginRequired: 'Please log in first',
|
||||
|
||||
}
|
||||
|
||||
@@ -6,4 +6,17 @@ export const lang = {
|
||||
submitSuccess: '提交成功',
|
||||
// 未获取到表单信息
|
||||
noFormInfo: '未获取到表单信息',
|
||||
// 行为设置相关
|
||||
// 请输入验证码
|
||||
captchaPlaceholder: '请输入验证码',
|
||||
// 请输入验证码(校验提示)
|
||||
captchaRequired: '请输入验证码',
|
||||
// 验证码错误
|
||||
captchaError: '验证码错误,请重试',
|
||||
// 提交次数已达上限
|
||||
submitLimit: '提交次数已达上限',
|
||||
// 表单未开放
|
||||
notOpen: '表单未开放',
|
||||
// 请先登录
|
||||
loginRequired: '请先登录',
|
||||
}
|
||||
|
||||
@@ -7,10 +7,15 @@
|
||||
<view class="system-form-wrap">
|
||||
<view class="form-title">{{ $lang('form.form.title') }}</view>
|
||||
<ns-form :data="detail.json_data" :formConfig="detail.form_config" ref="form"></ns-form>
|
||||
<!-- 行为设置:提交验证码 -->
|
||||
<view class="captcha-wrap" v-if="behavior.captcha == 1">
|
||||
<input class="captcha-input" type="text" v-model="captcha.code" :placeholder="$lang('form.form.captchaPlaceholder')" />
|
||||
<image class="captcha-img" :src="captcha.img" mode="aspectFill" @click="getCaptcha()"></image>
|
||||
</view>
|
||||
<button type="primary" size="mini" class="button mini" @click="create()">{{ $lang('common.submit') }}</button>
|
||||
</view>
|
||||
</view>
|
||||
<ns-empty :text="complete ? $lang('form.form.submitSuccess') : $lang('form.form.noFormInfo')" v-else></ns-empty>
|
||||
<ns-empty :text="emptyText" v-else></ns-empty>
|
||||
|
||||
<loading-cover ref="loadingCover"></loading-cover>
|
||||
<ns-login ref="login"></ns-login>
|
||||
@@ -30,9 +35,20 @@
|
||||
isRepeat: false,
|
||||
complete: false,
|
||||
scroll: true,
|
||||
urlParams: {}
|
||||
urlParams: {},
|
||||
// 行为设置(后端 __form_config__.behavior 下发,含默认值)
|
||||
behavior: {},
|
||||
// 非成功状态的空态文案(表单未开放/需登录/加载失败等)
|
||||
formError: '',
|
||||
// 图形验证码(behavior.captcha=1 时展示)
|
||||
captcha: { id: '', img: '', code: '' }
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
emptyText() {
|
||||
return this.complete ? this.$lang('form.form.submitSuccess') : (this.formError || this.$lang('form.form.noFormInfo'));
|
||||
}
|
||||
},
|
||||
onLoad(data) {
|
||||
// #ifdef MP-ALIPAY
|
||||
let options = my.getLaunchOptionsSync();
|
||||
@@ -66,11 +82,7 @@
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
if (!this.storeToken) {
|
||||
this.redirectTologin('/pages_tool/form/form?id=' + this.id);
|
||||
return;
|
||||
}
|
||||
|
||||
// 打开是否需要登录由后端 behavior 决定(info 返回 FORM_LOGIN_REQUIRED 时弹登录)
|
||||
this.getData();
|
||||
},
|
||||
watch: {
|
||||
@@ -88,6 +100,16 @@
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.detail = res.data;
|
||||
this.behavior = (res.data.form_config && res.data.form_config.behavior) || {};
|
||||
if (this.behavior.captcha == 1) this.getCaptcha();
|
||||
} else if (res.message == 'FORM_LOGIN_REQUIRED') {
|
||||
// 打开需登录:弹登录组件,登录成功后 watch storeToken 重新拉取
|
||||
this.$refs.login ? this.$refs.login.open('/pages_tool/form/form?id=' + this.id)
|
||||
: (this.formError = this.$lang('form.form.loginRequired'));
|
||||
} else if (res.message == 'FORM_NOT_OPEN') {
|
||||
this.formError = this.$lang('form.form.notOpen');
|
||||
} else {
|
||||
this.formError = res.message || this.$lang('form.form.noFormInfo');
|
||||
}
|
||||
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
|
||||
},
|
||||
@@ -96,29 +118,90 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
// 图形验证码(点击图片刷新;提交失败后自动刷新)
|
||||
getCaptcha() {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/captcha/captcha',
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.captcha.id = res.data.id;
|
||||
this.captcha.img = res.data.img;
|
||||
this.captcha.code = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 填完跳转:消费统一链接选择器的完整对象(wap_url 外链/页面路径、外部小程序、拨打电话)
|
||||
doRedirect(link) {
|
||||
const fallback = () => { this.complete = true; this.detail = null; };
|
||||
if (!link) return fallback();
|
||||
if (link.appid) {
|
||||
// 跳转其他微信小程序
|
||||
wx.navigateToMiniProgram({ appId: link.appid, path: link.page || '', fail: fallback });
|
||||
} else if (link.mobile) {
|
||||
uni.makePhoneCall({ phoneNumber: String(link.mobile), fail: fallback });
|
||||
fallback();
|
||||
} else if (link.wap_url) {
|
||||
if (/^https?:\/\//i.test(link.wap_url)) {
|
||||
uni.navigateTo({ url: '/pages_tool/webview/webview?src=' + encodeURIComponent(link.wap_url), fail: fallback });
|
||||
} else {
|
||||
uni.navigateTo({ url: link.wap_url, fail: fallback });
|
||||
}
|
||||
} else {
|
||||
fallback();
|
||||
}
|
||||
},
|
||||
create() {
|
||||
if (this.$refs.form.verify()) {
|
||||
if (this.isRepeat) return;
|
||||
this.isRepeat = true;
|
||||
const behavior = this.behavior || {};
|
||||
|
||||
// 填写需登录 / 限填(后端强制,前端提前拦截优化体验)
|
||||
if ((behavior.require_login_submit == 1 || behavior.submit_limit > 0) && !this.storeToken) {
|
||||
this.$refs.login && this.$refs.login.open('/pages_tool/form/form?id=' + this.id);
|
||||
return;
|
||||
}
|
||||
// 验证码必填
|
||||
if (behavior.captcha == 1 && !this.captcha.code) {
|
||||
this.$util.showToast({ title: this.$lang('form.form.captchaRequired') });
|
||||
return;
|
||||
}
|
||||
|
||||
this.isRepeat = true;
|
||||
this.$api.sendRequest({
|
||||
url: '/form/api/form/create',
|
||||
data: {
|
||||
form_id: this.id,
|
||||
form_data: typeof this.$refs.form.formData === 'string' ? this.$refs.form.formData : JSON.stringify(this.$refs.form.formData),
|
||||
url_params: JSON.stringify(this.urlParams),
|
||||
member_id: this.memberInfo ? this.memberInfo.id : 0
|
||||
member_id: this.memberInfo ? this.memberInfo.id : 0,
|
||||
captcha_id: this.captcha.id || '',
|
||||
captcha_code: this.captcha.code || ''
|
||||
},
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
this.$util.showToast({ title: this.$lang('form.form.submitSuccess') })
|
||||
this.$util.showToast({ title: this.$lang('form.form.submitSuccess') });
|
||||
const link = behavior.redirect;
|
||||
setTimeout(() => {
|
||||
this.complete = true;
|
||||
this.detail = null;
|
||||
}, 1500)
|
||||
link ? this.doRedirect(link)
|
||||
: (this.complete = true, this.detail = null);
|
||||
}, link ? 800 : 1500);
|
||||
} else {
|
||||
this.isRepeat = false;
|
||||
this.$util.showToast({ title: res.message })
|
||||
if (res.message == 'FORM_LOGIN_REQUIRED') {
|
||||
this.$refs.login && this.$refs.login.open('/pages_tool/form/form?id=' + this.id);
|
||||
} else if (res.message == 'CAPTCHA_ERROR' || res.message == 'CAPTCHA_FAILURE') {
|
||||
this.$util.showToast({ title: this.$lang('form.form.captchaError') });
|
||||
if (behavior.captcha == 1) this.getCaptcha();
|
||||
} else if (res.message == 'FORM_SUBMIT_LIMIT') {
|
||||
this.$util.showToast({ title: this.$lang('form.form.submitLimit') });
|
||||
this.complete = true;
|
||||
this.detail = null;
|
||||
} else if (res.message == 'FORM_NOT_OPEN') {
|
||||
this.$util.showToast({ title: this.$lang('form.form.notOpen') });
|
||||
} else {
|
||||
this.$util.showToast({ title: res.message });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -153,6 +236,34 @@
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
|
||||
.captcha-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
margin-top: 24rpx;
|
||||
|
||||
.captcha-input {
|
||||
flex: 1;
|
||||
height: 72rpx;
|
||||
line-height: 72rpx;
|
||||
font-size: 28rpx;
|
||||
border: 2rpx solid #e5e7eb;
|
||||
border-radius: 12rpx;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.captcha-img {
|
||||
width: 200rpx;
|
||||
height: 72rpx;
|
||||
margin-left: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
border: 2rpx solid #e5e7eb;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
height: 80rpx;
|
||||
line-height: 80rpx !important;
|
||||
|
||||
@@ -35,7 +35,15 @@
|
||||
<view class="page harmony-page">
|
||||
<scroll-view scroll-y="true" :show-scrollbar="false" class="form-scroll">
|
||||
<view class="system-form-wrap">
|
||||
<diy-form ref="form" :value="diyValue" dataMode="raw" :onSubmit="handleSubmit" />
|
||||
<diy-form ref="form" :value="diyValue" dataMode="raw" :showSubmit="!showCaptcha" :onSubmit="handleSubmit" />
|
||||
<!-- 行为设置:提交验证码开启时,隐藏 diy-form 内置按钮,由本页渲染验证码+提交按钮 -->
|
||||
<view v-if="showCaptcha" class="form-extra-wrap">
|
||||
<view class="captcha-wrap">
|
||||
<input class="captcha-input" type="text" v-model="captcha.code" :placeholder="$lang('form.form.captchaPlaceholder')" />
|
||||
<image class="captcha-img" :src="captcha.img" mode="aspectFill" @click="getCaptcha()"></image>
|
||||
</view>
|
||||
<view class="custom-submit" @click="submitFromPage">{{ submitBtnText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
@@ -44,17 +52,24 @@
|
||||
<view class="page">
|
||||
<view class="system-form-wrap">
|
||||
<!-- 复用 diy-form:banner / tip / 表单字段 / 提交按钮 全部由其内部渲染,样式(bannerPaddingX/tipColor/submitBgColor 等)由 form_config 控制。
|
||||
:onSubmit 接管提交逻辑(带 uniacid + showModal);跨 H5 / MP 一致,不依赖 $listeners。
|
||||
注意:create 重度依赖本组件 this(id/uniacid/memberInfo/$api 等),必须在 created 阶段 bind this,
|
||||
否则 diy-form 通过 this.onSubmit(formData) 调用时 this 会漂移到子组件实例 -->
|
||||
<diy-form ref="form" :value="diyValue" dataMode="raw" :onSubmit="handleSubmit" />
|
||||
:onSubmit 接管提交逻辑(带 uniacid + showModal);跨 H5 / MP 一致,不依赖 $listeners。
|
||||
注意:create 重度依赖本组件 this(id/uniacid/memberInfo/$api 等),必须在 created 阶段 bind this,
|
||||
否则 diy-form 通过 this.onSubmit(formData) 调用时 this 会漂移到子组件实例 -->
|
||||
<diy-form ref="form" :value="diyValue" dataMode="raw" :showSubmit="!showCaptcha" :onSubmit="handleSubmit" />
|
||||
<!-- 行为设置:提交验证码开启时,隐藏 diy-form 内置按钮,由本页渲染验证码+提交按钮 -->
|
||||
<view v-if="showCaptcha" class="form-extra-wrap">
|
||||
<view class="captcha-wrap">
|
||||
<input class="captcha-input" type="text" v-model="captcha.code" :placeholder="$lang('form.form.captchaPlaceholder')" />
|
||||
<image class="captcha-img" :src="captcha.img" mode="aspectFill" @click="getCaptcha()"></image>
|
||||
</view>
|
||||
<view class="custom-submit" @click="submitFromPage">{{ submitBtnText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</block>
|
||||
<block v-else>
|
||||
<ns-empty :text="complete ? $lang('form.formdata.submitSuccess') : $lang('form.formdata.noFormInfo')"
|
||||
:isIndex="false"></ns-empty>
|
||||
<ns-empty :text="emptyText" :isIndex="false"></ns-empty>
|
||||
</block>
|
||||
<loading-cover ref="loadingCover"></loading-cover>
|
||||
<ns-login ref="login"></ns-login>
|
||||
@@ -81,6 +96,14 @@ export default {
|
||||
showHomeBtn: false, // 查询参数 show_home=1 时,在系统标题栏左侧显示 Home 按钮
|
||||
urlParams: {}, // 通用 URL 透传参数收集
|
||||
handleSubmit: null, // create 的 this 绑定版本,作为 :onSubmit 传给 diy-form(见 created)
|
||||
// 行为设置(后端 __form_config__.behavior 下发,含默认值)
|
||||
behavior: {},
|
||||
// 非成功状态的空态文案(表单未开放/需登录/加载失败等)
|
||||
formError: '',
|
||||
// 图形验证码(behavior.captcha=1 时展示,由本页渲染而非 diy-form)
|
||||
captcha: { id: '', img: '', code: '' },
|
||||
// 登录后回跳地址(onLoad 时由原始 options 重建)
|
||||
backUrl: '',
|
||||
|
||||
// #ifndef H5
|
||||
navbarHeight: 44, // 自绘 navbar 内容区高度(不含状态栏),跨端兜底 44px
|
||||
@@ -135,6 +158,19 @@ export default {
|
||||
show_tip: this.detail.show_tip,
|
||||
form_tip: this.detail.form_tip || this.$lang('form.formdata.formTipPlaceholder')
|
||||
}
|
||||
},
|
||||
// 行为设置:提交验证码开启时 diy-form 隐藏内置提交按钮,本页渲染验证码 + 自有提交按钮
|
||||
showCaptcha() {
|
||||
return this.behavior.captcha == 1;
|
||||
},
|
||||
// 自有提交按钮文案:跟随表单配置的提交按钮文字(form_config 为 camelCase)
|
||||
submitBtnText() {
|
||||
return (this.detail && this.detail.form_config && this.detail.form_config.submitText) || this.$lang('common.submit');
|
||||
},
|
||||
// 空状态文案:提交成功 / 表单未开放 / 需登录 / 加载失败
|
||||
emptyText() {
|
||||
return this.complete ? this.$lang('form.formdata.submitSuccess')
|
||||
: (this.formError || this.$lang('form.formdata.noFormInfo'));
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
@@ -217,7 +253,15 @@ export default {
|
||||
if (navbar) navbar.style.display = 'none'
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
// #endif
|
||||
|
||||
// 登录后回跳地址:由原始 options 重建(供 FORM_LOGIN_REQUIRED 时 ns-login 使用)
|
||||
const backQuery = [];
|
||||
for (let key in options) {
|
||||
if (key === 'scene') continue;
|
||||
backQuery.push(key + '=' + encodeURIComponent(options[key]));
|
||||
}
|
||||
this.backUrl = '/pages_tool/form/formdata' + (backQuery.length ? '?' + backQuery.join('&') : '');
|
||||
|
||||
this.getData()
|
||||
},
|
||||
@@ -256,6 +300,17 @@ export default {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.detail = res.data
|
||||
this.updateNavbarTitle();
|
||||
// 行为设置(后端已合并默认值):验证码开启时拉取图形验证码
|
||||
this.behavior = (res.data.form_config && res.data.form_config.behavior) || {}
|
||||
if (this.behavior.captcha == 1) this.getCaptcha()
|
||||
} else if (res.message == 'FORM_LOGIN_REQUIRED') {
|
||||
// 打开需登录:弹登录组件,登录成功后 watch storeToken 重新拉取
|
||||
this.$refs.login ? this.$refs.login.open(this.backUrl)
|
||||
: (this.formError = this.$lang('form.form.loginRequired'))
|
||||
} else if (res.message == 'FORM_NOT_OPEN') {
|
||||
this.formError = this.$lang('form.form.notOpen')
|
||||
} else {
|
||||
this.formError = res.message || ''
|
||||
}
|
||||
this.$refs.loadingCover && this.$refs.loadingCover.hide()
|
||||
},
|
||||
@@ -282,6 +337,50 @@ export default {
|
||||
this.navbarTitle = formName;
|
||||
// #endif
|
||||
},
|
||||
// 图形验证码(点击图片刷新;提交失败后自动刷新)
|
||||
getCaptcha() {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/captcha/captcha',
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.captcha.id = res.data.id
|
||||
this.captcha.img = res.data.img
|
||||
this.captcha.code = ''
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 验证码模式下本页自有提交按钮:先走 diy-form 校验与取数,再进 create
|
||||
submitFromPage() {
|
||||
if (this.isRepeat) return;
|
||||
if (!this.$refs.form || !this.$refs.form.verify()) return;
|
||||
const formData = this.$refs.form.getFormData();
|
||||
this.create(formData);
|
||||
},
|
||||
// 填完跳转:消费统一链接选择器的完整对象(wap_url 外链/页面路径、外部小程序、拨打电话)
|
||||
doRedirect(link) {
|
||||
const fallback = () => { this.complete = true; this.detail = null; };
|
||||
if (!link) return fallback();
|
||||
if (link.appid) {
|
||||
// 跳转其他微信小程序(仅小程序端可用;H5 场景直接回退完成态)
|
||||
// #ifdef MP-WEIXIN
|
||||
wx.navigateToMiniProgram({ appId: link.appid, path: link.page || '', fail: fallback });
|
||||
return;
|
||||
// #endif
|
||||
fallback();
|
||||
} else if (link.mobile) {
|
||||
uni.makePhoneCall({ phoneNumber: String(link.mobile), fail: fallback });
|
||||
fallback();
|
||||
} else if (link.wap_url) {
|
||||
if (/^https?:\/\//i.test(link.wap_url)) {
|
||||
uni.navigateTo({ url: '/pages_tool/webview/webview?src=' + encodeURIComponent(link.wap_url), fail: fallback });
|
||||
} else {
|
||||
uni.navigateTo({ url: link.wap_url, fail: fallback });
|
||||
}
|
||||
} else {
|
||||
fallback();
|
||||
}
|
||||
},
|
||||
// 由 diy-form 内置提交按钮触发:diy-form handleSubmit 已先做 verify(),
|
||||
// 仅在通过时才通过 :onSubmit 函数 prop 调用本方法(跨 H5 / MP 一致,不走 $emit / $listeners)。
|
||||
// 注意:本方法通过 created 中 this.handleSubmit = this.create.bind(this) 预绑定 this,
|
||||
@@ -290,6 +389,18 @@ export default {
|
||||
// 防重复提交:console 在拦截之前,避免日志噪声;拦截后立即置位
|
||||
if (this.isRepeat) return;
|
||||
|
||||
const behavior = this.behavior || {};
|
||||
// 填写需登录 / 限填(后端强制,前端提前拦截优化体验)
|
||||
if ((behavior.require_login_submit == 1 || behavior.submit_limit > 0) && !this.storeToken) {
|
||||
this.$refs.login && this.$refs.login.open(this.backUrl);
|
||||
return;
|
||||
}
|
||||
// 验证码必填
|
||||
if (behavior.captcha == 1 && !this.captcha.code) {
|
||||
this.$util.showToast({ title: this.$lang('form.form.captchaRequired') });
|
||||
return;
|
||||
}
|
||||
|
||||
this.isRepeat = true;
|
||||
this.$api.sendRequest({
|
||||
url: '/form/api/form/create',
|
||||
@@ -298,22 +409,42 @@ export default {
|
||||
form_data: typeof formData === 'string' ? formData : JSON.stringify(formData),
|
||||
uniacid: this.uniacid,
|
||||
url_params: JSON.stringify(this.urlParams),
|
||||
member_id: this.memberInfo ? this.memberInfo.id : 0
|
||||
member_id: this.memberInfo ? this.memberInfo.id : 0,
|
||||
captcha_id: this.captcha.id || '',
|
||||
captcha_code: this.captcha.code || ''
|
||||
},
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
this.complete = true
|
||||
uni.showModal({
|
||||
title: this.$lang('form.formdata.tip'),
|
||||
content: this.$lang('form.formdata.submitSuccess'),
|
||||
showCancel: false,
|
||||
success: () => { }
|
||||
})
|
||||
const link = behavior.redirect;
|
||||
if (link) {
|
||||
this.$util.showToast({ title: this.$lang('form.formdata.submitSuccess') });
|
||||
setTimeout(() => this.doRedirect(link), 800);
|
||||
} else {
|
||||
this.complete = true
|
||||
uni.showModal({
|
||||
title: this.$lang('form.formdata.tip'),
|
||||
content: this.$lang('form.formdata.submitSuccess'),
|
||||
showCancel: false,
|
||||
success: () => { }
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.isRepeat = false
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
})
|
||||
if (res.message == 'FORM_LOGIN_REQUIRED') {
|
||||
this.$refs.login && this.$refs.login.open(this.backUrl)
|
||||
} else if (res.message == 'CAPTCHA_ERROR' || res.message == 'CAPTCHA_FAILURE') {
|
||||
this.$util.showToast({ title: this.$lang('form.form.captchaError') })
|
||||
if (behavior.captcha == 1) this.getCaptcha()
|
||||
} else if (res.message == 'FORM_SUBMIT_LIMIT') {
|
||||
this.$util.showToast({ title: this.$lang('form.form.submitLimit') })
|
||||
this.complete = true
|
||||
} else if (res.message == 'FORM_NOT_OPEN') {
|
||||
this.$util.showToast({ title: this.$lang('form.form.notOpen') })
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
@@ -490,6 +621,48 @@ page {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
// ===== 行为设置:验证码行 + 自有提交按钮(diy-form 内置按钮被 showSubmit=false 隐藏时接管) =====
|
||||
.form-extra-wrap {
|
||||
padding: 0 28rpx 20rpx;
|
||||
}
|
||||
.captcha-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
margin-top: 24rpx;
|
||||
|
||||
.captcha-input {
|
||||
flex: 1;
|
||||
height: 72rpx;
|
||||
line-height: 72rpx;
|
||||
font-size: 28rpx;
|
||||
border: 2rpx solid #e5e7eb;
|
||||
border-radius: 12rpx;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.captcha-img {
|
||||
width: 200rpx;
|
||||
height: 72rpx;
|
||||
margin-left: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
border: 2rpx solid #e5e7eb;
|
||||
}
|
||||
}
|
||||
// 提交按钮:视觉对齐 diy-form 内置按钮(红底白字圆角,medium 内边距)
|
||||
.custom-submit {
|
||||
margin-top: 30rpx;
|
||||
padding: 24rpx 0;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
background-color: #ff4544;
|
||||
border-radius: 12rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
::v-deep .mescroll-totop {
|
||||
/* #ifdef H5 */
|
||||
right: 27rpx !important;
|
||||
|
||||
Reference in New Issue
Block a user