refactor: 重构 management/pages/edit 目录下组件, 使用 Vue3 组合式 API 写法 (#251)
This commit is contained in:
parent
d9255db8a9
commit
cffe037269
@ -14,22 +14,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
|
||||
import BackPanel from '../modules/generalModule/BackPanel.vue'
|
||||
import TitlePanel from '../modules/generalModule/TitlePanel.vue'
|
||||
import NavPanel from '../modules/generalModule/NavPanel.vue'
|
||||
import HistoryPanel from '../modules/contentModule/HistoryPanel.vue'
|
||||
import SavePanel from '../modules/contentModule/SavePanel.vue'
|
||||
import PublishPanel from '../modules/contentModule/PublishPanel.vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const store = useStore()
|
||||
const title = computed(() => _get(store.state, 'edit.schema.metaData.title'))
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nav {
|
||||
width: 100%;
|
||||
|
@ -16,28 +16,28 @@
|
||||
:form-config="content"
|
||||
>
|
||||
<Component
|
||||
:is="content.type"
|
||||
:is="components[content.type]"
|
||||
:form-config="content"
|
||||
:module-config="moduleConfig"
|
||||
@form-change="onFormChange($event, content)"
|
||||
@form-change="handleFormChange($event, content)"
|
||||
:class="content.contentClass"
|
||||
/>
|
||||
</FormItem>
|
||||
</template>
|
||||
<FormItem v-else :form-config="item">
|
||||
<Component
|
||||
:is="item.type"
|
||||
:is="components[item.type]"
|
||||
:form-config="item"
|
||||
:module-config="moduleConfig"
|
||||
@form-change="onFormChange($event, item)"
|
||||
@form-change="handleFormChange($event, item)"
|
||||
:class="item.contentClass"
|
||||
/>
|
||||
</FormItem>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import { watch, ref, shallowRef } from 'vue'
|
||||
import { get as _get, pick as _pick, isFunction as _isFunction } from 'lodash-es'
|
||||
|
||||
import FormItem from '@/materials/setters/widgets/FormItem.vue'
|
||||
@ -45,8 +45,20 @@ import setterLoader from '@/materials/setters/setterLoader'
|
||||
|
||||
import { FORM_CHANGE_EVENT_KEY } from '@/materials/setters/constant'
|
||||
|
||||
interface Props {
|
||||
formConfigList: Array<any>
|
||||
moduleConfig: any
|
||||
}
|
||||
|
||||
interface Emit {
|
||||
(ev: typeof FORM_CHANGE_EVENT_KEY, arg: { key: string; value: any }): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
// 静态配置设置动态值
|
||||
const formatValue = ({ item, moduleConfig }) => {
|
||||
const formatValue = ({ item, moduleConfig }: any) => {
|
||||
if (_isFunction(item.valueAdapter)) {
|
||||
const value = item.valueAdapter({ moduleConfig })
|
||||
|
||||
@ -65,89 +77,64 @@ const formatValue = ({ item, moduleConfig }) => {
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'SettersField',
|
||||
props: {
|
||||
formConfigList: Array, // 对应题型组件的meta.js内容
|
||||
moduleConfig: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
register: {},
|
||||
formFieldData: [],
|
||||
init: true
|
||||
const formFieldData = ref<Array<any>>([])
|
||||
const init = ref<boolean>(true)
|
||||
const components = shallowRef<any>({})
|
||||
|
||||
const handleFormChange = (data: any, formConfig: any) => {
|
||||
if (_isFunction(formConfig?.setterAdapter)) {
|
||||
const resultData = formConfig.setterAdapter(data)
|
||||
|
||||
if (Array.isArray(resultData)) {
|
||||
resultData.forEach((item) => {
|
||||
emit(FORM_CHANGE_EVENT_KEY, item)
|
||||
})
|
||||
} else {
|
||||
emit(FORM_CHANGE_EVENT_KEY, resultData)
|
||||
}
|
||||
} else {
|
||||
emit(FORM_CHANGE_EVENT_KEY, data)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
FormItem
|
||||
},
|
||||
watch: {
|
||||
formConfigList: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
async handler(newVal) {
|
||||
this.init = true
|
||||
if (!newVal || !newVal.length) {
|
||||
return
|
||||
}
|
||||
|
||||
// 组件注册
|
||||
await this.handleComponentRegister(newVal)
|
||||
|
||||
this.init = false
|
||||
this.formFieldData = this.setValues(this.formConfigList)
|
||||
}
|
||||
},
|
||||
// schema变化联动
|
||||
moduleConfig: {
|
||||
deep: true,
|
||||
async handler() {
|
||||
// 配置变化后初次不监听value变化(如题型切换场景避免多次计算)
|
||||
if (this.init) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: 优化,依赖的schema变化时,均会重新计算
|
||||
this.formFieldData = this.setValues(this.formConfigList)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setValues(configList = []) {
|
||||
const normalizationValues = (configList: Array<any> = []) => {
|
||||
return configList
|
||||
.filter((item) => {
|
||||
.filter((item: any) => {
|
||||
// 组件组
|
||||
if (item.type === 'Customed') {
|
||||
item.content = this.setValues(item.content)
|
||||
item.content = normalizationValues(item.content)
|
||||
return true
|
||||
}
|
||||
|
||||
if (!item.type) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (item.hidden) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 动态显隐设置器
|
||||
if (_isFunction(item.relyFunc)) {
|
||||
return item.relyFunc(this.moduleConfig)
|
||||
return item.relyFunc(props.moduleConfig)
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
.map((item) => {
|
||||
.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
value: formatValue({ item, moduleConfig: this.moduleConfig }) // 动态复值
|
||||
value: formatValue({ item, moduleConfig: props.moduleConfig }) // 动态复值
|
||||
}
|
||||
})
|
||||
},
|
||||
async handleComponentRegister(formFieldData) {
|
||||
let innerSetters = []
|
||||
const setters = formFieldData.map((item) => {
|
||||
}
|
||||
|
||||
const registerComponents = async (formFieldData: any) => {
|
||||
let innerSetters: Array<any> = []
|
||||
|
||||
const setters = formFieldData.map((item: any) => {
|
||||
if (item.type === 'Customed') {
|
||||
innerSetters.push(...(item.content || []).map((content) => content.type))
|
||||
innerSetters.push(...(item.content || []).map((content: any) => content.type))
|
||||
}
|
||||
|
||||
return item.type
|
||||
@ -155,51 +142,65 @@ export default {
|
||||
|
||||
const settersSet = new Set([...setters, ...innerSetters])
|
||||
const settersArr = Array.from(settersSet)
|
||||
const allSetters = settersArr.map((item) => {
|
||||
return {
|
||||
const allSetters = settersArr.map((item) => ({
|
||||
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
|
||||
if (!this.$options.components) {
|
||||
this.$options.components = {}
|
||||
}
|
||||
this.$options.components[componentName] = component
|
||||
this.register[type] = componentName
|
||||
components.value[type] = component
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.formConfigList,
|
||||
async (newVal: Array<any>) => {
|
||||
init.value = true
|
||||
|
||||
if (!newVal || !newVal.length) {
|
||||
return
|
||||
}
|
||||
|
||||
await registerComponents(newVal)
|
||||
init.value = false
|
||||
formFieldData.value = normalizationValues(newVal)
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
onFormChange(data, formConfig) {
|
||||
if (_isFunction(formConfig?.setterAdapter)) {
|
||||
const resultData = formConfig.setterAdapter(data)
|
||||
if (Array.isArray(resultData)) {
|
||||
resultData.forEach((item) => {
|
||||
this.$emit(FORM_CHANGE_EVENT_KEY, item)
|
||||
})
|
||||
} else {
|
||||
this.$emit(FORM_CHANGE_EVENT_KEY, resultData)
|
||||
}
|
||||
} else {
|
||||
this.$emit(FORM_CHANGE_EVENT_KEY, data)
|
||||
}
|
||||
}
|
||||
watch(
|
||||
() => props.moduleConfig,
|
||||
() => {
|
||||
// 配置变化后初次不监听value变化(如题型切换场景避免多次计算)
|
||||
if (init.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: 优化,依赖的schema变化时,均会重新计算
|
||||
formFieldData.value = normalizationValues(props.formConfigList)
|
||||
},
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.config-form {
|
||||
padding: 15px 0;
|
||||
|
@ -13,42 +13,38 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
|
||||
import LeftMenu from '@/management/components/LeftMenu.vue'
|
||||
|
||||
import CommonTemplate from './components/CommonTemplate.vue'
|
||||
import Navbar from './components/ModuleNavbar.vue'
|
||||
|
||||
import { initShowLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||
export default {
|
||||
name: 'questionEditPage',
|
||||
components: {
|
||||
CommonTemplate,
|
||||
Navbar,
|
||||
LeftMenu
|
||||
},
|
||||
async created() {
|
||||
this.$store.commit('edit/setSurveyId', this.$route.params.id)
|
||||
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
onMounted(async () => {
|
||||
store.commit('edit/setSurveyId', route.params.id)
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('edit/init')
|
||||
// await this.$store.dispatch('logic/initShowLogic', this.$store.state.edit.schema.logicConf.showLogicConf || {})
|
||||
await initShowLogicEngine(this.$store.state.edit.schema.logicConf.showLogicConf || {})
|
||||
} catch (error) {
|
||||
ElMessage.error(error.message)
|
||||
// 自动跳转回列表页
|
||||
await store.dispatch('edit/init')
|
||||
await initShowLogicEngine(store.state.edit.schema.logicConf.showLogicConf || {})
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err.message)
|
||||
|
||||
setTimeout(() => {
|
||||
this.$router.replace({
|
||||
name: 'survey'
|
||||
})
|
||||
router.replace({ name: 'survey' })
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.edit-index {
|
||||
height: 100%;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-popover placement="top" trigger="click" @show="onShow" :width="320">
|
||||
<el-tabs v-model="currentTab" class="custom-tab" v-if="visible" v-loading="paneLoading">
|
||||
<el-popover placement="top" trigger="click" @show="handlePopoverShow" :width="320">
|
||||
<el-tabs v-model="currentTab" class="custom-tab" v-if="visible" v-loading="loading">
|
||||
<el-tab-pane label="修改历史" name="daily" class="custom-tab-pane">
|
||||
<div class="line" v-for="(his, index) in dailyList" :key="index">
|
||||
<span class="operator">{{ his.operator }}</span>
|
||||
@ -24,100 +24,77 @@
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSurveyHistory } from '@/management/api/survey'
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
import moment from 'moment'
|
||||
// 引入中文
|
||||
import 'moment/locale/zh-cn'
|
||||
// 设置中文
|
||||
moment.locale('zh-cn')
|
||||
|
||||
import { mapState } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
import { getSurveyHistory } from '@/management/api/survey'
|
||||
|
||||
const getItemData = (item) => ({
|
||||
const getItemData = (item: any) => ({
|
||||
operator: item?.operator?.username || '未知用户',
|
||||
time: moment(item.createDate).format('YYYY-MM-DD HH:mm:ss')
|
||||
})
|
||||
|
||||
export default {
|
||||
name: 'HistoryPanel',
|
||||
computed: {
|
||||
...mapState({
|
||||
surveyId: (state) => _get(state, 'edit.surveyId')
|
||||
}),
|
||||
dailyList() {
|
||||
return this.dailyHis.map(getItemData)
|
||||
},
|
||||
publishList() {
|
||||
return this.publishHis.map(getItemData)
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dailyHis: [],
|
||||
publishHis: [],
|
||||
currentTab: 'daily',
|
||||
visible: false,
|
||||
paneLoading: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
visible: {
|
||||
async handler(newVal) {
|
||||
if (this.visible && newVal) {
|
||||
this.fetchHis()
|
||||
}
|
||||
}
|
||||
},
|
||||
currentTab: {
|
||||
immediate: true,
|
||||
async handler(newVal) {
|
||||
if (this.visible && newVal) {
|
||||
this.fetchHis()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onShow() {
|
||||
this.visible = true
|
||||
},
|
||||
fetchHis() {
|
||||
this.paneLoading = true
|
||||
switch (this.currentTab) {
|
||||
case 'daily':
|
||||
getSurveyHistory({
|
||||
surveyId: this.surveyId,
|
||||
historyType: 'dailyHis'
|
||||
})
|
||||
.then((dailyHis) => {
|
||||
this.dailyHis = dailyHis.data || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.paneLoading = false
|
||||
})
|
||||
break
|
||||
const dailyList = ref<Array<any>>([])
|
||||
const publishList = ref<Array<any>>([])
|
||||
const currentTab = ref<'daily' | 'publish'>('daily')
|
||||
const visible = ref<boolean>(false)
|
||||
|
||||
case 'publish':
|
||||
const store = useStore()
|
||||
|
||||
const queryHistories = async () => {
|
||||
if (dirtyMonitor.value) {
|
||||
loading.value = true
|
||||
dirtyMonitor.value = false
|
||||
|
||||
const surveyId = _get(store.state, 'edit.surveyId')
|
||||
const [dHis, pHis] = await Promise.all([
|
||||
getSurveyHistory({
|
||||
surveyId: this.surveyId,
|
||||
surveyId,
|
||||
historyType: 'dailyHis'
|
||||
}),
|
||||
getSurveyHistory({
|
||||
surveyId,
|
||||
historyType: 'publishHis'
|
||||
})
|
||||
.then((publishHis) => {
|
||||
this.publishHis = publishHis.data || []
|
||||
]).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
.finally(() => {
|
||||
this.paneLoading = false
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
if ((dHis.data || []).length !== dailyList.value.length) {
|
||||
dailyList.value = (dHis.data || []).map(getItemData)
|
||||
}
|
||||
|
||||
if ((pHis.data || []).length !== publishList.value.length) {
|
||||
publishList.value = (pHis.data || []).map(getItemData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handlePopoverShow = async () => {
|
||||
visible.value = true
|
||||
queryHistories()
|
||||
}
|
||||
const loading = ref<boolean>(false)
|
||||
const dirtyMonitor = ref<boolean>(true)
|
||||
const schemaUpdateTime = computed(() => _get(store.state, 'edit.schemaUpdateTime'))
|
||||
|
||||
watch(
|
||||
schemaUpdateTime,
|
||||
() => {
|
||||
if (!dirtyMonitor.value) {
|
||||
dirtyMonitor.value = true
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import url('@/management/styles/edit-btn.scss');
|
||||
|
||||
|
@ -1,80 +1,81 @@
|
||||
<template>
|
||||
<el-button type="primary" :loading="isPublishing" class="publish-btn" @click="onPublish">
|
||||
<el-button type="primary" :loading="isPublishing" class="publish-btn" @click="handlePublish">
|
||||
发布
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { get as _get } from 'lodash-es'
|
||||
import { mapState } from 'vuex'
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
|
||||
import { publishSurvey, saveSurvey } from '@/management/api/survey'
|
||||
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||
import buildData from './buildData'
|
||||
|
||||
export default {
|
||||
name: 'PublishPanel',
|
||||
data() {
|
||||
return {
|
||||
isPublishing: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
surveyId: (state) => _get(state, 'edit.surveyId')
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
async onPublish() {
|
||||
try {
|
||||
this.updateLogicConf()
|
||||
} catch (error) {
|
||||
ElMessage.error('请检查逻辑配置是否有误')
|
||||
return
|
||||
}
|
||||
const saveData = buildData(this.$store.state.edit.schema)
|
||||
if (!saveData.surveyId) {
|
||||
ElMessage.error('未获取到问卷id')
|
||||
return
|
||||
}
|
||||
if (this.isPublishing) {
|
||||
return
|
||||
}
|
||||
const isPublishing = ref<boolean>(false)
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
|
||||
try {
|
||||
this.isPublishing = true
|
||||
const saveRes = await saveSurvey(saveData)
|
||||
if (saveRes.code !== 200) {
|
||||
ElMessage.error(saveRes.errmsg || '问卷保存失败')
|
||||
return
|
||||
}
|
||||
const publishRes = await publishSurvey({ surveyId: this.surveyId })
|
||||
if (publishRes.code === 200) {
|
||||
ElMessage.success('发布成功')
|
||||
this.$store.dispatch('edit/getSchemaFromRemote')
|
||||
this.$router.push({ name: 'publish' })
|
||||
} else {
|
||||
ElMessage.error(`发布失败 ${publishRes.errmsg}`)
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error(`发布失败`)
|
||||
} finally {
|
||||
this.isPublishing = false
|
||||
}
|
||||
},
|
||||
updateLogicConf() {
|
||||
if (showLogicEngine.value) {
|
||||
const updateLogicConf = () => {
|
||||
if (
|
||||
showLogicEngine.value &&
|
||||
showLogicEngine.value.rules &&
|
||||
showLogicEngine.value.rules.length !== 0
|
||||
) {
|
||||
showLogicEngine.value.validateSchema()
|
||||
const showLogicConf = showLogicEngine.value.toJson()
|
||||
// 更新逻辑配置
|
||||
this.$store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
||||
store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
||||
}
|
||||
}
|
||||
|
||||
const handlePublish = async () => {
|
||||
if (isPublishing.value) {
|
||||
return
|
||||
}
|
||||
|
||||
isPublishing.value = true
|
||||
|
||||
try {
|
||||
updateLogicConf()
|
||||
} catch (err) {
|
||||
isPublishing.value = false
|
||||
ElMessage.error('请检查逻辑配置是否有误')
|
||||
return
|
||||
}
|
||||
|
||||
const saveData = buildData(store.state.edit.schema)
|
||||
if (!saveData.surveyId) {
|
||||
isPublishing.value = false
|
||||
ElMessage.error('未获取到问卷id')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const saveRes: any = await saveSurvey(saveData)
|
||||
if (saveRes.code !== 200) {
|
||||
isPublishing.value = false
|
||||
ElMessage.error(saveRes.errmsg || '问卷保存失败')
|
||||
return
|
||||
}
|
||||
|
||||
const publishRes: any = await publishSurvey({ surveyId: saveData.surveyId })
|
||||
if (publishRes.code === 200) {
|
||||
ElMessage.success('发布成功')
|
||||
store.dispatch('edit/getSchemaFromRemote')
|
||||
router.push({ name: 'publish' })
|
||||
} else {
|
||||
ElMessage.error(`发布失败 ${publishRes.errmsg}`)
|
||||
}
|
||||
} catch (err) {
|
||||
ElMessage.error(`发布失败`)
|
||||
} finally {
|
||||
isPublishing.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.publish-btn {
|
||||
width: 100px;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="btn" @click="onSave" v-loading="isSaving">
|
||||
<div class="btn" @click="handleSave" v-loading="isSaving">
|
||||
<i class="iconfont icon-baocun"></i>
|
||||
<span class="btn-txt">保存</span>
|
||||
<transition name="fade">
|
||||
@ -13,115 +13,109 @@
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, nextTick, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
|
||||
import { saveSurvey } from '@/management/api/survey'
|
||||
import buildData from './buildData'
|
||||
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||
import buildData from './buildData'
|
||||
|
||||
export default {
|
||||
components: {},
|
||||
name: 'SavePanel',
|
||||
data() {
|
||||
return {
|
||||
isSaving: false,
|
||||
isShowAutoSave: false,
|
||||
autoSaveStatus: 'succeed'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
schemaUpdateTime: (state) => _get(state, 'edit.schemaUpdateTime')
|
||||
}),
|
||||
saveText() {
|
||||
const statusMap = {
|
||||
const isSaving = ref<boolean>(false)
|
||||
const isShowAutoSave = ref<boolean>(false)
|
||||
const autoSaveStatus = ref<'succeed' | 'saving' | 'failed'>('succeed')
|
||||
const saveText = computed(
|
||||
() =>
|
||||
({
|
||||
saving: '保存中',
|
||||
succeed: '保存成功',
|
||||
failed: '保存失败'
|
||||
}
|
||||
return statusMap[this.autoSaveStatus]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
schemaUpdateTime() {
|
||||
this.triggerAutoSave()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
triggerAutoSave() {
|
||||
if (this.autoSaveStatus === 'saving') {
|
||||
// 正在调用接口
|
||||
setTimeout(() => {
|
||||
this.triggerAutoSave()
|
||||
}, 1000)
|
||||
} else {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer)
|
||||
}
|
||||
this.timer = setTimeout(() => {
|
||||
this.autoSaveStatus = 'saving'
|
||||
this.isShowAutoSave = true
|
||||
this.$nextTick(() => {
|
||||
this.saveData()
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.autoSaveStatus = 'succeed'
|
||||
} else {
|
||||
this.autoSaveStatus = 'failed'
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.isShowAutoSave = false
|
||||
this.timer = null
|
||||
}, 300)
|
||||
})
|
||||
.catch(() => {
|
||||
this.timer = null
|
||||
this.autoSaveStatus = 'failed'
|
||||
this.isShowAutoSave = true
|
||||
})
|
||||
})
|
||||
}, 2000)
|
||||
}
|
||||
},
|
||||
updateLogicConf() {
|
||||
if (showLogicEngine.value) {
|
||||
showLogicEngine.value.validateSchema()
|
||||
const showLogicConf = showLogicEngine.value.toJson()
|
||||
// 更新逻辑配置
|
||||
this.$store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
||||
}
|
||||
},
|
||||
async saveData() {
|
||||
const saveData = buildData(this.$store.state.edit.schema)
|
||||
})[autoSaveStatus.value]
|
||||
)
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const saveData = async () => {
|
||||
const saveData = buildData(store.state.edit.schema)
|
||||
|
||||
if (!saveData.surveyId) {
|
||||
ElMessage.error('未获取到问卷id')
|
||||
return null
|
||||
}
|
||||
|
||||
const res = await saveSurvey(saveData)
|
||||
return res
|
||||
},
|
||||
async onSave() {
|
||||
if (this.isSaving) {
|
||||
}
|
||||
|
||||
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 timerHandle = ref<NodeJS.Timeout | number | null>(null)
|
||||
const triggerAutoSave = () => {
|
||||
if (autoSaveStatus.value === 'saving') {
|
||||
setTimeout(() => triggerAutoSave(), 1000)
|
||||
} else {
|
||||
if (timerHandle.value) {
|
||||
clearTimeout(timerHandle.value)
|
||||
timerHandle.value = null
|
||||
}
|
||||
|
||||
timerHandle.value = setTimeout(() => {
|
||||
autoSaveStatus.value = 'saving'
|
||||
isShowAutoSave.value = true
|
||||
nextTick(async () => {
|
||||
try {
|
||||
const res: any = await saveData()
|
||||
if (res.code === 200) {
|
||||
autoSaveStatus.value = 'succeed'
|
||||
} else {
|
||||
autoSaveStatus.value = 'failed'
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
isShowAutoSave.value = false
|
||||
timerHandle.value = null
|
||||
}, 300)
|
||||
} catch (err) {
|
||||
autoSaveStatus.value = 'failed'
|
||||
isShowAutoSave.value = true
|
||||
}
|
||||
})
|
||||
}, 2000)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSave = async () => {
|
||||
if (isSaving.value) {
|
||||
return
|
||||
}
|
||||
this.isShowAutoSave = false
|
||||
|
||||
isSaving.value = true
|
||||
isShowAutoSave.value = false
|
||||
|
||||
try {
|
||||
this.updateLogicConf()
|
||||
updateLogicConf()
|
||||
} catch (error) {
|
||||
// console.error(error)
|
||||
isSaving.value = false
|
||||
ElMessage.error('请检查逻辑配置是否有误')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
this.isSaving = true
|
||||
const res = await this.saveData()
|
||||
const res: any = await saveData()
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('保存成功')
|
||||
} else {
|
||||
@ -130,13 +124,15 @@ export default {
|
||||
} catch (error) {
|
||||
ElMessage.error('保存问卷失败')
|
||||
} finally {
|
||||
this.isSaving = false
|
||||
isSaving.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
const schemaUpdateTime = computed(() => _get(store.state, 'edit.schemaUpdateTime'))
|
||||
watch(schemaUpdateTime, () => {
|
||||
triggerAutoSave()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import url('@/management/styles/edit-btn.scss');
|
||||
|
||||
|
@ -1,16 +1,12 @@
|
||||
<template>
|
||||
<div class="back-btn" @click="onBack">
|
||||
<div class="back-btn" @click="handleNavigateHome">
|
||||
<i class="iconfont icon-fanhui"></i>
|
||||
<span>返回</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const onBack = () => {
|
||||
window.open('/survey', '_self')
|
||||
}
|
||||
const handleNavigateHome = () => window.open('/survey', '_self')
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.back-btn {
|
||||
height: 100%;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<template v-for="btnItem in btnList" :key="btnItem.key">
|
||||
<template v-for="route in routes" :key="route.key">
|
||||
<router-link
|
||||
:to="{ name: btnItem.router }"
|
||||
:to="{ name: route.router }"
|
||||
replace
|
||||
v-slot="{ href, navigate, isActive, isExactActive }"
|
||||
custom
|
||||
@ -10,25 +10,22 @@
|
||||
<div
|
||||
:class="[
|
||||
'navbar-btn',
|
||||
(isActive && ['skinsettings', 'edit'].includes(btnItem.key)) || isExactActive
|
||||
(isActive && ['skinsettings', 'edit'].includes(route.key)) || isExactActive
|
||||
? 'router-link-exact-active'
|
||||
: ''
|
||||
]"
|
||||
>
|
||||
<i class="iconfont" :class="[btnItem.icon]"></i>
|
||||
<i class="iconfont" :class="[route.icon]"></i>
|
||||
<a :href="href" @click="navigate"
|
||||
><span>{{ btnItem.text }}</span></a
|
||||
><span>{{ route.text }}</span></a
|
||||
>
|
||||
</div>
|
||||
</router-link>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const btnList = reactive([
|
||||
const routes = [
|
||||
{
|
||||
icon: 'icon-wenjuanbianji',
|
||||
text: '问卷编辑',
|
||||
@ -50,9 +47,8 @@ const btnList = reactive([
|
||||
key: 'skinsettings',
|
||||
next: true
|
||||
}
|
||||
])
|
||||
]
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
display: flex;
|
||||
|
@ -46,7 +46,6 @@ const hideFullTitle = () => {
|
||||
tooltipVisible.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title-container {
|
||||
position: relative;
|
||||
|
@ -8,26 +8,14 @@
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
<script>
|
||||
import TypeList from './components/TypeList.vue'
|
||||
import QuestionCatalog from './components/QuestionCatalog.vue'
|
||||
|
||||
export default {
|
||||
name: 'CatalogPanel',
|
||||
data() {
|
||||
return {
|
||||
tabSelected: '0'
|
||||
}
|
||||
},
|
||||
components: {
|
||||
TypeList,
|
||||
QuestionCatalog
|
||||
},
|
||||
methods: {}
|
||||
}
|
||||
const tabSelected = ref<string>('0')
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tab-box {
|
||||
width: 300px;
|
||||
|
@ -11,47 +11,31 @@
|
||||
class="question-config-form"
|
||||
:form-config-list="formConfigList"
|
||||
:module-config="moduleConfig"
|
||||
@form-change="onFormChange"
|
||||
@form-change="handleFormChange"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
<script>
|
||||
import SetterField from '@/management/pages/edit/components/SetterField.vue'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'SetterPanel',
|
||||
data() {
|
||||
return {
|
||||
tabSelected: '0'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentEditOne() {
|
||||
return this.$store.state?.edit?.currentEditOne
|
||||
},
|
||||
...mapGetters({
|
||||
formConfigList: 'edit/formConfigList',
|
||||
moduleConfig: 'edit/moduleConfig',
|
||||
currentEditKey: 'edit/currentEditKey',
|
||||
currentEditMeta: 'edit/currentEditMeta'
|
||||
})
|
||||
},
|
||||
components: {
|
||||
SetterField
|
||||
},
|
||||
methods: {
|
||||
onFormChange(data) {
|
||||
const store = useStore()
|
||||
|
||||
const currentEditOne = computed(() => store.state?.edit?.currentEditOne)
|
||||
const formConfigList = computed(() => store.getters['edit/formConfigList'])
|
||||
const moduleConfig = computed(() => store.getters['edit/moduleConfig'])
|
||||
const currentEditKey = computed(() => store.getters['edit/currentEditKey'])
|
||||
const currentEditMeta = computed(() => store.getters['edit/currentEditMeta'])
|
||||
|
||||
const handleFormChange = (data: any) => {
|
||||
const { key, value } = data
|
||||
const resultKey = `${this.currentEditKey}.${key}`
|
||||
this.$store.dispatch('edit/changeSchema', { key: resultKey, value })
|
||||
}
|
||||
}
|
||||
const resultKey = `${currentEditKey.value}.${key}`
|
||||
store.dispatch('edit/changeSchema', { key: resultKey, value })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.setter-wrapper {
|
||||
width: 360px;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="question-catalog-item" @click="onSelect()">
|
||||
<div class="question-catalog-item" @click="handleSelect()">
|
||||
<div class="iconfont icon-tuodong draggHandle"></div>
|
||||
<div class="catalog-item-body">
|
||||
<div class="catalog-item-index" v-if="showIndex">{{ indexNumber }}.</div>
|
||||
@ -7,37 +7,29 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
title: string
|
||||
indexNumber: string | number
|
||||
showIndex: boolean
|
||||
}
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'CatalogItem',
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
indexNumber: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
showIndex: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
components: {},
|
||||
methods: {
|
||||
onSelect() {
|
||||
this.$emit('select')
|
||||
}
|
||||
interface Emit {
|
||||
(ev: 'select'): void
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
title: '',
|
||||
indexNumber: '',
|
||||
showIndex: false
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const handleSelect = () => {
|
||||
emit('select')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.question-catalog-item {
|
||||
position: relative;
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="question-catalog-wrapper">
|
||||
<draggable
|
||||
:list="renderData"
|
||||
@end="onDragEnd"
|
||||
@end="handleDragEnd"
|
||||
itemKey="field"
|
||||
handle=".draggHandle"
|
||||
host-class="catalog-item-ghost"
|
||||
@ -12,50 +12,43 @@
|
||||
:title="element.title"
|
||||
:indexNumber="element.indexNumber"
|
||||
:showIndex="element.showIndex"
|
||||
@select="onSelect(index)"
|
||||
@select="handleSelect(index)"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import draggable from 'vuedraggable'
|
||||
|
||||
import CatalogItem from './CatalogItem.vue'
|
||||
import { filterQuestionPreviewData } from '@/management/utils/index'
|
||||
|
||||
export default {
|
||||
name: 'QuestionCatalog',
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
questionDataList() {
|
||||
return this.$store.state.edit.schema.questionDataList
|
||||
},
|
||||
renderData() {
|
||||
return filterQuestionPreviewData(this.questionDataList) || []
|
||||
const store = useStore()
|
||||
const renderData = computed(() => {
|
||||
const questions = store.state.edit.schema.questionDataList
|
||||
return filterQuestionPreviewData(questions) || []
|
||||
})
|
||||
|
||||
const handleDragEnd = ({ newIndex, oldIndex }: any) => {
|
||||
const currentActivityKey = store.state.edit.currentEditOne
|
||||
|
||||
if (currentActivityKey === oldIndex) {
|
||||
handleSelect(newIndex)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
draggable,
|
||||
CatalogItem
|
||||
},
|
||||
methods: {
|
||||
onDragEnd(data) {
|
||||
const { newIndex, oldIndex } = data
|
||||
this.$store.dispatch('edit/moveQuestion', {
|
||||
|
||||
store.dispatch('edit/moveQuestion', {
|
||||
index: oldIndex,
|
||||
range: newIndex - oldIndex
|
||||
})
|
||||
},
|
||||
onSelect(index) {
|
||||
this.$store.commit('edit/setCurrentEditOne', index)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSelect = (idx: number) => {
|
||||
store.commit('edit/setCurrentEditOne', idx)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.question-catalog-wrapper {
|
||||
padding-bottom: 400px; // 考试题有个上拉框会盖住,改成和题型一致的
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="question-config">
|
||||
<div class="question-config-wrapper">
|
||||
<div class="question-config-main">
|
||||
<div v-for="form of renderData" :key="form.key" class="config-item">
|
||||
<div v-for="form of setterList" :key="form.key" class="config-item">
|
||||
<div class="config-title">
|
||||
<span>
|
||||
{{ form.title }}
|
||||
@ -16,17 +16,17 @@
|
||||
>
|
||||
<template v-for="(item, index) in form.formList">
|
||||
<FormItem
|
||||
v-if="item.type && !item.hidden && Boolean(register[item.type])"
|
||||
v-if="item.type && !item.hidden && Boolean(registerTypes[item.type])"
|
||||
:key="index"
|
||||
:form-config="item"
|
||||
:style="item.style"
|
||||
>
|
||||
<Component
|
||||
v-if="Boolean(register[item.type])"
|
||||
:is="item.type"
|
||||
v-if="Boolean(registerTypes[item.type])"
|
||||
:is="components[item.type]"
|
||||
:module-config="form.dataConfig"
|
||||
:form-config="item"
|
||||
@form-change="onFormChange"
|
||||
@form-change="handleFormChange"
|
||||
/>
|
||||
</FormItem>
|
||||
</template>
|
||||
@ -36,92 +36,83 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, onMounted, shallowRef } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { cloneDeep as _cloneDeep, isArray as _isArray, get as _get } from 'lodash-es'
|
||||
|
||||
<script>
|
||||
import baseConfig from './config/baseConfig'
|
||||
import baseFormConfig from './config/baseFormConfig'
|
||||
import FormItem from '@/materials/setters/widgets/FormItem.vue'
|
||||
import setterLoader from '@/materials/setters/setterLoader'
|
||||
import { cloneDeep as _cloneDeep, isArray as _isArray, get as _get } from 'lodash-es'
|
||||
|
||||
export default {
|
||||
name: 'SettingPanel',
|
||||
components: {
|
||||
FormItem
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formConfigList: [],
|
||||
register: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onFormChange(data) {
|
||||
this.$store.dispatch('edit/changeSchema', {
|
||||
key: data.key,
|
||||
value: data.value
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
allSetters() {
|
||||
const formList = this.formConfigList.map((item) => item.formList).flat()
|
||||
const typeList = formList.map((item) => ({
|
||||
type: item.type,
|
||||
path: item.path || item.type
|
||||
}))
|
||||
const formConfigList = ref<Array<any>>([])
|
||||
const components = shallowRef<any>({})
|
||||
const registerTypes = ref<any>({})
|
||||
const setterList = computed(() => {
|
||||
const list = _cloneDeep(formConfigList.value)
|
||||
|
||||
return typeList
|
||||
},
|
||||
renderData() {
|
||||
// todo: 1、给formConfig组装value;2、新增dataConfig字段
|
||||
const formConfigList = _cloneDeep(this.formConfigList)
|
||||
return list.map((form) => {
|
||||
const dataConfig: any = {}
|
||||
|
||||
return formConfigList.map((form) => {
|
||||
const dataConfig = {}
|
||||
for (const formItem of form.formList) {
|
||||
const formKey = formItem.key ? formItem.key : formItem.keys
|
||||
let formValue
|
||||
if (_isArray(formKey)) {
|
||||
formValue = []
|
||||
for (const key of formKey) {
|
||||
const val = _get(this.$store.state.edit.schema, key, formItem.value)
|
||||
const val = _get(store.state.edit.schema, key, formItem.value)
|
||||
formValue.push(val)
|
||||
dataConfig[key] = val
|
||||
}
|
||||
} else {
|
||||
formValue = _get(this.$store.state.edit.schema, formKey, formItem.value)
|
||||
formValue = _get(store.state.edit.schema, formKey, formItem.value)
|
||||
dataConfig[formKey] = formValue
|
||||
}
|
||||
formItem.value = formValue
|
||||
}
|
||||
|
||||
form.dataConfig = dataConfig
|
||||
|
||||
return form
|
||||
})
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
this.formConfigList = baseConfig.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
formList: item.formList.map((key) => baseFormConfig[key]).filter((config) => !!config)
|
||||
}
|
||||
})
|
||||
|
||||
const comps = await setterLoader.loadComponents(this.allSetters)
|
||||
const store = useStore()
|
||||
const handleFormChange = (data: any) => {
|
||||
store.dispatch('edit/changeSchema', {
|
||||
key: data.key,
|
||||
value: data.value
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
formConfigList.value = baseConfig.map((item) => ({
|
||||
...item,
|
||||
formList: item.formList.map((key) => (baseFormConfig as any)[key]).filter((config) => !!config)
|
||||
}))
|
||||
|
||||
const formList = formConfigList.value.map((item) => item.formList).flat()
|
||||
const typeList = formList.map((item) => ({
|
||||
type: item.type,
|
||||
path: item.path || item.type
|
||||
}))
|
||||
|
||||
const comps = await setterLoader.loadComponents(typeList)
|
||||
for (const comp of comps) {
|
||||
if (!comp) {
|
||||
continue
|
||||
}
|
||||
|
||||
const { type, component, err } = comp
|
||||
if (!err) {
|
||||
const componentName = component.name
|
||||
this.$options.components[componentName] = component
|
||||
this.register[type] = componentName
|
||||
}
|
||||
}
|
||||
|
||||
components.value[type] = component
|
||||
registerTypes.value[type] = componentName
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -4,24 +4,15 @@
|
||||
<p class="title-msg" v-safe-html="resultText"></p>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'OverTime',
|
||||
props: {
|
||||
moduleConfig: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
resultText() {
|
||||
return this.moduleConfig?.submitConf?.msgContent?.msg_9001 || '问卷已过期'
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
@ -9,24 +9,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SuccessContent',
|
||||
props: {
|
||||
moduleConfig: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
successText() {
|
||||
return this.moduleConfig?.submitConf?.msgContent?.msg_200 || ''
|
||||
}
|
||||
}
|
||||
interface Props {
|
||||
moduleConfig: any
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
const successText = computed(() => props.moduleConfig?.msgContent?.msg_200 || '')
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/*成功页面跳转全屏展示浮层*/
|
||||
.suc-page {
|
||||
|
@ -6,7 +6,7 @@
|
||||
v-for="(status, index) in statusList"
|
||||
:key="index"
|
||||
class="status-item"
|
||||
@click="filterDisabledStatus({ type: status.type })"
|
||||
@click="handleChangePreview({ type: status.type })"
|
||||
>
|
||||
<span>{{ status.title }}</span>
|
||||
<div class="preview-item">
|
||||
@ -16,16 +16,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
<script setup lang="ts">
|
||||
import { useStore } from 'vuex'
|
||||
import { EDIT_STATUS_MAP } from '../enum'
|
||||
|
||||
export default {
|
||||
name: 'CatalogPanel',
|
||||
data() {
|
||||
return {
|
||||
statusList: [
|
||||
const store = useStore()
|
||||
const statusList = [
|
||||
{
|
||||
type: EDIT_STATUS_MAP.SUCCESS,
|
||||
title: '提交成功',
|
||||
@ -37,20 +33,15 @@ export default {
|
||||
previewImg: '/imgs/icons/overtime.webp'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
changeStatusPreview: 'edit/changeStatusPreview'
|
||||
}),
|
||||
filterDisabledStatus(data) {
|
||||
this.changeStatusPreview(data)
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -2,43 +2,35 @@
|
||||
<div class="result-config-preview">
|
||||
<div class="result-page-wrap">
|
||||
<div class="result-page">
|
||||
<component :is="currentEditStatus" :key="currentEditStatus" :module-config="moduleConfig" />
|
||||
<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'
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import SuccessContent from '../components/SuccessContent.vue'
|
||||
import OverTime from '../components/OverTime.vue'
|
||||
import { EDIT_STATUS_MAP } from '../enum'
|
||||
import { get as _get } from 'lodash-es'
|
||||
|
||||
export default {
|
||||
name: 'PreviewPanel',
|
||||
props: {},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
currentEditStatus: (state) => state.edit.currentEditStatus,
|
||||
submitConf: (state) => _get(state, 'edit.schema.submitConf')
|
||||
}),
|
||||
moduleConfig() {
|
||||
return {
|
||||
submitConf: this.submitConf
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
const components = {
|
||||
[EDIT_STATUS_MAP.SUCCESS]: SuccessContent,
|
||||
[EDIT_STATUS_MAP.OVERTIME]: OverTime
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
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%;
|
||||
|
@ -4,82 +4,67 @@
|
||||
{{ currentEditText }}
|
||||
</div>
|
||||
<el-form class="question-config-form" label-position="top" @submit.prevent>
|
||||
<template v-for="(item, index) in formFieldData" :key="index">
|
||||
<template v-for="(item, index) in formFields" :key="index">
|
||||
<FormItem
|
||||
v-if="item.type && !item.hidden && Boolean(register[item.type])"
|
||||
v-if="item.type && !item.hidden && Boolean(registerTypes[item.type])"
|
||||
:form-config="item"
|
||||
:style="item.style"
|
||||
>
|
||||
<Component
|
||||
v-if="Boolean(register[item.type])"
|
||||
:is="item.type"
|
||||
v-if="Boolean(registerTypes[item.type])"
|
||||
:is="components[item.type]"
|
||||
:module-config="moduleConfig"
|
||||
:form-config="item"
|
||||
@form-change="onFormChange"
|
||||
@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'
|
||||
|
||||
<script>
|
||||
import FormItem from '@/materials/setters/widgets/FormItem.vue'
|
||||
import setterLoader from '@/materials/setters/setterLoader'
|
||||
import statusConfig from '../config/statusConfig'
|
||||
import { mapState } from 'vuex'
|
||||
import { get as _get, pick as _pick } from 'lodash-es'
|
||||
|
||||
const textMap = {
|
||||
Success: '提交成功页面配置',
|
||||
OverTime: '问卷过期页面配置'
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'SetterPanel',
|
||||
components: {
|
||||
FormItem
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
register: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
formFieldData() {
|
||||
const formList = statusConfig[this.currentEditStatus] || []
|
||||
return formList.map((item) => {
|
||||
const value = _get(this.moduleConfig, item.key, item.value)
|
||||
return {
|
||||
...item,
|
||||
value
|
||||
}
|
||||
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
|
||||
})
|
||||
},
|
||||
currentEditText() {
|
||||
return textMap[this.currentEditStatus] || ''
|
||||
},
|
||||
...mapState({
|
||||
currentEditStatus: (state) => state.edit.currentEditStatus,
|
||||
submitConf: (state) => _get(state, 'edit.schema.submitConf')
|
||||
}),
|
||||
moduleConfig() {
|
||||
return this.submitConf
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
formFieldData: {
|
||||
immediate: true,
|
||||
handler(newVal) {
|
||||
if (Array.isArray(newVal)) {
|
||||
this.handleComponentRegister(newVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async handleComponentRegister(formFieldData) {
|
||||
const setters = formFieldData.map((item) => item.type)
|
||||
|
||||
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) => {
|
||||
@ -88,50 +73,29 @@ export default {
|
||||
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
|
||||
this.$options.components[componentName] = component
|
||||
this.register[type] = componentName
|
||||
|
||||
components.value[type] = component
|
||||
registerTypes.value[type] = componentName
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
getValueFromModuleConfig(item) {
|
||||
const { key, keys } = item
|
||||
const moduleConfig = this.moduleConfig
|
||||
let result = item
|
||||
if (key) {
|
||||
result = {
|
||||
...item,
|
||||
value: _get(moduleConfig, key, item.value)
|
||||
}
|
||||
}
|
||||
if (keys) {
|
||||
result = {
|
||||
...item,
|
||||
value: _pick(moduleConfig, keys)
|
||||
}
|
||||
}
|
||||
return result
|
||||
},
|
||||
onFormChange(data) {
|
||||
const { key, value } = data
|
||||
const resultKey = `submitConf.${key}`
|
||||
this.$store.dispatch('edit/changeSchema', { key: resultKey, value })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.question-edit-form {
|
||||
width: 360px;
|
||||
|
@ -8,7 +8,7 @@
|
||||
:class="[groupName === item.value ? 'current' : '', 'tag']"
|
||||
type="info"
|
||||
:key="item.value"
|
||||
@click="() => changeGroup(item.value)"
|
||||
@click="() => handleChangeGroup(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-tag>
|
||||
@ -25,75 +25,63 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
import skinPresets from '@/management/config/skinPresets.js'
|
||||
export default {
|
||||
name: 'CatalogPanel',
|
||||
data() {
|
||||
return {
|
||||
skinPresets: [],
|
||||
groupName: 'temp'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
bannerList() {
|
||||
return this.$store?.state?.bannerList || []
|
||||
},
|
||||
groupList() {
|
||||
return Object.keys(this.bannerList).map((key) => {
|
||||
return {
|
||||
label: this.bannerList[key].name,
|
||||
|
||||
const store = useStore()
|
||||
const groupName = ref<string>('temp')
|
||||
const bannerList = computed(() => store?.state?.bannerList || [])
|
||||
const groupList = computed(() =>
|
||||
Object.keys(bannerList.value).map((key) => ({
|
||||
label: bannerList.value[key].name,
|
||||
value: key
|
||||
}
|
||||
})
|
||||
},
|
||||
currentBannerList() {
|
||||
const arr = Object.keys(this.bannerList)
|
||||
}))
|
||||
)
|
||||
const currentBannerList = computed(() => {
|
||||
const arr = Object.keys(bannerList.value)
|
||||
.map((key) => {
|
||||
return this.bannerList[key]
|
||||
return bannerList.value[key]
|
||||
})
|
||||
.map((data) => {
|
||||
return data.list.map((item) => {
|
||||
return data.list.map((item: any) => {
|
||||
item.group = data.key
|
||||
return item
|
||||
})
|
||||
})
|
||||
|
||||
const allbanner = arr.reduce((acc, curr) => {
|
||||
return acc.concat(curr)
|
||||
}, [])
|
||||
return allbanner.filter((item) => {
|
||||
if (this.groupName === 'temp') {
|
||||
|
||||
return allbanner.filter((item: any) => {
|
||||
if (groupName.value === 'temp') {
|
||||
return true
|
||||
} else {
|
||||
return item.group === this.groupName
|
||||
return item.group === groupName.value
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const handleChangeGroup = (value: string) => {
|
||||
groupName.value = value
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
...mapActions({
|
||||
changeThemePreset: 'edit/changeThemePreset'
|
||||
}),
|
||||
changeGroup(value) {
|
||||
this.groupName = value
|
||||
},
|
||||
changePreset(banner) {
|
||||
|
||||
const changePreset = (banner: any) => {
|
||||
const name = banner.group + '-' + banner.title
|
||||
let presets = {
|
||||
'bannerConf.bannerConfig.bgImage': banner.src,
|
||||
'skinConf.themeConf.color': '#FAA600',
|
||||
'skinConf.backgroundConf.color': '#fff'
|
||||
}
|
||||
if (skinPresets[name]) {
|
||||
presets = Object.assign(presets, skinPresets[name])
|
||||
|
||||
if ((skinPresets as any)[name]) {
|
||||
presets = Object.assign(presets, (skinPresets as any)[name])
|
||||
}
|
||||
|
||||
this.changeThemePreset(presets)
|
||||
}
|
||||
}
|
||||
store.dispatch('edit/changeThemePreset', presets)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@ -14,7 +14,7 @@
|
||||
:module-config="_get(schema, collapse.key, {})"
|
||||
@form-change="
|
||||
(key) => {
|
||||
onFormChange(key, collapse.key)
|
||||
handleFormChange(key, collapse.key)
|
||||
}
|
||||
"
|
||||
/>
|
||||
@ -23,37 +23,24 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<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'
|
||||
import { mapState } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
export default {
|
||||
name: 'SetterPanel',
|
||||
components: {
|
||||
SetterField
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
collapse: '',
|
||||
skinConfig
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
skinConf: (state) => _get(state, 'edit.schema.skinConf'),
|
||||
schema: (state) => _get(state, 'edit.schema')
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
_get,
|
||||
onFormChange(data, collapse) {
|
||||
|
||||
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}`
|
||||
this.$store.dispatch('edit/changeSchema', { key: resultKey, value })
|
||||
}
|
||||
}
|
||||
|
||||
store.dispatch('edit/changeSchema', { key: resultKey, value })
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@ -5,15 +5,18 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, provide } from 'vue'
|
||||
import RulePanel from '../../modules/logicModule/RulePanel.vue'
|
||||
import { filterQuestionPreviewData } from '@/management/utils/index'
|
||||
import { useStore } from 'vuex'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
import RulePanel from '../../modules/logicModule/RulePanel.vue'
|
||||
import { filterQuestionPreviewData } from '@/management/utils/index'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const questionDataList = computed(() => {
|
||||
return store.state.edit.schema.questionDataList
|
||||
})
|
||||
|
||||
const renderData = computed(() => {
|
||||
return filterQuestionPreviewData(cloneDeep(questionDataList.value))
|
||||
})
|
||||
|
@ -11,20 +11,11 @@
|
||||
</template>
|
||||
</CommonTemplate>
|
||||
</template>
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import CommonTemplate from '../../components/CommonTemplate.vue'
|
||||
import CatalogPanel from '../../modules/questionModule/CatalogPanel.vue'
|
||||
import PreviewPanel from '../../modules/questionModule/PreviewPanel.vue'
|
||||
import SetterPanel from '../../modules/questionModule/SetterPanel.vue'
|
||||
export default {
|
||||
name: 'editIndex',
|
||||
components: {
|
||||
CommonTemplate,
|
||||
CatalogPanel,
|
||||
PreviewPanel,
|
||||
SetterPanel
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.navbar {
|
||||
|
@ -3,24 +3,21 @@
|
||||
<div class="navbar-tab">
|
||||
<el-radio-group v-model="activeRouter">
|
||||
<el-radio-button
|
||||
v-for="btnItem in btnList"
|
||||
:key="btnItem.router"
|
||||
:label="btnItem.text"
|
||||
:value="btnItem.router"
|
||||
v-for="item in routes"
|
||||
:key="item.router"
|
||||
:label="item.text"
|
||||
:value="item.router"
|
||||
/>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'QuestionPage',
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
activeRouter: this.$route.name,
|
||||
btnList: [
|
||||
<script setup lang="ts">
|
||||
import { watch, ref } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
text: '内容设置',
|
||||
router: 'QuestionEditIndex',
|
||||
@ -32,16 +29,20 @@ export default {
|
||||
key: 'logicEdit'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const activeRouter = ref(route.name)
|
||||
|
||||
watch(
|
||||
activeRouter,
|
||||
(val: any) => {
|
||||
router.push({ name: val })
|
||||
},
|
||||
watch: {
|
||||
activeRouter: {
|
||||
handler(val) {
|
||||
this.$router.push({ name: val })
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.question-content {
|
||||
|
@ -3,17 +3,9 @@
|
||||
<SettingPanel></SettingPanel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import SettingPanel from '../../modules/settingModule/SettingPanel.vue'
|
||||
export default {
|
||||
name: 'SettingPage',
|
||||
components: {
|
||||
SettingPanel
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.setting-page {
|
||||
width: 100%;
|
||||
|
@ -11,24 +11,20 @@
|
||||
</template>
|
||||
</CommonTemplate>
|
||||
</template>
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
import CommonTemplate from '../../components/CommonTemplate.vue'
|
||||
import CatalogPanel from '../../modules/settingModule/skin/CatalogPanel.vue'
|
||||
import PreviewPanel from '../../modules/settingModule/skin/PreviewPanel.vue'
|
||||
import SetterPanel from '../../modules/settingModule/skin/SetterPanel.vue'
|
||||
|
||||
export default {
|
||||
name: 'ContentPage',
|
||||
components: {
|
||||
CommonTemplate,
|
||||
CatalogPanel,
|
||||
PreviewPanel,
|
||||
SetterPanel
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('getBannerData')
|
||||
}
|
||||
}
|
||||
const store = useStore()
|
||||
|
||||
onMounted(() => {
|
||||
store.dispatch('getBannerData')
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.navbar {
|
||||
|
@ -11,20 +11,9 @@
|
||||
</template>
|
||||
</CommonTemplate>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import CommonTemplate from '../../components/CommonTemplate.vue'
|
||||
import ResultCatalog from '../../modules/settingModule/result/CatalogPanel.vue'
|
||||
import ResultPreview from '../../modules/settingModule/result/PreviewPanel.vue'
|
||||
import ResultSetter from '../../modules/settingModule/result/SetterPanel.vue'
|
||||
|
||||
export default {
|
||||
name: 'ResultPage',
|
||||
components: {
|
||||
CommonTemplate,
|
||||
ResultCatalog,
|
||||
ResultPreview,
|
||||
ResultSetter
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -3,24 +3,21 @@
|
||||
<div class="navbar-tab">
|
||||
<el-radio-group v-model="activeRouter">
|
||||
<el-radio-button
|
||||
v-for="btnItem in btnList"
|
||||
:key="btnItem.router"
|
||||
:label="btnItem.text"
|
||||
:value="btnItem.router"
|
||||
v-for="item in routes"
|
||||
:key="item.router"
|
||||
:label="item.text"
|
||||
:value="item.router"
|
||||
/>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'skinPage',
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
activeRouter: this.$route.name,
|
||||
btnList: [
|
||||
<script setup lang="ts">
|
||||
import { watch, ref } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
text: '内容页',
|
||||
router: 'QuestionSkinSetting',
|
||||
@ -33,16 +30,20 @@ export default {
|
||||
key: 'status'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const activeRouter = ref(route.name)
|
||||
|
||||
watch(
|
||||
activeRouter,
|
||||
(val: any) => {
|
||||
router.push({ name: val })
|
||||
},
|
||||
watch: {
|
||||
activeRouter: {
|
||||
handler(val) {
|
||||
this.$router.push({ name: val })
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.skin-content {
|
||||
|
Loading…
Reference in New Issue
Block a user