mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2025-12-13 18:12:49 +00:00
up
This commit is contained in:
parent
962288cc81
commit
982213b49a
59
uni-app/src/addon/components/diy-form-detail/index.vue
Normal file
59
uni-app/src/addon/components/diy-form-detail/index.vue
Normal file
@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<view :style="themeColor()">
|
||||
<view v-show="!loading" class="diy-template-wrap">
|
||||
<diy-group ref="diyGroupRef" :data="diyFormData" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import diyGroup from '@/addon/components/diy/group/index.vue'
|
||||
import { getFormRecord } from '@/app/api/diy_form';
|
||||
|
||||
const props = defineProps(['record_id','completeLayout']);
|
||||
const emits = defineEmits(['callback'])
|
||||
|
||||
const loading = ref(true);
|
||||
|
||||
const diyFormData: any = reactive({
|
||||
global: {},
|
||||
value: []
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getFormRecord({
|
||||
record_id: props.record_id
|
||||
}).then((res: any) => {
|
||||
diyFormData.global.completeLayout = props.completeLayout || 'style-1';
|
||||
if (res.data.recordsFieldList) {
|
||||
|
||||
res.data.recordsFieldList.forEach((item: any) => {
|
||||
let comp = {
|
||||
id: item.field_key,
|
||||
componentName: item.field_type,
|
||||
pageStyle: '',
|
||||
viewFormDetail: true, // 查看表单详情标识
|
||||
field: {
|
||||
name: item.field_name,
|
||||
value: item.handle_field_value,
|
||||
required: item.field_required,
|
||||
unique: item.field_unique,
|
||||
privacyProtection: item.privacy_protection,
|
||||
},
|
||||
margin: {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
both: 0
|
||||
}
|
||||
};
|
||||
diyFormData.value.push(comp);
|
||||
})
|
||||
}
|
||||
emits('callback', res.data.recordsFieldList)
|
||||
loading.value = false;
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
emits('callback', [])
|
||||
})
|
||||
})
|
||||
</script>
|
||||
191
uni-app/src/addon/components/diy-form/index.vue
Normal file
191
uni-app/src/addon/components/diy-form/index.vue
Normal file
@ -0,0 +1,191 @@
|
||||
<template>
|
||||
<view :style="themeColor()">
|
||||
<!-- 自定义组件渲染 -->
|
||||
<view v-show="requestData.status == 1 && !diy.getLoading()" class="diy-template-wrap">
|
||||
<diy-group ref="diyGroupRef" :data="diyFormData" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue';
|
||||
import { useDiyForm } from '@/hooks/useDiyForm'
|
||||
import { deepClone,getValidTime } from '@/utils/common'
|
||||
import diyGroup from '@/addon/components/diy/group/index.vue'
|
||||
|
||||
const props = defineProps(['form_id', 'relate_id', 'storage_name', 'form_border']);
|
||||
|
||||
const diy = useDiyForm({
|
||||
form_id: props.form_id,
|
||||
needLogin: false // 不检测登录,调用业务自行处理
|
||||
})
|
||||
|
||||
const diyGroupRef = ref(null)
|
||||
|
||||
const requestData = computed(() => {
|
||||
return diy.requestData;
|
||||
})
|
||||
|
||||
const diyFormData: any = reactive({})
|
||||
|
||||
onMounted(() => {
|
||||
diy.getData(() => {
|
||||
diyFormData.status = diy.data.status;
|
||||
if (diyFormData.status) {
|
||||
diyFormData.title = diy.data.title;
|
||||
diyFormData.global = diy.data.global;
|
||||
if (diyFormData.global) {
|
||||
diyFormData.global.topStatusBar.isShow = false; // 顶部导航栏强制隐藏
|
||||
diyFormData.global.bottomTabBarSwitch = false; // 底部导航强制隐藏
|
||||
}
|
||||
let value: any = [];
|
||||
if(props.form_border == 'none'){
|
||||
diyFormData.global.borderControl = false;
|
||||
}
|
||||
// 需要过滤 组件类型,筛选出来表单,排除表单提交组件
|
||||
diy.data.value.forEach((item: any) => {
|
||||
if (item.componentType == 'diy_form' && item.componentName != 'FormSubmit') {
|
||||
value.push(item);
|
||||
}
|
||||
})
|
||||
diyFormData.value = value;
|
||||
diyFormData.componentRefs = null;
|
||||
diyGroupRef.value?.refresh();
|
||||
watchFormData();
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const watchFormData = () => {
|
||||
watch(
|
||||
() => diyFormData.value,
|
||||
(newValue, oldValue) => {
|
||||
if (newValue) {
|
||||
let formData: any = {
|
||||
validTime: getValidTime(5), // 缓存数据有效期为5分钟
|
||||
components: []
|
||||
};
|
||||
newValue.forEach((item: any) => {
|
||||
// 只存表单组件
|
||||
if (item.componentType == 'diy_form' && item.componentName != 'FormSubmit') {
|
||||
// 只存储表单数据,压缩存储空间
|
||||
let field = deepClone(item.field);
|
||||
// 移除不需要存储的数据
|
||||
delete field.remark; // 字段说明
|
||||
delete field.detailComponent; // 用于详情展示
|
||||
delete field.default; // 默认值
|
||||
formData.components.push({
|
||||
id: item.id,
|
||||
componentName: item.componentName,
|
||||
componentType: item.componentType,
|
||||
componentTitle: item.componentTitle,
|
||||
isHidden: item.isHidden,
|
||||
field: field
|
||||
})
|
||||
}
|
||||
})
|
||||
if (formData.components.length) {
|
||||
uni.setStorageSync('diyFormStorage_' + props.form_id, formData)
|
||||
}
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
}
|
||||
|
||||
const verify = () => {
|
||||
if(!diyFormData.status) return true;
|
||||
if(!diyFormData.value) return true;
|
||||
let allPass = true; // 是否全部通过验证
|
||||
|
||||
let componentRefs = diyGroupRef.value.getFormRef().componentRefs;
|
||||
|
||||
// 需要过滤 组件类型,筛选出来表单
|
||||
for (let i = 0; i < diyFormData.value.length; i++) {
|
||||
let item = diyFormData.value[i];
|
||||
if (item.field.required || item.field.value) {
|
||||
let refKey = `diy${ item.componentName }Ref`;
|
||||
let isBreak = false;
|
||||
if (componentRefs[refKey]) {
|
||||
for (let k = 0; k < componentRefs[refKey].length; k++) {
|
||||
let compRef = componentRefs[refKey][k];
|
||||
let verify = compRef.verify(); // 验证表单组件数据
|
||||
if (verify && !verify.code) {
|
||||
isBreak = true;
|
||||
uni.showToast({
|
||||
title: verify.message,
|
||||
icon: 'none'
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (isBreak) {
|
||||
allPass = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!allPass) return false;
|
||||
|
||||
const data = {
|
||||
form_id: props.form_id,
|
||||
value: uni.getStorageSync('diyFormStorage_' + props.form_id),
|
||||
relate_id: props.relate_id || 0 // 关联业务id
|
||||
}
|
||||
if (props.storage_name) {
|
||||
uni.setStorageSync(props.storage_name, data)
|
||||
}
|
||||
return allPass;
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
const getData = ()=> {
|
||||
return {
|
||||
form_id: props.form_id,
|
||||
value: diyFormData.value,
|
||||
relate_id: props.relate_id || 0 // 关联业务id
|
||||
}
|
||||
}
|
||||
|
||||
const clearStorage = (keys: any=[]) => {
|
||||
uni.removeStorageSync('diyFormStorage_' + props.form_id)
|
||||
if (props.storage_name) uni.removeStorageSync(props.storage_name)
|
||||
if(keys) {
|
||||
keys.forEach((key: any) => {
|
||||
uni.removeStorageSync(key)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 监听页面隐藏
|
||||
diy.onHide();
|
||||
|
||||
// 监听页面卸载
|
||||
diy.onUnload();
|
||||
|
||||
// 监听滚动事件
|
||||
// diy.onPageScroll()
|
||||
|
||||
defineExpose({
|
||||
verify,
|
||||
getData,
|
||||
clearStorage
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.diy-template-wrap {
|
||||
/* #ifdef MP */
|
||||
.child-diy-template-wrap {
|
||||
::v-deep .diy-group {
|
||||
> .draggable-element.top-fixed-diy {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
||||
@ -8,53 +8,113 @@
|
||||
<view v-if="diyGroup.isShowPlaceHolder(index,component)" class="absolute w-full z-1" :style="{ height : (component.margin.top * 2 * -1) + 'rpx' }" @click.stop="diyGroup.placeholderEvent"></view>
|
||||
|
||||
<template v-if="component.componentName == 'GraphicNav'">
|
||||
<diy-graphic-nav :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-graphic-nav :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'HorzBlank'">
|
||||
<diy-horz-blank :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-horz-blank :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'HorzLine'">
|
||||
<diy-horz-line :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-horz-line :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'HotArea'">
|
||||
<diy-hot-area :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-hot-area :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'ImageAds'">
|
||||
<diy-image-ads :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-image-ads :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'MemberInfo'">
|
||||
<diy-member-info :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-member-info :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'MemberLevel'">
|
||||
<diy-member-level :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-member-level :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'Notice'">
|
||||
<diy-notice :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-notice :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'RubikCube'">
|
||||
<diy-rubik-cube :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-rubik-cube :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'Text'">
|
||||
<diy-text :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-text :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'RichText'">
|
||||
<diy-rich-text :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount"/>
|
||||
<diy-rich-text :component="component" :global="data.global" :index="index"/>
|
||||
</template>
|
||||
<template v-if="component.componentName == 'ActiveCube'">
|
||||
<diy-active-cube :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount"/>
|
||||
<diy-active-cube :component="component" :global="data.global" :index="index"/>
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FloatBtn'">
|
||||
<diy-float-btn :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount"/>
|
||||
<diy-float-btn :component="component" :global="data.global" :index="index"/>
|
||||
</template>
|
||||
<template v-if="component.componentName == 'CarouselSearch'">
|
||||
<diy-carousel-search :scrollBool="diyGroup.componentsScrollBool.CarouselSearch" :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
<diy-carousel-search :scrollBool="diyGroup.componentsScrollBool.CarouselSearch" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'PictureShow'">
|
||||
<diy-picture-show :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormSubmit'">
|
||||
<diy-form-submit :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormInput'">
|
||||
<diy-form-input ref="diyFormInputRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormTextarea'">
|
||||
<diy-form-textarea ref="diyFormTextareaRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormIdentity'">
|
||||
<diy-form-identity ref="diyFormIdentityRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormEmail'">
|
||||
<diy-form-email ref="diyFormEmailRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormMobile'">
|
||||
<diy-form-mobile ref="diyFormMobileRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormWechatName'">
|
||||
<diy-form-wechat-name ref="diyFormWechatNameRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormNumber'">
|
||||
<diy-form-number ref="diyFormNumberRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormRadio'">
|
||||
<diy-form-radio ref="diyFormRadioRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormCheckbox'">
|
||||
<diy-form-checkbox ref="diyFormCheckboxRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormTable'">
|
||||
<diy-form-table ref="diyFormTableRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormDate'">
|
||||
<diy-form-date ref="diyFormDateRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormDateScope'">
|
||||
<diy-form-date-scope ref="diyFormDateScopeRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormTime'">
|
||||
<diy-form-time ref="diyFormTimeRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormTimeScope'">
|
||||
<diy-form-time-scope ref="diyFormTimeScopeRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormLocation'">
|
||||
<diy-form-location ref="diyFormLocationRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormAddress'">
|
||||
<diy-form-address ref="diyFormAddressRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormImage'">
|
||||
<diy-form-image ref="diyFormImageRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormVideo'">
|
||||
<diy-form-video ref="diyFormVideoRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'FormFile'">
|
||||
<diy-form-file ref="diyFormFileRef" :component="component" :global="data.global" :index="index" />
|
||||
</template>
|
||||
<template v-if="component.componentName == 'PictureShow'">
|
||||
<diy-picture-show :component="component" :global="data.global" :index="index" :pullDownRefreshCount="props.pullDownRefreshCount" />
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
<template v-if="diyStore.mode == '' && data.global.bottomTabBarSwitch">
|
||||
<template v-if="diyStore.mode == '' && data.global && data.global.bottomTabBarSwitch">
|
||||
<view class="pt-[20rpx]"></view>
|
||||
<tabbar />
|
||||
</template>
|
||||
@ -65,19 +125,22 @@
|
||||
|
||||
import { useDiyGroup } from './useDiyGroup'
|
||||
import useDiyStore from '@/app/stores/diy';
|
||||
import { ref } from 'vue';
|
||||
import { ref,getCurrentInstance } from 'vue';
|
||||
|
||||
const props = defineProps(['data', 'pullDownRefreshCount']);
|
||||
const props = defineProps(['data']);
|
||||
|
||||
const instance: any = getCurrentInstance();
|
||||
const getFormRef = () => {
|
||||
return {
|
||||
componentRefs: instance.refs
|
||||
}
|
||||
}
|
||||
|
||||
const topTabbarRef = ref(null);
|
||||
const diyStore = useDiyStore();
|
||||
|
||||
const diyGroup = useDiyGroup({
|
||||
...props,
|
||||
getFormRef() {
|
||||
return {
|
||||
topTabbarRef: topTabbarRef.value
|
||||
}
|
||||
}
|
||||
getFormRef
|
||||
});
|
||||
|
||||
const data = ref(diyGroup.data)
|
||||
@ -89,7 +152,8 @@
|
||||
diyGroup.onPageScroll()
|
||||
|
||||
defineExpose({
|
||||
refresh: diyGroup.refresh
|
||||
refresh: diyGroup.refresh,
|
||||
getFormRef
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -34,9 +34,9 @@ export function useDiyGroup(params: any = {}) {
|
||||
} else {
|
||||
obj['draggable-element'] = true;
|
||||
}
|
||||
if(component.componentName == 'ImageAds'){
|
||||
obj['overflow-hidden'] = true
|
||||
}
|
||||
if (component.componentName == 'ImageAds') {
|
||||
obj['overflow-hidden'] = true
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -92,13 +92,13 @@ export function useDiyGroup(params: any = {}) {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
|
||||
// 初始化组件滚动值
|
||||
scrollVal = uni.getStorageSync('componentsScrollValGroup');
|
||||
if (scrollVal) {
|
||||
for (let key in scrollVal) {
|
||||
componentsScrollBool.value[key] = -1;
|
||||
}
|
||||
}
|
||||
// 初始化组件滚动值
|
||||
scrollVal = uni.getStorageSync('componentsScrollValGroup');
|
||||
if (scrollVal) {
|
||||
for (let key in scrollVal) {
|
||||
componentsScrollBool.value[key] = -1;
|
||||
}
|
||||
}
|
||||
}, 500)
|
||||
});
|
||||
});
|
||||
@ -106,9 +106,35 @@ export function useDiyGroup(params: any = {}) {
|
||||
|
||||
// 页面onShow调用时,也会触发改方法
|
||||
const refresh = () => {
|
||||
|
||||
nextTick(() => {
|
||||
params.getFormRef().topTabbarRef?.refresh();
|
||||
let time: any = null;
|
||||
let fn = () => {
|
||||
diyStore.componentRefs = params.getFormRef().componentRefs;
|
||||
data.value.componentRefs = params.getFormRef().componentRefs;
|
||||
params.getFormRef().componentRefs.topTabbarRef?.refresh();
|
||||
if (time) clearInterval(time);
|
||||
}
|
||||
|
||||
let getPass = () => {
|
||||
let pass = false;
|
||||
try {
|
||||
params.getFormRef()
|
||||
pass = true;
|
||||
} catch (e) {
|
||||
pass = false;
|
||||
}
|
||||
if (pass) {
|
||||
fn();
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
if (!getPass()) {
|
||||
time = setInterval(() => {
|
||||
getPass()
|
||||
}, 100)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<view class="fixed-group">
|
||||
<template v-if="props.data.global.component == 'demo-index'">
|
||||
<fixed-demo-index :data="props.data" :pullDownRefreshCount="props.pullDownRefreshCount"></fixed-demo-index>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
const props = defineProps(['data','pullDownRefreshCount']);
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
@ -1,8 +0,0 @@
|
||||
<template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user