1. 新增diy-form组件的raw数据源模式,支持直接透传ns-newform格式的表单数据 2. 新增showSubmit配置项,支持隐藏内置提交按钮由父页面自行实现提交逻辑 3. 暴露verify和getFormData方法供父组件调用 4. 替换pages_tool/form/formdata.vue的旧表单组件为diy-form,适配新的调用方式 5. 新增样式穿透修复diy-form默认样式与原有页面风格不一致的问题
254 lines
5.9 KiB
Vue
254 lines
5.9 KiB
Vue
<template>
|
||
<view :style="themeColor">
|
||
<block v-if="detail">
|
||
<view class="page">
|
||
<view class="form-banner" v-if="detail.show_banner > 0">
|
||
<image :src="$util.img(formBanner)" mode="widthFix"></image>
|
||
</view>
|
||
<view class="form-tip">
|
||
<view class="system-form-tip" v-if="detail.show_tip > 0">{{ formTip }}</view>
|
||
</view>
|
||
<view class="system-form-wrap">
|
||
<!-- 复用 diy-form 渲染表单字段:raw 模式直接透传 detail.json_data,隐藏内置 banner/tip/提交按钮(页面自己渲染) -->
|
||
<diy-form
|
||
ref="form"
|
||
:value="diyValue"
|
||
dataMode="raw"
|
||
:showSubmit="false"
|
||
/>
|
||
<button class="button mini" style="font-size:32rpx;" type="primary" size="mini"
|
||
@click="create">提交</button>
|
||
</view>
|
||
</view>
|
||
</block>
|
||
<block v-else>
|
||
<ns-empty :text="complete ? '提交成功' : '未获取到表单信息'" :isIndex="false"></ns-empty>
|
||
</block>
|
||
<loading-cover ref="loadingCover"></loading-cover>
|
||
<ns-login ref="login"></ns-login>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
|
||
import diyForm from '@/components-diy/diy-form.vue';
|
||
|
||
export default {
|
||
components: {
|
||
diyForm
|
||
},
|
||
data() {
|
||
return {
|
||
id: 0,
|
||
detail: null,
|
||
isRepeat: false,
|
||
complete: false,
|
||
scroll: true,
|
||
uniacid: 0,
|
||
isFromMpWebView: false, // 是否是从微信小程序的WebView跳转过来的
|
||
|
||
// #ifdef H5
|
||
formTitle: '', // 查询参数传入的Title
|
||
enableSetTitle: false, // 查询参数传入的是否可以强制设置Title
|
||
// #endif
|
||
}
|
||
},
|
||
computed: {
|
||
formBanner() {
|
||
const bannerImg = this.detail?.form_banner
|
||
return bannerImg ? bannerImg : 'public/uniapp/form/banner.png'
|
||
},
|
||
formTip() {
|
||
const tip = this.detail?.form_tip
|
||
console.log('formTip computed, tip value:', tip, 'truthy:', !!tip)
|
||
return tip ? tip : '请填写表单所需信息'
|
||
},
|
||
// 构造 diy-form raw 模式期望的 value 形态:
|
||
// - jsonData:透传给 ns-newform(已是 ns-newform 期望的 [{ controller, value, val }])
|
||
// - formConfig:snake_case 表单配置,diy-form 内部 mergedFormConfig 会做 camelCase 转换
|
||
// - 不传 show_banner / show_tip:让 diy-form 自带的 banner/tip 不渲染(页面已自渲染)
|
||
// 注:本 computed 只在 <block v-if="detail"> 内被消费,无需 null 守卫
|
||
diyValue() {
|
||
return {
|
||
jsonData: this.detail.json_data,
|
||
formConfig: this.detail.form_config
|
||
}
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
if (!options.uniacid) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '参数错误',
|
||
showCancel: false,
|
||
success: () => { }
|
||
})
|
||
return false
|
||
}
|
||
|
||
uni.setStorageSync('skipPrivacyCheck', true);
|
||
|
||
// #ifdef H5
|
||
this.formTitle = options?.title ?? '';
|
||
this.enableSetTitle = options?.enable_set_title == 1;
|
||
// #endif
|
||
|
||
this.uniacid = options.uniacid
|
||
this.id = options.id || 0
|
||
this.isFromMpWebView = options.from === 'mp-webview';
|
||
|
||
if (options.scene) {
|
||
const scene = decodeURIComponent(options.scene)
|
||
const params = scene.split('&')
|
||
params.length && params.forEach(item => {
|
||
if (item.indexOf('id') != -1) {
|
||
this.id = item.split('-')[1]
|
||
}
|
||
})
|
||
}
|
||
|
||
// #ifdef H5
|
||
if (this.isFromMpWebView) {
|
||
this.$nextTick(() => {
|
||
const navbar = document.querySelector('uni-page-head')
|
||
if (navbar) navbar.style.display = 'none'
|
||
})
|
||
}
|
||
// #endif
|
||
|
||
this.getData()
|
||
},
|
||
|
||
watch: {
|
||
storeToken(newVal, oldVal) {
|
||
newVal && this.getData()
|
||
}
|
||
},
|
||
onShow() {
|
||
this.updateNavbarTitle();
|
||
},
|
||
methods: {
|
||
getData() {
|
||
this.$api.sendRequest({
|
||
url: '/form/api/form/info',
|
||
data: {
|
||
form_id: this.id,
|
||
uniacid: this.uniacid
|
||
},
|
||
success: res => {
|
||
if (res.code == 0 && res.data) {
|
||
this.detail = res.data
|
||
console.log(`form data =>`, this.detail)
|
||
this.updateNavbarTitle();
|
||
}
|
||
this.$refs.loadingCover && this.$refs.loadingCover.hide()
|
||
},
|
||
fail: () => {
|
||
this.$refs.loadingCover && this.$refs.loadingCover.hide()
|
||
}
|
||
})
|
||
},
|
||
updateNavbarTitle() {
|
||
if (!this.detail?.form_name) return;
|
||
let formName = this.detail.form_name;
|
||
// #ifdef H5
|
||
if (this.enableSetTitle && this.formTitle) {
|
||
formName = this.formTitle;
|
||
}
|
||
// #endif
|
||
uni.setNavigationBarTitle({ title: formName });
|
||
},
|
||
create() {
|
||
// 校验(ns-newform 校验失败时会内部 toast;返回 false 表示失败)
|
||
if (!this.$refs.form.verify()) return
|
||
|
||
if (this.isRepeat) return
|
||
|
||
this.isRepeat = true
|
||
this.$api.sendRequest({
|
||
url: '/form/api/form/create',
|
||
data: {
|
||
form_id: this.id,
|
||
form_data: JSON.stringify(this.$refs.form.getFormData()),
|
||
uniacid: this.uniacid
|
||
},
|
||
success: res => {
|
||
if (res.code == 0) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '提交成功',
|
||
showCancel: false,
|
||
success: () => { }
|
||
})
|
||
} else {
|
||
this.isRepeat = false
|
||
this.$util.showToast({
|
||
title: res.message
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
page {
|
||
background: #fff;
|
||
}
|
||
|
||
.form-banner {
|
||
width: 100vw;
|
||
line-height: 1;
|
||
}
|
||
|
||
.form-banner image {
|
||
width: 100%;
|
||
line-height: 1;
|
||
}
|
||
|
||
.form-tip {
|
||
text-align: center;
|
||
}
|
||
|
||
.system-form-tip {
|
||
line-height: 120rpx;
|
||
font-weight: 600;
|
||
font-size: 30rpx;
|
||
}
|
||
|
||
.system-form-wrap {
|
||
border-radius: 32rpx;
|
||
overflow: hidden;
|
||
margin: 0 0 60rpx 0;
|
||
padding: 0 12rpx;
|
||
padding-top: 40rpx;
|
||
transform: translateY(-40rpx);
|
||
}
|
||
|
||
.system-form-wrap .button {
|
||
height: 80rpx;
|
||
line-height: 80rpx !important;
|
||
margin-top: 30rpx !important;
|
||
width: 84%;
|
||
margin-left: 28rpx !important;
|
||
border-radius: 80rpx;
|
||
background: #f4391c;
|
||
color: #fff;
|
||
}
|
||
|
||
.system-form-wrap .form-wrap {
|
||
background: #fff;
|
||
padding: 30rpx;
|
||
border-radius: 32rpx;
|
||
}
|
||
|
||
// 穿透 diy-form 包装层:消除其自带的 10rpx 圆角与白色背景,
|
||
// 让 form 内容区域保持与原始 ns-newform 接入时一致的视觉
|
||
.system-form-wrap ::v-deep .diy-from {
|
||
background: transparent;
|
||
border-radius: 0;
|
||
}
|
||
</style>
|