feat: 优化编辑页模块和配置结构
This commit is contained in:
parent
ba418c5cd7
commit
310fe0d325
@ -8,7 +8,6 @@ export const replacePxWithRem = (html) => {
|
|||||||
const imgRegex = /<img[^>]*style=["'][^"']*\b(?:width|height):\s*\d+(\.\d+)?px[^"']*["'][^>]*>/gi
|
const imgRegex = /<img[^>]*style=["'][^"']*\b(?:width|height):\s*\d+(\.\d+)?px[^"']*["'][^>]*>/gi
|
||||||
const styleRegex = /style="([^"]*)"/g
|
const styleRegex = /style="([^"]*)"/g
|
||||||
if (!imgRegex.test(html)) {
|
if (!imgRegex.test(html)) {
|
||||||
console.log('无需修改')
|
|
||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
export default [
|
|
||||||
{
|
|
||||||
label: '顶部图片地址',
|
|
||||||
type: 'InputSetter',
|
|
||||||
key: 'bgImage',
|
|
||||||
labelStyle: { width: '120px' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '顶部视频地址',
|
|
||||||
type: 'InputSetter',
|
|
||||||
key: 'videoLink',
|
|
||||||
labelStyle: { width: '120px' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '视频海报地址',
|
|
||||||
type: 'InputSetter',
|
|
||||||
key: 'postImg',
|
|
||||||
labelStyle: { width: '120px' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '图片支持点击',
|
|
||||||
type: 'CustomedSwitch',
|
|
||||||
labelStyle: { width: '120px' },
|
|
||||||
key: 'bgImageAllowJump'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '跳转链接',
|
|
||||||
type: 'InputSetter',
|
|
||||||
labelStyle: { width: '120px' },
|
|
||||||
key: 'bgImageJumpLink',
|
|
||||||
relyFunc: (data) => {
|
|
||||||
return !!data?.bgImageAllowJump
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,16 +0,0 @@
|
|||||||
export default [
|
|
||||||
{
|
|
||||||
label: '自定义Logo',
|
|
||||||
type: 'InputSetter',
|
|
||||||
key: 'logoImage',
|
|
||||||
tip: '默认尺寸200px*50px',
|
|
||||||
labelStyle: { width: '120px' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Logo大小',
|
|
||||||
type: 'InputPercent',
|
|
||||||
key: 'logoImageWidth',
|
|
||||||
tip: '填写宽度百分比,例如30%',
|
|
||||||
labelStyle: { width: '120px' }
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,48 +0,0 @@
|
|||||||
import bannerConfig from './bannerConfig'
|
|
||||||
import logoConfig from './logoConfig'
|
|
||||||
|
|
||||||
export default [
|
|
||||||
{
|
|
||||||
name: '头图',
|
|
||||||
key: 'bannerConf.bannerConfig',
|
|
||||||
formConfigList: bannerConfig
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '背景',
|
|
||||||
key: 'skinConf.backgroundConf',
|
|
||||||
formConfigList: [
|
|
||||||
{
|
|
||||||
label: '背景颜色',
|
|
||||||
type: 'ColorPicker',
|
|
||||||
key: 'color'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '主题色',
|
|
||||||
key: 'skinConf.themeConf',
|
|
||||||
formConfigList: [
|
|
||||||
{
|
|
||||||
label: '全局应用',
|
|
||||||
type: 'ColorPicker',
|
|
||||||
key: 'color'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'skinConf.contentConf',
|
|
||||||
name: '内容区域',
|
|
||||||
formConfigList: [
|
|
||||||
{
|
|
||||||
label: '内容透明度',
|
|
||||||
type: 'SliderSetter',
|
|
||||||
key: 'opacity'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '品牌logo',
|
|
||||||
key: 'bottomConf',
|
|
||||||
formConfigList: logoConfig
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,62 +0,0 @@
|
|||||||
export default [
|
|
||||||
{
|
|
||||||
title: '提交按钮文案',
|
|
||||||
type: 'InputSetter',
|
|
||||||
key: 'submitTitle',
|
|
||||||
placeholder: '提交',
|
|
||||||
value: ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '提交确认弹窗',
|
|
||||||
type: 'Customed',
|
|
||||||
key: 'confirmAgain',
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
label: '是否配置该项',
|
|
||||||
labelStyle: { width: '120px' },
|
|
||||||
type: 'CustomedSwitch',
|
|
||||||
key: 'confirmAgain.is_again',
|
|
||||||
value: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '二次确认文案',
|
|
||||||
labelStyle: { width: '120px' },
|
|
||||||
type: 'InputSetter',
|
|
||||||
key: 'confirmAgain.again_text',
|
|
||||||
placeholder: '确认要提交吗?',
|
|
||||||
value: '确认要提交吗?'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '提交文案配置',
|
|
||||||
type: 'Customed',
|
|
||||||
key: 'msgContent',
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
label: '已提交',
|
|
||||||
labelStyle: { width: '120px' },
|
|
||||||
type: 'InputSetter',
|
|
||||||
key: 'msgContent.msg_9002',
|
|
||||||
placeholder: '请勿多次提交!',
|
|
||||||
value: '请勿多次提交!'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '提交结束',
|
|
||||||
labelStyle: { width: '120px' },
|
|
||||||
type: 'InputSetter',
|
|
||||||
key: 'msgContent.msg_9003',
|
|
||||||
placeholder: '您来晚了,已经满额!',
|
|
||||||
value: '您来晚了,已经满额!'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '其他提交失败',
|
|
||||||
labelStyle: { width: '120px' },
|
|
||||||
type: 'InputSetter',
|
|
||||||
key: 'msgContent.msg_9004',
|
|
||||||
placeholder: '提交失败!',
|
|
||||||
value: '提交失败!'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
@ -18,8 +18,11 @@
|
|||||||
</CooperationPanel>
|
</CooperationPanel>
|
||||||
<PreviewPanel></PreviewPanel>
|
<PreviewPanel></PreviewPanel>
|
||||||
<HistoryPanel></HistoryPanel>
|
<HistoryPanel></HistoryPanel>
|
||||||
<SavePanel></SavePanel>
|
<SavePanel :updateLogicConf="updateLogicConf" :updateWhiteConf="updateWhiteConf"></SavePanel>
|
||||||
<PublishPanel></PublishPanel>
|
<PublishPanel
|
||||||
|
:updateLogicConf="updateLogicConf"
|
||||||
|
:updateWhiteConf="updateWhiteConf"
|
||||||
|
></PublishPanel>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -28,6 +31,8 @@ import { computed } from 'vue'
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { get as _get } from 'lodash-es'
|
import { get as _get } from 'lodash-es'
|
||||||
|
|
||||||
|
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||||
|
|
||||||
import BackPanel from '../modules/generalModule/BackPanel.vue'
|
import BackPanel from '../modules/generalModule/BackPanel.vue'
|
||||||
import TitlePanel from '../modules/generalModule/TitlePanel.vue'
|
import TitlePanel from '../modules/generalModule/TitlePanel.vue'
|
||||||
import NavPanel from '../modules/generalModule/NavPanel.vue'
|
import NavPanel from '../modules/generalModule/NavPanel.vue'
|
||||||
@ -39,6 +44,59 @@ import CooperationPanel from '../modules/contentModule/CooperationPanel.vue'
|
|||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const title = computed(() => _get(store.state, 'edit.schema.metaData.title'))
|
const title = computed(() => _get(store.state, 'edit.schema.metaData.title'))
|
||||||
|
// 校验 - 逻辑
|
||||||
|
const updateLogicConf = () => {
|
||||||
|
let res = {
|
||||||
|
validated: true,
|
||||||
|
message: ''
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
showLogicEngine.value &&
|
||||||
|
showLogicEngine.value.rules &&
|
||||||
|
showLogicEngine.value.rules.length !== 0
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
showLogicEngine.value.validateSchema()
|
||||||
|
} catch (error) {
|
||||||
|
res = {
|
||||||
|
validated: false,
|
||||||
|
message: '逻辑配置不能为空'
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
const showLogicConf = showLogicEngine.value.toJson()
|
||||||
|
// 更新逻辑配置
|
||||||
|
store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验 - 白名单
|
||||||
|
const updateWhiteConf = () => {
|
||||||
|
let res = {
|
||||||
|
validated: true,
|
||||||
|
message: ''
|
||||||
|
}
|
||||||
|
const baseConf = store.state.edit.schema.baseConf || {}
|
||||||
|
if (baseConf.passwordSwitch && !baseConf.password) {
|
||||||
|
res = {
|
||||||
|
validated: false,
|
||||||
|
message: '访问密码不能为空'
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
if (baseConf.whitelistType != 'ALL' && !baseConf.whitelist?.length) {
|
||||||
|
res = {
|
||||||
|
validated: false,
|
||||||
|
message: '白名单不能为空'
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import url('@/management/styles/edit-btn.scss');
|
@import url('@/management/styles/edit-btn.scss');
|
||||||
|
@ -11,35 +11,37 @@ import { ElMessage } from 'element-plus'
|
|||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
import { publishSurvey, saveSurvey } from '@/management/api/survey'
|
import { publishSurvey, saveSurvey } from '@/management/api/survey'
|
||||||
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
|
||||||
import buildData from './buildData'
|
import buildData from './buildData'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
updateLogicConf: any
|
||||||
|
updateWhiteConf: any
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const isPublishing = ref<boolean>(false)
|
const isPublishing = ref<boolean>(false)
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const updateLogicConf = () => {
|
const validate = () => {
|
||||||
if (
|
let checked = true
|
||||||
showLogicEngine.value &&
|
let msg = ''
|
||||||
showLogicEngine.value.rules &&
|
const { validated, message } = props.updateLogicConf()
|
||||||
showLogicEngine.value.rules.length !== 0
|
if (!validated) {
|
||||||
) {
|
checked = validated
|
||||||
showLogicEngine.value.validateSchema()
|
msg = `检查页面"问卷编辑>显示逻辑":${message}`
|
||||||
const showLogicConf = showLogicEngine.value.toJson()
|
|
||||||
// 更新逻辑配置
|
|
||||||
store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
|
||||||
}
|
}
|
||||||
|
const { validated: whiteValidated, message: whiteMsg } = props.updateWhiteConf()
|
||||||
|
if (!whiteValidated) {
|
||||||
|
checked = whiteValidated
|
||||||
|
msg = `检查页面"问卷设置>作答限制":${whiteMsg}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateWhiteConf = () => {
|
return {
|
||||||
const baseConf = store.state.edit.schema.baseConf || {};
|
checked,
|
||||||
if (baseConf.passwordSwitch && !baseConf.password) {
|
msg
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if (baseConf.whitelistType!='ALL' && !baseConf.whitelist?.length) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePublish = async () => {
|
const handlePublish = async () => {
|
||||||
@ -49,11 +51,11 @@ const handlePublish = async () => {
|
|||||||
|
|
||||||
isPublishing.value = true
|
isPublishing.value = true
|
||||||
|
|
||||||
try {
|
// 发布检测
|
||||||
updateLogicConf()
|
const { checked, msg } = validate()
|
||||||
} catch (err) {
|
if (!checked) {
|
||||||
isPublishing.value = false
|
isPublishing.value = false
|
||||||
ElMessage.error('请检查逻辑配置是否有误')
|
ElMessage.error(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,14 +16,23 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, nextTick, watch } from 'vue'
|
import { ref, computed, nextTick, watch } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
import { get as _get } from 'lodash-es'
|
import { get as _get } from 'lodash-es'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
import { saveSurvey } from '@/management/api/survey'
|
import { saveSurvey } from '@/management/api/survey'
|
||||||
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
|
||||||
import buildData from './buildData'
|
import buildData from './buildData'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
updateLogicConf: any
|
||||||
|
updateWhiteConf: any
|
||||||
|
}
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const isSaving = ref<boolean>(false)
|
const isSaving = ref<boolean>(false)
|
||||||
const isShowAutoSave = ref<boolean>(false)
|
const isShowAutoSave = ref<boolean>(false)
|
||||||
const autoSaveStatus = ref<'succeed' | 'saving' | 'failed'>('succeed')
|
const autoSaveStatus = ref<'succeed' | 'saving' | 'failed'>('succeed')
|
||||||
@ -38,6 +47,27 @@ const saveText = computed(
|
|||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
|
const validate = () => {
|
||||||
|
let checked = true
|
||||||
|
let msg = ''
|
||||||
|
if (route.path.includes('edit/logic')) {
|
||||||
|
const { validated, message } = props.updateLogicConf()
|
||||||
|
checked = validated
|
||||||
|
msg = message
|
||||||
|
}
|
||||||
|
|
||||||
|
if (route.path.includes('edit/setting')) {
|
||||||
|
const { validated, message } = props.updateWhiteConf()
|
||||||
|
checked = validated
|
||||||
|
msg = message
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
checked,
|
||||||
|
msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const saveData = async () => {
|
const saveData = async () => {
|
||||||
const saveData = buildData(store.state.edit.schema)
|
const saveData = buildData(store.state.edit.schema)
|
||||||
|
|
||||||
@ -50,30 +80,6 @@ const saveData = async () => {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateLogicConf = () => {
|
|
||||||
if (
|
|
||||||
showLogicEngine.value &&
|
|
||||||
showLogicEngine.value.rules &&
|
|
||||||
showLogicEngine.value.rules.length !== 0
|
|
||||||
) {
|
|
||||||
showLogicEngine.value.validateSchema()
|
|
||||||
const showLogicConf = showLogicEngine.value.toJson()
|
|
||||||
// 更新逻辑配置
|
|
||||||
store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateWhiteConf = () => {
|
|
||||||
const baseConf = store.state.edit.schema.baseConf || {};
|
|
||||||
if (baseConf.passwordSwitch && !baseConf.password) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (baseConf.whitelistType!='ALL' && !baseConf.whitelist?.length) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const timerHandle = ref<NodeJS.Timeout | number | null>(null)
|
const timerHandle = ref<NodeJS.Timeout | number | null>(null)
|
||||||
const triggerAutoSave = () => {
|
const triggerAutoSave = () => {
|
||||||
if (autoSaveStatus.value === 'saving') {
|
if (autoSaveStatus.value === 'saving') {
|
||||||
@ -117,17 +123,12 @@ const handleSave = async () => {
|
|||||||
isSaving.value = true
|
isSaving.value = true
|
||||||
isShowAutoSave.value = false
|
isShowAutoSave.value = false
|
||||||
|
|
||||||
try {
|
// 保存检测
|
||||||
updateLogicConf()
|
const { checked, msg } = validate()
|
||||||
} catch (error) {
|
if (!checked) {
|
||||||
isSaving.value = false
|
|
||||||
ElMessage.error('请检查逻辑配置是否有误')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if(updateWhiteConf()){
|
|
||||||
isSaving.value = false
|
isSaving.value = false
|
||||||
ElMessage.error('请检查问卷设置是否有误')
|
ElMessage.error('请检查问卷设置是否有误')
|
||||||
|
ElMessage.error(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,16 +39,31 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, onMounted, shallowRef } from 'vue'
|
import { computed, ref, onMounted, shallowRef } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { cloneDeep as _cloneDeep, isArray as _isArray, get as _get,isFunction as _isFunction} from 'lodash-es'
|
import {
|
||||||
|
cloneDeep as _cloneDeep,
|
||||||
|
isArray as _isArray,
|
||||||
|
get as _get,
|
||||||
|
isFunction as _isFunction
|
||||||
|
} from 'lodash-es'
|
||||||
|
|
||||||
import baseConfig from './config/baseConfig'
|
import baseConfig from '@/management/pages/edit/setterConfig/baseConfig'
|
||||||
import baseFormConfig from './config/baseFormConfig'
|
import baseFormConfig from '@/management/pages/edit/setterConfig/baseFormConfig'
|
||||||
import FormItem from '@/materials/setters/widgets/FormItem.vue'
|
import FormItem from '@/materials/setters/widgets/FormItem.vue'
|
||||||
import setterLoader from '@/materials/setters/setterLoader'
|
import setterLoader from '@/materials/setters/setterLoader'
|
||||||
|
|
||||||
|
import WhiteList from './components/WhiteList.vue'
|
||||||
|
import TeamMemberList from './components/TeamMemberList.vue'
|
||||||
|
|
||||||
const formConfigList = ref<Array<any>>([])
|
const formConfigList = ref<Array<any>>([])
|
||||||
const components = shallowRef<any>({})
|
const components = shallowRef<any>({
|
||||||
const registerTypes = ref<any>({})
|
['WhiteList']: WhiteList,
|
||||||
|
['TeamMemberList']: TeamMemberList
|
||||||
|
})
|
||||||
|
// 登记默认注册的高级设置器组件
|
||||||
|
const registerTypes = ref<any>({
|
||||||
|
WhiteList: 'WhiteList',
|
||||||
|
TeamMemberList: 'TeamMemberList'
|
||||||
|
})
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const schemaBaseConf = computed(() => store.state.edit?.schema?.baseConf || {})
|
const schemaBaseConf = computed(() => store.state.edit?.schema?.baseConf || {})
|
||||||
|
|
||||||
@ -103,7 +118,9 @@ onMounted(async () => {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
const formList = formConfigList.value.map((item) => item.formList).flat()
|
const formList = formConfigList.value.map((item) => item.formList).flat()
|
||||||
const typeList = formList.map((item) => ({
|
const typeList = formList
|
||||||
|
.filter((item) => !item.custom)
|
||||||
|
.map((item) => ({
|
||||||
type: item.type,
|
type: item.type,
|
||||||
path: item.path || item.type
|
path: item.path || item.type
|
||||||
}))
|
}))
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="over-time">
|
|
||||||
<img class="over-img" src="/imgs/icons/overtime.webp" />
|
|
||||||
<p class="title-msg" v-safe-html="resultText"></p>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
moduleConfig: any
|
|
||||||
}
|
|
||||||
const props = defineProps<Props>()
|
|
||||||
const resultText = computed(() => props.moduleConfig?.msgContent?.msg_9001 || '问卷已过期')
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.over-time {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 5.5rem;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
.title-msg {
|
|
||||||
width: 100%;
|
|
||||||
font-size: 16px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.over-time .over-img {
|
|
||||||
margin-top: 1.6rem;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,56 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="suc-page">
|
|
||||||
<div class="suc-content">
|
|
||||||
<div class="title-box">
|
|
||||||
<img src="/imgs/icons/success.webp" class="success-img" />
|
|
||||||
<div class="title-msg" v-safe-html="successText"></div>
|
|
||||||
</div>
|
|
||||||
<div class="bottom-btn"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
moduleConfig: any
|
|
||||||
}
|
|
||||||
const props = defineProps<Props>()
|
|
||||||
const successText = computed(() => props.moduleConfig?.msgContent?.msg_200 || '')
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
/*成功页面跳转全屏展示浮层*/
|
|
||||||
.suc-page {
|
|
||||||
padding: 0;
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
display: inline-block;
|
|
||||||
height: 100%;
|
|
||||||
.success-img {
|
|
||||||
margin-top: -0.2rem;
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.suc-content {
|
|
||||||
max-width: 920px;
|
|
||||||
margin: 0 auto;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
position: relative;
|
|
||||||
padding-top: 1.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-msg {
|
|
||||||
margin-top: 0.4rem;
|
|
||||||
margin-bottom: 0.4rem;
|
|
||||||
font-size: 0.36rem;
|
|
||||||
color: #666;
|
|
||||||
:deep(*) {
|
|
||||||
font-size: 0.36rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.bottom-btn {
|
|
||||||
height: 300px;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,26 +0,0 @@
|
|||||||
export default {
|
|
||||||
Success: [
|
|
||||||
{
|
|
||||||
label: '提示文案',
|
|
||||||
type: 'RichText',
|
|
||||||
key: 'msgContent.msg_200',
|
|
||||||
placeholder: '提交成功',
|
|
||||||
value: '提交成功',
|
|
||||||
labelStyle: {
|
|
||||||
'font-weight': 'bold'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
OverTime: [
|
|
||||||
{
|
|
||||||
label: '提示文案',
|
|
||||||
type: 'RichText',
|
|
||||||
key: 'msgContent.msg_9001',
|
|
||||||
placeholder: '问卷已过期',
|
|
||||||
value: '问卷已过期',
|
|
||||||
labelStyle: {
|
|
||||||
'font-weight': 'bold'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="tab-box">
|
|
||||||
<div class="title">结果页状态选择</div>
|
|
||||||
<div class="status-list-wrapper">
|
|
||||||
<div
|
|
||||||
v-for="(status, index) in statusList"
|
|
||||||
:key="index"
|
|
||||||
class="status-item"
|
|
||||||
@click="handleChangePreview({ type: status.type })"
|
|
||||||
>
|
|
||||||
<span>{{ status.title }}</span>
|
|
||||||
<div class="preview-item">
|
|
||||||
<img :src="status.previewImg" :alt="status.title" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { EDIT_STATUS_MAP } from '../enum'
|
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
const statusList = [
|
|
||||||
{
|
|
||||||
type: EDIT_STATUS_MAP.SUCCESS,
|
|
||||||
title: '提交成功',
|
|
||||||
previewImg: '/imgs/icons/success.webp'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: EDIT_STATUS_MAP.OVERTIME,
|
|
||||||
title: '问卷过期',
|
|
||||||
previewImg: '/imgs/icons/overtime.webp'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const handleChangePreview = (data: any) => {
|
|
||||||
const currentStatus = store.state?.edit?.currentEditStatus
|
|
||||||
|
|
||||||
if (currentStatus && currentStatus !== data.type) {
|
|
||||||
store.commit('edit/changeStatusPreview', data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.tab-box {
|
|
||||||
width: 300px;
|
|
||||||
height: 100%;
|
|
||||||
box-shadow: none;
|
|
||||||
border: none;
|
|
||||||
overflow-y: auto;
|
|
||||||
background-color: #fff;
|
|
||||||
.title {
|
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: $primary-color;
|
|
||||||
padding-left: 20px;
|
|
||||||
// background: #f9fafc;
|
|
||||||
border-bottom: 1px solid #edeffc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.status-list-wrapper {
|
|
||||||
padding: 19px 18px 100px 19px;
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
|
|
||||||
label.title {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-item {
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
|
|
||||||
span {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 17px;
|
|
||||||
color: $font-color-stress;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
.preview-item {
|
|
||||||
padding: 40px 80px;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.2s;
|
|
||||||
&:hover {
|
|
||||||
-webkit-filter: brightness(90%);
|
|
||||||
filter: brightness(90%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,62 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="result-config-preview">
|
|
||||||
<div class="result-page-wrap">
|
|
||||||
<div class="result-page">
|
|
||||||
<component
|
|
||||||
:is="components[currentEditStatus]"
|
|
||||||
:key="currentEditStatus"
|
|
||||||
:module-config="moduleConfig"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed } from 'vue'
|
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { get as _get } from 'lodash-es'
|
|
||||||
|
|
||||||
import SuccessContent from '../components/SuccessContent.vue'
|
|
||||||
import OverTime from '../components/OverTime.vue'
|
|
||||||
import { EDIT_STATUS_MAP } from '../enum'
|
|
||||||
|
|
||||||
const components = {
|
|
||||||
[EDIT_STATUS_MAP.SUCCESS]: SuccessContent,
|
|
||||||
[EDIT_STATUS_MAP.OVERTIME]: OverTime
|
|
||||||
}
|
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
const currentEditStatus = computed(() => store.state?.edit?.currentEditStatus)
|
|
||||||
const moduleConfig = computed(() => {
|
|
||||||
return _get(store.state, 'edit.schema.submitConf')
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.result-config-preview {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
min-width: 500px;
|
|
||||||
padding-bottom: 80px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
background-color: #f6f7f9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result-page-wrap {
|
|
||||||
width: 90%;
|
|
||||||
margin-top: 50px;
|
|
||||||
min-height: 812px;
|
|
||||||
max-height: 812px;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
background-color: var(--primary-background-color);
|
|
||||||
padding: 0 0.3rem;
|
|
||||||
.result-page {
|
|
||||||
background: rgba(255, 255, 255, var(--opacity));
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,120 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="question-edit-form">
|
|
||||||
<div class="setter-title">
|
|
||||||
{{ currentEditText }}
|
|
||||||
</div>
|
|
||||||
<el-form class="question-config-form" label-position="top" @submit.prevent>
|
|
||||||
<template v-for="(item, index) in formFields" :key="index">
|
|
||||||
<FormItem
|
|
||||||
v-if="item.type && !item.hidden && Boolean(registerTypes[item.type])"
|
|
||||||
:form-config="item"
|
|
||||||
:style="item.style"
|
|
||||||
>
|
|
||||||
<Component
|
|
||||||
v-if="Boolean(registerTypes[item.type])"
|
|
||||||
:is="components[item.type]"
|
|
||||||
:module-config="moduleConfig"
|
|
||||||
:form-config="item"
|
|
||||||
@form-change="handleFormChange"
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
</template>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed, ref, shallowRef } from 'vue'
|
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { get as _get } from 'lodash-es'
|
|
||||||
|
|
||||||
import FormItem from '@/materials/setters/widgets/FormItem.vue'
|
|
||||||
import setterLoader from '@/materials/setters/setterLoader'
|
|
||||||
import statusConfig from '../config/statusConfig'
|
|
||||||
|
|
||||||
const textMap = {
|
|
||||||
Success: '提交成功页面配置',
|
|
||||||
OverTime: '问卷过期页面配置'
|
|
||||||
}
|
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
|
|
||||||
const components = shallowRef<any>({})
|
|
||||||
const registerTypes = ref<any>({})
|
|
||||||
const moduleConfig = computed(() => _get(store.state, 'edit.schema.submitConf'))
|
|
||||||
const currentEditText = computed(() => (textMap as any)[store.state.edit.currentEditStatus])
|
|
||||||
const formFields = computed(() => {
|
|
||||||
const currentStatus = store.state.edit.currentEditStatus
|
|
||||||
const formList = (statusConfig as any)[currentStatus] || []
|
|
||||||
const list = formList.map((item: any) => {
|
|
||||||
const value = _get(moduleConfig.value, item.key, item.value)
|
|
||||||
|
|
||||||
return { ...item, value }
|
|
||||||
})
|
|
||||||
|
|
||||||
registerComponents(list)
|
|
||||||
|
|
||||||
return list
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleFormChange = ({ key, value }: any) => {
|
|
||||||
store.dispatch('edit/changeSchema', {
|
|
||||||
key: `submitConf.${key}`,
|
|
||||||
value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const registerComponents = async (formFieldData: any) => {
|
|
||||||
const setters = formFieldData.map((item: any) => item.type)
|
|
||||||
const settersSet = new Set(setters)
|
|
||||||
const settersArr = Array.from(settersSet)
|
|
||||||
const allSetters = settersArr.map((item) => {
|
|
||||||
return {
|
|
||||||
type: item,
|
|
||||||
path: item
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
try {
|
|
||||||
const comps = await setterLoader.loadComponents(allSetters)
|
|
||||||
|
|
||||||
for (const comp of comps) {
|
|
||||||
if (!comp) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const { type, component, err } = comp
|
|
||||||
|
|
||||||
if (!err) {
|
|
||||||
const componentName = component.name
|
|
||||||
|
|
||||||
components.value[type] = component
|
|
||||||
registerTypes.value[type] = componentName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.question-edit-form {
|
|
||||||
width: 360px;
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.setter-title {
|
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: $primary-color;
|
|
||||||
padding-left: 20px;
|
|
||||||
// background: #f9fafc;
|
|
||||||
border-bottom: 1px solid #edeffc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.question-config-form {
|
|
||||||
padding: 30px 20px 50px 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,85 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="setter-wrapper">
|
|
||||||
<div class="setter-title">样式设置</div>
|
|
||||||
<div class="setter-content">
|
|
||||||
<el-collapse v-model="collapse">
|
|
||||||
<el-collapse-item
|
|
||||||
v-for="(collapse, index) in skinConfig"
|
|
||||||
:key="index"
|
|
||||||
:title="collapse.name"
|
|
||||||
:name="collapse.key"
|
|
||||||
>
|
|
||||||
<SetterField
|
|
||||||
:form-config-list="collapse.formConfigList"
|
|
||||||
:module-config="_get(schema, collapse.key, {})"
|
|
||||||
@form-change="
|
|
||||||
(key) => {
|
|
||||||
handleFormChange(key, collapse.key)
|
|
||||||
}
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</el-collapse-item>
|
|
||||||
</el-collapse>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed, ref } from 'vue'
|
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { get as _get } from 'lodash-es'
|
|
||||||
|
|
||||||
import skinConfig from '@/management/config/setterConfig/skinConfig'
|
|
||||||
import SetterField from '@/management/pages/edit/components/SetterField.vue'
|
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
const collapse = ref<string>('')
|
|
||||||
const schema = computed(() => _get(store.state, 'edit.schema'))
|
|
||||||
|
|
||||||
const handleFormChange = (data: any, collapse: string) => {
|
|
||||||
const { key, value } = data
|
|
||||||
const currentEditKey = `${collapse}`
|
|
||||||
const resultKey = `${currentEditKey}.${key}`
|
|
||||||
|
|
||||||
store.dispatch('edit/changeSchema', { key: resultKey, value })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.setter-wrapper {
|
|
||||||
width: 360px;
|
|
||||||
height: 100%;
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.setter-title {
|
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: $primary-color;
|
|
||||||
padding-left: 20px;
|
|
||||||
// background: #f9fafc;
|
|
||||||
border-bottom: 1px solid #edeffc;
|
|
||||||
}
|
|
||||||
.setter-content {
|
|
||||||
padding: 10px 20px;
|
|
||||||
.el-collapse {
|
|
||||||
border: none;
|
|
||||||
:deep(.el-collapse-item__header) {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #606266;
|
|
||||||
font-weight: bold;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
:deep(.el-collapse-item__wrap) {
|
|
||||||
border: none;
|
|
||||||
.el-collapse-item__content {
|
|
||||||
padding-bottom: 0px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.config-form {
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -16,9 +16,9 @@ import { onMounted } from 'vue'
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
|
||||||
import CommonTemplate from '../../components/CommonTemplate.vue'
|
import CommonTemplate from '../../components/CommonTemplate.vue'
|
||||||
import CatalogPanel from '../../modules/settingModule/skin/CatalogPanel.vue'
|
import CatalogPanel from '../../modules/skinModule/CatalogPanel.vue'
|
||||||
import PreviewPanel from '../../modules/settingModule/skin/PreviewPanel.vue'
|
import PreviewPanel from '../../modules/skinModule/PreviewPanel.vue'
|
||||||
import SetterPanel from '../../modules/settingModule/skin/SetterPanel.vue'
|
import SetterPanel from '../../modules/skinModule/SetterPanel.vue'
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import CommonTemplate from '../../components/CommonTemplate.vue'
|
import CommonTemplate from '../../components/CommonTemplate.vue'
|
||||||
import ResultCatalog from '../../modules/settingModule/result/CatalogPanel.vue'
|
import ResultCatalog from '../../modules/resultModule/CatalogPanel.vue'
|
||||||
import ResultPreview from '../../modules/settingModule/result/PreviewPanel.vue'
|
import ResultPreview from '../../modules/resultModule/PreviewPanel.vue'
|
||||||
import ResultSetter from '../../modules/settingModule/result/SetterPanel.vue'
|
import ResultSetter from '../../modules/resultModule/SetterPanel.vue'
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="answer-radio-wrap">
|
|
||||||
<el-radio-group v-model="whitelistType" @change="handleRadioGroupChange">
|
|
||||||
<el-radio value="ALL">所有人</el-radio>
|
|
||||||
<el-radio value="MEMBER">空间成员</el-radio>
|
|
||||||
<el-radio value="CUSTOM">白名单</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup>
|
|
||||||
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { FORM_CHANGE_EVENT_KEY } from '@/materials/setters/constant'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
formConfig: Object,
|
|
||||||
})
|
|
||||||
const emit = defineEmits([FORM_CHANGE_EVENT_KEY])
|
|
||||||
|
|
||||||
const whitelistType = ref(props.formConfig?.value || 'ALL')
|
|
||||||
|
|
||||||
const handleRadioGroupChange = (value) => {
|
|
||||||
const key = props.formConfig.key
|
|
||||||
emit(FORM_CHANGE_EVENT_KEY, { key, value })
|
|
||||||
emit(FORM_CHANGE_EVENT_KEY, { key:'baseConf.whitelist', value: [] })
|
|
||||||
emit(FORM_CHANGE_EVENT_KEY, { key: 'baseConf.memberType', value: 'MOBILE' })
|
|
||||||
if (whitelistType.value == 'ALL') {
|
|
||||||
emit(FORM_CHANGE_EVENT_KEY, { key:'baseConf.whitelistTip', value:'' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.switch-input-wrap{
|
|
||||||
width: 100%;
|
|
||||||
.mt16{
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
Loading…
Reference in New Issue
Block a user