feat: edit vuex迁移pinia (#325)

* build: dev reload optimized

* feat: edit store change pinia

* feat: store中状态修改增加方法

* feat: js改为ts

---------

Co-authored-by: jiangchunfu <jiangchunfu@kaike.la>
This commit is contained in:
Jiangchunfu 2024-07-10 14:05:41 +08:00 committed by GitHub
parent 64a1caf0dd
commit 1a15faad42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 494 additions and 152 deletions

View File

@ -1,17 +1,19 @@
import { computed } from 'vue' import { computed } from 'vue'
import store from '@/management/store' import { storeToRefs } from 'pinia'
import { useEditStore } from '@/management/stores/edit'
import { cleanRichText } from '@/common/xss' import { cleanRichText } from '@/common/xss'
export const useQuestionInfo = (field) => { export const useQuestionInfo = (field) => {
const editStore = useEditStore()
const { questionDataList } = storeToRefs(editStore)
const getQuestionTitle = computed(() => { const getQuestionTitle = computed(() => {
const questionDataList = store.state.edit.schema.questionDataList
return () => { return () => {
return questionDataList.find((item) => item.field === field)?.title return questionDataList.value.find((item) => item.field === field)?.title
} }
}) })
const getOptionTitle = computed(() => { const getOptionTitle = computed(() => {
const questionDataList = store.state.edit.schema.questionDataList
return (value) => { return (value) => {
const options = questionDataList.find((item) => item.field === field)?.options || [] const options = questionDataList.value.find((item) => item.field === field)?.options || []
if (value instanceof Array) { if (value instanceof Array) {
return options return options
.filter((item) => value.includes(item.hash)) .filter((item) => value.includes(item.hash))

View File

@ -1,5 +1,5 @@
// 引入防抖函数 // 引入防抖函数
import _debounce from 'lodash/debounce' import { debounce as _debounce } from 'lodash-es'
/** /**
* @description: 监听元素尺寸变化 * @description: 监听元素尺寸变化
* @param {*} el 元素dom * @param {*} el 元素dom

View File

@ -34,7 +34,7 @@
<script setup> <script setup>
import { reactive, toRefs, computed, watch, onMounted, onUnmounted, ref } from 'vue' import { reactive, toRefs, computed, watch, onMounted, onUnmounted, ref } from 'vue'
import _cloneDeep from 'lodash/cloneDeep' import { cloneDeep as _cloneDeep } from 'lodash-es'
import { import {
separateItemListHead, separateItemListHead,
summaryType, summaryType,

View File

@ -34,7 +34,7 @@
<script> <script>
import { computed, defineComponent, ref, getCurrentInstance } from 'vue' import { computed, defineComponent, ref, getCurrentInstance } from 'vue'
import { useStore } from 'vuex' import { useEditStore } from '@/management/stores/edit'
import QuestionContainerB from '@/materials/questions/QuestionContainerB' import QuestionContainerB from '@/materials/questions/QuestionContainerB'
import QuestionWrapper from '@/management/pages/edit/components/QuestionWrapper.vue' import QuestionWrapper from '@/management/pages/edit/components/QuestionWrapper.vue'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
@ -61,13 +61,13 @@ export default defineComponent({
}, },
emits: ['change', 'select', 'changeSeq'], emits: ['change', 'select', 'changeSeq'],
setup(props, { emit }) { setup(props, { emit }) {
const store = useStore() const editStore = useEditStore()
const renderData = computed({ const renderData = computed({
get() { get() {
return filterQuestionPreviewData(props.questionDataList) return filterQuestionPreviewData(props.questionDataList)
}, },
set(questionDataList) { set(value) {
store.commit('edit/setQuestionDataList', questionDataList) editStore.setQuestionDataList(value)
} }
}) })
const handleSelect = (index) => { const handleSelect = (index) => {

View File

@ -17,8 +17,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { useStore } from 'vuex' import { useEditStore } from '@/management/stores/edit'
import { get as _get } from 'lodash-es'
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'
@ -28,8 +27,8 @@ import PreviewPanel from '../modules/contentModule/PreviewPanel.vue'
import SavePanel from '../modules/contentModule/SavePanel.vue' import SavePanel from '../modules/contentModule/SavePanel.vue'
import PublishPanel from '../modules/contentModule/PublishPanel.vue' import PublishPanel from '../modules/contentModule/PublishPanel.vue'
const store = useStore() const editStore = useEditStore()
const title = computed(() => _get(store.state, 'edit.schema.metaData.title')) const title = computed(() => (editStore.schema?.metaData as any)?.title || '')
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.nav { .nav {

View File

@ -15,7 +15,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue' import { onMounted } from 'vue'
import { useStore } from 'vuex' import { useEditStore } from '@/management/stores/edit'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
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'
@ -26,16 +26,17 @@ import Navbar from './components/ModuleNavbar.vue'
import { initShowLogicEngine } from '@/management/hooks/useShowLogicEngine' import { initShowLogicEngine } from '@/management/hooks/useShowLogicEngine'
const store = useStore() const editStore = useEditStore()
const { schema, init, setSurveyId } = editStore
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
onMounted(async () => { onMounted(async () => {
store.commit('edit/setSurveyId', route.params.id) setSurveyId(route.params.id as string)
try { try {
await store.dispatch('edit/init') await init()
await initShowLogicEngine(store.state.edit.schema.logicConf.showLogicConf || {}) await initShowLogicEngine(schema.logicConf.showLogicConf || {})
} catch (err: any) { } catch (err: any) {
ElMessage.error(err.message) ElMessage.error(err.message)

View File

@ -25,9 +25,9 @@
</el-popover> </el-popover>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, watch } from 'vue' import { ref, watch } from 'vue'
import { useStore } from 'vuex' import { storeToRefs } from 'pinia'
import { get as _get } from 'lodash-es' import { useEditStore } from '@/management/stores/edit'
import moment from 'moment' import moment from 'moment'
import 'moment/locale/zh-cn' import 'moment/locale/zh-cn'
moment.locale('zh-cn') moment.locale('zh-cn')
@ -44,21 +44,21 @@ const publishList = ref<Array<any>>([])
const currentTab = ref<'daily' | 'publish'>('daily') const currentTab = ref<'daily' | 'publish'>('daily')
const visible = ref<boolean>(false) const visible = ref<boolean>(false)
const store = useStore() const editStore = useEditStore()
const { surveyId, schemaUpdateTime } = storeToRefs(editStore)
const queryHistories = async () => { const queryHistories = async () => {
if (dirtyMonitor.value) { if (dirtyMonitor.value) {
loading.value = true loading.value = true
dirtyMonitor.value = false dirtyMonitor.value = false
const surveyId = _get(store.state, 'edit.surveyId')
const [dHis, pHis] = await Promise.all([ const [dHis, pHis] = await Promise.all([
getSurveyHistory({ getSurveyHistory({
surveyId, surveyId: surveyId.value,
historyType: 'dailyHis' historyType: 'dailyHis'
}), }),
getSurveyHistory({ getSurveyHistory({
surveyId, surveyId: surveyId.value,
historyType: 'publishHis' historyType: 'publishHis'
}) })
]).finally(() => { ]).finally(() => {
@ -81,7 +81,6 @@ const handlePopoverShow = async () => {
} }
const loading = ref<boolean>(false) const loading = ref<boolean>(false)
const dirtyMonitor = ref<boolean>(true) const dirtyMonitor = ref<boolean>(true)
const schemaUpdateTime = computed(() => _get(store.state, 'edit.schemaUpdateTime'))
watch( watch(
schemaUpdateTime, schemaUpdateTime,

View File

@ -5,7 +5,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import { useStore } from 'vuex' import { useEditStore } from '@/management/stores/edit'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
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'
@ -15,7 +15,8 @@ import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
import buildData from './buildData' import buildData from './buildData'
const isPublishing = ref<boolean>(false) const isPublishing = ref<boolean>(false)
const store = useStore() const editStore = useEditStore()
const { schema, changeSchema, getSchemaFromRemote } = editStore
const router = useRouter() const router = useRouter()
const updateLogicConf = () => { const updateLogicConf = () => {
@ -27,7 +28,7 @@ const updateLogicConf = () => {
showLogicEngine.value.validateSchema() showLogicEngine.value.validateSchema()
const showLogicConf = showLogicEngine.value.toJson() const showLogicConf = showLogicEngine.value.toJson()
// //
store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } }) changeSchema({ key: 'logicConf', value: { showLogicConf } })
} }
} }
@ -46,7 +47,7 @@ const handlePublish = async () => {
return return
} }
const saveData = buildData(store.state.edit.schema) const saveData = buildData(schema)
if (!saveData.surveyId) { if (!saveData.surveyId) {
isPublishing.value = false isPublishing.value = false
ElMessage.error('未获取到问卷id') ElMessage.error('未获取到问卷id')
@ -64,7 +65,7 @@ const handlePublish = async () => {
const publishRes: any = await publishSurvey({ surveyId: saveData.surveyId }) const publishRes: any = await publishSurvey({ surveyId: saveData.surveyId })
if (publishRes.code === 200) { if (publishRes.code === 200) {
ElMessage.success('发布成功') ElMessage.success('发布成功')
store.dispatch('edit/getSchemaFromRemote') getSchemaFromRemote()
router.push({ name: 'publish' }) router.push({ name: 'publish' })
} else { } else {
ElMessage.error(`发布失败 ${publishRes.errmsg}`) ElMessage.error(`发布失败 ${publishRes.errmsg}`)

View File

@ -15,8 +15,8 @@
</template> </template>
<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 { storeToRefs } from 'pinia'
import { get as _get } from 'lodash-es' import { useEditStore } from '@/management/stores/edit'
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'
@ -36,10 +36,12 @@ const saveText = computed(
})[autoSaveStatus.value] })[autoSaveStatus.value]
) )
const store = useStore() const editStore = useEditStore()
const { schemaUpdateTime } = storeToRefs(editStore)
const { schema, changeSchema } = editStore
const saveData = async () => { const saveData = async () => {
const saveData = buildData(store.state.edit.schema) const saveData = buildData(schema)
if (!saveData.surveyId) { if (!saveData.surveyId) {
ElMessage.error('未获取到问卷id') ElMessage.error('未获取到问卷id')
@ -59,7 +61,7 @@ const updateLogicConf = () => {
showLogicEngine.value.validateSchema() showLogicEngine.value.validateSchema()
const showLogicConf = showLogicEngine.value.toJson() const showLogicConf = showLogicEngine.value.toJson()
// //
store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } }) changeSchema({ key: 'logicConf', value: { showLogicConf } })
} }
} }
@ -128,7 +130,6 @@ const handleSave = async () => {
} }
} }
const schemaUpdateTime = computed(() => _get(store.state, 'edit.schemaUpdateTime'))
watch(schemaUpdateTime, () => { watch(schemaUpdateTime, () => {
triggerAutoSave() triggerAutoSave()
}) })

View File

@ -6,13 +6,13 @@
:bannerConf="bannerConf" :bannerConf="bannerConf"
:readonly="false" :readonly="false"
:is-selected="currentEditOne === 'mainTitle'" :is-selected="currentEditOne === 'mainTitle'"
@select="onSelectEditOne('mainTitle')" @select="setCurrentEditOne('mainTitle')"
@change="handleChange" @change="handleChange"
/> />
<MaterialGroup <MaterialGroup
:current-edit-one="parseInt(currentEditOne)" :current-edit-one="parseInt(currentEditOne)"
:questionDataList="questionDataList" :questionDataList="questionDataList"
@select="onSelectEditOne" @select="setCurrentEditOne"
@change="handleChange" @change="handleChange"
@changeSeq="onQuestionOperation" @changeSeq="onQuestionOperation"
ref="materialGroup" ref="materialGroup"
@ -22,7 +22,7 @@
:readonly="false" :readonly="false"
:skin-conf="skinConf" :skin-conf="skinConf"
:is-selected="currentEditOne === 'submit'" :is-selected="currentEditOne === 'submit'"
@select="onSelectEditOne('submit')" @select="setCurrentEditOne('submit')"
/> />
</div> </div>
</div> </div>
@ -30,24 +30,23 @@
</template> </template>
<script setup> <script setup>
import { computed, ref, watch } from 'vue' import { computed, ref, watch, toRefs } from 'vue'
import communalLoader from '@materials/communals/communalLoader.js' import communalLoader from '@materials/communals/communalLoader.js'
import MaterialGroup from '@/management/pages/edit/components/MaterialGroup.vue' import MaterialGroup from '@/management/pages/edit/components/MaterialGroup.vue'
import { useStore } from 'vuex' import { storeToRefs } from 'pinia'
import { useEditStore } from '@/management/stores/edit'
const MainTitle = communalLoader.loadComponent('MainTitle') const MainTitle = communalLoader.loadComponent('MainTitle')
const SubmitButton = communalLoader.loadComponent('SubmitButton') const SubmitButton = communalLoader.loadComponent('SubmitButton')
const store = useStore() const editStore = useEditStore()
const { questionDataList, currentEditOne, currentEditKey } = storeToRefs(editStore)
const { schema, changeSchema, moveQuestion, copyQuestion, deleteQuestion, setCurrentEditOne } =
editStore
const mainOperation = ref(null) const mainOperation = ref(null)
const materialGroup = ref(null) const materialGroup = ref(null)
const bannerConf = computed(() => store.state.edit.schema.bannerConf) const { bannerConf, submitConf, skinConf } = toRefs(schema)
const submitConf = computed(() => store.state.edit.schema.submitConf)
const skinConf = computed(() => store.state.edit.schema.skinConf)
const questionDataList = computed(() => store.state.edit.schema.questionDataList)
const currentEditOne = computed(() => store.state.edit.currentEditOne)
const currentEditKey = computed(() => store.getters['edit/currentEditKey'])
const autoScrollData = computed(() => { const autoScrollData = computed(() => {
return { return {
currentEditOne: currentEditOne.value, currentEditOne: currentEditOne.value,
@ -55,44 +54,39 @@ const autoScrollData = computed(() => {
} }
}) })
const onSelectEditOne = async (currentEditOne) => {
store.commit('edit/setCurrentEditOne', currentEditOne)
}
const handleChange = (data) => { const handleChange = (data) => {
if (currentEditOne.value === null) { if (currentEditOne.value === null) {
return return
} }
const { key, value } = data const { key, value } = data
const resultKey = `${currentEditKey.value}.${key}` const resultKey = `${currentEditKey.value}.${key}`
store.dispatch('edit/changeSchema', { key: resultKey, value }) changeSchema({ key: resultKey, value })
} }
const onMainClick = (e) => { const onMainClick = (e) => {
if (e.target === mainOperation.value) { if (e.target === mainOperation.value) {
store.commit('edit/setCurrentEditOne', null) setCurrentEditOne(null)
} }
} }
const onQuestionOperation = (data) => { const onQuestionOperation = (data) => {
switch (data.type) { switch (data.type) {
case 'move': case 'move':
store.dispatch('edit/moveQuestion', { moveQuestion({
index: data.index, index: data.index,
range: data.range range: data.range
}) })
break break
case 'delete': case 'delete':
store.dispatch('edit/deleteQuestion', { index: data.index }) deleteQuestion({ index: data.index })
break break
case 'copy': case 'copy':
store.dispatch('edit/copyQuestion', { index: data.index }) copyQuestion({ index: data.index })
break break
default: default:
break break
} }
} }
watch( watch(
skinConf, skinConf,
(newVal) => { (newVal) => {

View File

@ -17,23 +17,19 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { storeToRefs } from 'pinia'
import { useStore } from 'vuex' import { useEditStore } from '@/management/stores/edit'
import SetterField from '@/management/pages/edit/components/SetterField.vue' import SetterField from '@/management/pages/edit/components/SetterField.vue'
const store = useStore() const editStore = useEditStore()
const { currentEditOne, currentEditKey, currentEditMeta, formConfigList, moduleConfig } =
const currentEditOne = computed(() => store.state?.edit?.currentEditOne) storeToRefs(editStore)
const formConfigList = computed(() => store.getters['edit/formConfigList']) const { changeSchema } = editStore
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 handleFormChange = (data: any) => {
const { key, value } = data const { key, value } = data
const resultKey = `${currentEditKey.value}.${key}` const resultKey = `${currentEditKey.value}.${key}`
store.dispatch('edit/changeSchema', { key: resultKey, value }) changeSchema({ key: resultKey, value })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -12,7 +12,7 @@
:title="element.title" :title="element.title"
:indexNumber="element.indexNumber" :indexNumber="element.indexNumber"
:showIndex="element.showIndex" :showIndex="element.showIndex"
@select="handleSelect(index)" @select="setCurrentEditOne(index)"
/> />
</template> </template>
</draggable> </draggable>
@ -20,34 +20,30 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { useStore } from 'vuex' import { storeToRefs } from 'pinia'
import { useEditStore } from '@/management/stores/edit'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import CatalogItem from './CatalogItem.vue' import CatalogItem from './CatalogItem.vue'
import { filterQuestionPreviewData } from '@/management/utils/index' import { filterQuestionPreviewData } from '@/management/utils/index'
const store = useStore() const editStore = useEditStore()
const { questionDataList, currentEditOne } = storeToRefs(editStore)
const { moveQuestion, setCurrentEditOne } = editStore
const renderData = computed(() => { const renderData = computed(() => {
const questions = store.state.edit.schema.questionDataList return filterQuestionPreviewData(questionDataList.value) || []
return filterQuestionPreviewData(questions) || []
}) })
const handleDragEnd = ({ newIndex, oldIndex }: any) => { const handleDragEnd = ({ newIndex, oldIndex }: any) => {
const currentActivityKey = store.state.edit.currentEditOne if (currentEditOne.value === oldIndex) {
setCurrentEditOne(newIndex)
if (currentActivityKey === oldIndex) {
handleSelect(newIndex)
} }
store.dispatch('edit/moveQuestion', { moveQuestion({
index: oldIndex, index: oldIndex,
range: newIndex - oldIndex range: newIndex - oldIndex
}) })
} }
const handleSelect = (idx: number) => {
store.commit('edit/setCurrentEditOne', idx)
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.question-catalog-wrapper { .question-catalog-wrapper {

View File

@ -45,20 +45,24 @@ import { DND_GROUP } from '@/management/config/dnd'
import questionMenuConfig, { questionTypeList } from '@/management/config/questionMenuConfig' import questionMenuConfig, { questionTypeList } from '@/management/config/questionMenuConfig'
import { getQuestionByType } from '@/management/utils/index' import { getQuestionByType } from '@/management/utils/index'
import { useStore } from 'vuex' import { storeToRefs } from 'pinia'
import { get as _get, isNumber as _isNumber } from 'lodash-es' import { useEditStore } from '@/management/stores/edit'
import { isNumber as _isNumber } from 'lodash-es'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { QUESTION_TYPE } from '@/common/typeEnum.ts' import { QUESTION_TYPE } from '@/common/typeEnum.ts'
const store = useStore()
const editStore = useEditStore()
const { questionDataList, currentEditOne } = storeToRefs(editStore)
const { addQuestion, setCurrentEditOne } = editStore
const activeNames = ref([0, 1]) const activeNames = ref([0, 1])
const previewImg = ref('') const previewImg = ref('')
const isShowPreviewImage = ref(false) const isShowPreviewImage = ref(false)
const previewTop = ref(0) const previewTop = ref(0)
const questionDataList = computed(() => _get(store, 'state.edit.schema.questionDataList'))
const newQuestionIndex = computed(() => { const newQuestionIndex = computed(() => {
const currentEditOne = _get(store, 'state.edit.currentEditOne') const index = _isNumber(currentEditOne.value)
const index = _isNumber(currentEditOne) ? currentEditOne + 1 : questionDataList.value.length ? currentEditOne.value + 1
: questionDataList.value.length
return index return index
}) })
@ -78,8 +82,8 @@ const getNewQuestion = ({ type }) => {
const onQuestionType = ({ type }) => { const onQuestionType = ({ type }) => {
const newQuestion = getNewQuestion({ type }) const newQuestion = getNewQuestion({ type })
store.dispatch('edit/addQuestion', { question: newQuestion, index: newQuestionIndex.value }) addQuestion({ question: newQuestion, index: newQuestionIndex.value })
store.commit('edit/setCurrentEditOne', newQuestionIndex.value) setCurrentEditOne(newQuestionIndex.value)
} }
const showPreview = ({ snapshot }, id) => { const showPreview = ({ snapshot }, id) => {

View File

@ -38,7 +38,7 @@
</template> </template>
<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 { useEditStore } from '@/management/stores/edit'
import { cloneDeep as _cloneDeep, isArray as _isArray, get as _get } from 'lodash-es' import { cloneDeep as _cloneDeep, isArray as _isArray, get as _get } from 'lodash-es'
import baseConfig from './config/baseConfig' import baseConfig from './config/baseConfig'
@ -61,12 +61,12 @@ const setterList = computed(() => {
if (_isArray(formKey)) { if (_isArray(formKey)) {
formValue = [] formValue = []
for (const key of formKey) { for (const key of formKey) {
const val = _get(store.state.edit.schema, key, formItem.value) const val = _get(schema, key, formItem.value)
formValue.push(val) formValue.push(val)
dataConfig[key] = val dataConfig[key] = val
} }
} else { } else {
formValue = _get(store.state.edit.schema, formKey, formItem.value) formValue = _get(schema, formKey, formItem.value)
dataConfig[formKey] = formValue dataConfig[formKey] = formValue
} }
formItem.value = formValue formItem.value = formValue
@ -78,9 +78,10 @@ const setterList = computed(() => {
}) })
}) })
const store = useStore() const editStore = useEditStore()
const { schema, changeSchema } = editStore
const handleFormChange = (data: any) => { const handleFormChange = (data: any) => {
store.dispatch('edit/changeSchema', { changeSchema({
key: data.key, key: data.key,
value: data.value value: data.value
}) })

View File

@ -17,10 +17,12 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useStore } from 'vuex' import { useEditStore } from '@/management/stores/edit'
import { EDIT_STATUS_MAP } from '../enum' import { EDIT_STATUS_MAP } from '../enum'
import { storeToRefs } from 'pinia'
const store = useStore() const editStore = useEditStore()
const { currentEditStatus } = storeToRefs(editStore)
const statusList = [ const statusList = [
{ {
type: EDIT_STATUS_MAP.SUCCESS, type: EDIT_STATUS_MAP.SUCCESS,
@ -35,10 +37,8 @@ const statusList = [
] ]
const handleChangePreview = (data: any) => { const handleChangePreview = (data: any) => {
const currentStatus = store.state?.edit?.currentEditStatus if (currentEditStatus.value !== data.type) {
editStore.changeCurrentEditStatus(data.type)
if (currentStatus && currentStatus !== data.type) {
store.commit('edit/changeStatusPreview', data)
} }
} }
</script> </script>

View File

@ -12,9 +12,9 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { toRef } from 'vue'
import { useStore } from 'vuex' import { storeToRefs } from 'pinia'
import { get as _get } from 'lodash-es' import { useEditStore } from '@/management/stores/edit'
import SuccessContent from '../components/SuccessContent.vue' import SuccessContent from '../components/SuccessContent.vue'
import OverTime from '../components/OverTime.vue' import OverTime from '../components/OverTime.vue'
@ -25,11 +25,10 @@ const components = {
[EDIT_STATUS_MAP.OVERTIME]: OverTime [EDIT_STATUS_MAP.OVERTIME]: OverTime
} }
const store = useStore() const editStore = useEditStore()
const currentEditStatus = computed(() => store.state?.edit?.currentEditStatus) const { currentEditStatus } = storeToRefs(editStore)
const moduleConfig = computed(() => { const { schema } = editStore
return _get(store.state, 'edit.schema.submitConf') const moduleConfig = toRef(schema, 'submitConf')
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.result-config-preview { .result-config-preview {

View File

@ -23,8 +23,9 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, shallowRef } from 'vue' import { computed, ref, shallowRef, toRef } from 'vue'
import { useStore } from 'vuex' import { storeToRefs } from 'pinia'
import { useEditStore } from '@/management/stores/edit'
import { get as _get } from 'lodash-es' import { get as _get } from 'lodash-es'
import FormItem from '@/materials/setters/widgets/FormItem.vue' import FormItem from '@/materials/setters/widgets/FormItem.vue'
@ -36,15 +37,16 @@ const textMap = {
OverTime: '问卷过期页面配置' OverTime: '问卷过期页面配置'
} }
const store = useStore() const editStore = useEditStore()
const { currentEditStatus } = storeToRefs(editStore)
const { schema, changeSchema } = editStore
const components = shallowRef<any>({}) const components = shallowRef<any>({})
const registerTypes = ref<any>({}) const registerTypes = ref<any>({})
const moduleConfig = computed(() => _get(store.state, 'edit.schema.submitConf')) const moduleConfig = toRef(schema, 'submitConf')
const currentEditText = computed(() => (textMap as any)[store.state.edit.currentEditStatus]) const currentEditText = computed(() => (textMap as any)[currentEditStatus.value])
const formFields = computed(() => { const formFields = computed(() => {
const currentStatus = store.state.edit.currentEditStatus const formList = (statusConfig as any)[currentEditStatus.value] || []
const formList = (statusConfig as any)[currentStatus] || []
const list = formList.map((item: any) => { const list = formList.map((item: any) => {
const value = _get(moduleConfig.value, item.key, item.value) const value = _get(moduleConfig.value, item.key, item.value)
@ -57,7 +59,7 @@ const formFields = computed(() => {
}) })
const handleFormChange = ({ key, value }: any) => { const handleFormChange = ({ key, value }: any) => {
store.dispatch('edit/changeSchema', { changeSchema({
key: `submitConf.${key}`, key: `submitConf.${key}`,
value value
}) })

View File

@ -28,10 +28,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useStore } from 'vuex' import { useStore } from 'vuex'
import { useEditStore } from '@/management/stores/edit'
import skinPresets from '@/management/config/skinPresets.js' import skinPresets from '@/management/config/skinPresets.js'
const store = useStore() const store = useStore()
const editStore = useEditStore()
const { changeThemePreset } = editStore
const groupName = ref<string>('temp') const groupName = ref<string>('temp')
const bannerList = computed(() => store?.state?.bannerList || []) const bannerList = computed(() => store?.state?.bannerList || [])
const groupList = computed(() => const groupList = computed(() =>
@ -81,7 +84,7 @@ const changePreset = (banner: any) => {
presets = Object.assign(presets, (skinPresets as any)[name]) presets = Object.assign(presets, (skinPresets as any)[name])
} }
store.dispatch('edit/changeThemePreset', presets) changeThemePreset(presets)
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -24,9 +24,10 @@
</div> </div>
</template> </template>
<script> <script>
import { computed, defineComponent } from 'vue' import { defineComponent, toRefs } from 'vue'
import MaterialGroup from '@/management/pages/edit/components/MaterialGroup.vue' import MaterialGroup from '@/management/pages/edit/components/MaterialGroup.vue'
import { useStore } from 'vuex' import { storeToRefs } from 'pinia'
import { useEditStore } from '@/management/stores/edit'
import communalLoader from '@materials/communals/communalLoader.js' import communalLoader from '@materials/communals/communalLoader.js'
const HeaderContent = () => communalLoader.loadComponent('HeaderContent') const HeaderContent = () => communalLoader.loadComponent('HeaderContent')
@ -43,15 +44,10 @@ export default defineComponent({
LogoIcon: LogoIcon() LogoIcon: LogoIcon()
}, },
setup() { setup() {
const store = useStore() const editStore = useEditStore()
const { questionDataList, currentEditOne, currentEditKey } = storeToRefs(editStore)
const bannerConf = computed(() => store.state.edit.schema.bannerConf) const { schema } = editStore
const submitConf = computed(() => store.state.edit.schema.submitConf) const { bannerConf, submitConf, skinConf, bottomConf } = toRefs(schema)
const bottomConf = computed(() => store.state.edit.schema.bottomConf)
const skinConf = computed(() => store.state.edit.schema.skinConf)
const questionDataList = computed(() => store.state.edit.schema.questionDataList)
const currentEditOne = computed(() => store.state.edit.currentEditOne)
const currentEditKey = computed(() => store.getters['edit/currentEditKey'])
return { return {
bannerConf, bannerConf,

View File

@ -24,23 +24,23 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { ref } from 'vue'
import { useStore } from 'vuex' import { useEditStore } from '@/management/stores/edit'
import { get as _get } from 'lodash-es' import { get as _get } from 'lodash-es'
import skinConfig from '@/management/config/setterConfig/skinConfig' import skinConfig from '@/management/config/setterConfig/skinConfig'
import SetterField from '@/management/pages/edit/components/SetterField.vue' import SetterField from '@/management/pages/edit/components/SetterField.vue'
const store = useStore() const editStore = useEditStore()
const { schema, changeSchema } = editStore
const collapse = ref<string>('') const collapse = ref<string>('')
const schema = computed(() => _get(store.state, 'edit.schema'))
const handleFormChange = (data: any, collapse: string) => { const handleFormChange = (data: any, collapse: string) => {
const { key, value } = data const { key, value } = data
const currentEditKey = `${collapse}` const currentEditKey = `${collapse}`
const resultKey = `${currentEditKey}.${key}` const resultKey = `${currentEditKey}.${key}`
store.dispatch('edit/changeSchema', { key: resultKey, value }) changeSchema({ key: resultKey, value })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -5,17 +5,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, provide } from 'vue' import { computed, provide } from 'vue'
import { useStore } from 'vuex' import { storeToRefs } from 'pinia'
import { useEditStore } from '@/management/stores/edit'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
import RulePanel from '../../modules/logicModule/RulePanel.vue' import RulePanel from '../../modules/logicModule/RulePanel.vue'
import { filterQuestionPreviewData } from '@/management/utils/index' import { filterQuestionPreviewData } from '@/management/utils/index'
const store = useStore() const editStore = useEditStore()
const { questionDataList } = storeToRefs(editStore)
const questionDataList = computed(() => {
return store.state.edit.schema.questionDataList
})
const renderData = computed(() => { const renderData = computed(() => {
return filterQuestionPreviewData(cloneDeep(questionDataList.value)) return filterQuestionPreviewData(cloneDeep(questionDataList.value))

View File

@ -25,8 +25,8 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted } from 'vue' import { computed, onMounted, toRef } from 'vue'
import { useStore } from 'vuex' import { useEditStore } from '@/management/stores/edit'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { get as _get } from 'lodash-es' import { get as _get } from 'lodash-es'
@ -44,14 +44,15 @@ const defaultConfig = {
img: '/imgs/icons/unpublished.webp' img: '/imgs/icons/unpublished.webp'
} }
const store = useStore() const editStore = useEditStore()
const metaData = computed(() => _get(store.state, 'edit.schema.metaData')) const { schema, init, setSurveyId } = editStore
const metaData = toRef(schema, 'metaData')
const curStatus = computed(() => _get(metaData.value, 'curStatus.status', 'new')) const curStatus = computed(() => _get(metaData.value, 'curStatus.status', 'new'))
const mainChannel = computed(() => { const mainChannel = computed(() => {
let fullUrl = '' let fullUrl = ''
if (metaData.value) { if (metaData.value) {
fullUrl = `${location.origin}/render/${metaData.value.surveyPath}?t=${Date.now()}` fullUrl = `${location.origin}/render/${(metaData.value as any).surveyPath}?t=${Date.now()}`
} }
return { fullUrl } return { fullUrl }
@ -60,10 +61,10 @@ const mainChannel = computed(() => {
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
onMounted(async () => { onMounted(async () => {
store.commit('edit/setSurveyId', route.params.id) setSurveyId(route.params.id as string)
try { try {
await store.dispatch('edit/init') await init()
} catch (err: any) { } catch (err: any) {
ElMessage.error(err.message) ElMessage.error(err.message)
setTimeout(() => { setTimeout(() => {

View File

@ -0,0 +1,343 @@
import { defineStore } from 'pinia'
import { type Ref, ref, reactive, toRef, computed } from 'vue'
import { getSurveyById } from '@/management/api/survey'
import { merge as _merge, cloneDeep as _cloneDeep, set as _set } from 'lodash-es'
import { getNewField } from '@/management/utils'
import submitFormConfig from '@/management/config/setterConfig/submitConfig'
import questionLoader from '@/materials/questions/questionLoader'
const innerMetaConfig = {
submit: {
title: '提交配置',
formConfig: submitFormConfig
}
}
function useInitializeSchema(surveyId: Ref<string>) {
const schema = reactive({
metaData: null,
bannerConf: {
titleConfig: {
mainTitle: '<h3 style="text-align: center">欢迎填写问卷</h3>',
subTitle: `<p>为了给您提供更好的服务,希望您能抽出几分钟时间,将您的感受和建议告诉我们,<span style="color: rgb(204, 0, 0)">期待您的参与!</span></p>`,
applyTitle: ''
},
bannerConfig: {
bgImage: '',
bgImageAllowJump: false,
bgImageJumpLink: '',
videoLink: '',
postImg: ''
}
},
bottomConf: {
logoImage: '',
logoImageWidth: '28%'
},
skinConf: {
backgroundConf: {
color: '#fff'
},
themeConf: {
color: '#ffa600'
},
contentConf: {
opacity: 100
}
},
baseConf: {
begTime: '',
endTime: '',
language: 'chinese',
showVoteProcess: 'allow',
tLimit: 0,
answerBegTime: '',
answerEndTime: '',
answerLimitTime: 0
},
submitConf: {
submitTitle: '',
msgContent: {},
confirmAgain: {
is_again: true
},
link: ''
},
questionDataList: [],
logicConf: {
showLogicConf: []
}
})
function initSchema({ metaData, codeData }: { metaData: any; codeData: any }) {
schema.metaData = metaData
schema.bannerConf = _merge({}, schema.bannerConf, codeData.bannerConf)
schema.bottomConf = _merge({}, schema.bottomConf, codeData.bottomConf)
schema.skinConf = _merge({}, schema.skinConf, codeData.skinConf)
schema.baseConf = _merge({}, schema.baseConf, codeData.baseConf)
schema.submitConf = _merge({}, schema.submitConf, codeData.submitConf)
schema.questionDataList = codeData.questionDataList || []
schema.logicConf = codeData.logicConf
console.log(metaData, codeData)
}
async function getSchemaFromRemote() {
const res: any = await getSurveyById(surveyId.value)
if (res.code === 200) {
const metaData = res.data.surveyMetaRes
document.title = metaData.title
const {
bannerConf,
bottomConf,
skinConf,
baseConf,
submitConf,
dataConf,
logicConf = {}
} = res.data.surveyConfRes.code
initSchema({
metaData,
codeData: {
bannerConf,
bottomConf,
skinConf,
baseConf,
submitConf,
questionDataList: dataConf.dataList,
logicConf
}
})
} else {
throw new Error(res.errmsg || '问卷不存在')
}
}
return {
schema,
initSchema,
getSchemaFromRemote
}
}
function useQuestionDataListOperations(questionDataList: Ref<any[]>, updateTime: () => void) {
function copyQuestion({ index }: { index: number }) {
const newQuestion = _cloneDeep(questionDataList.value[index])
newQuestion.field = getNewField(questionDataList.value.map((item) => item.field))
addQuestion({ question: newQuestion, index })
}
function addQuestion({ question, index }: { question: any; index: number }) {
questionDataList.value.splice(index, 0, question)
updateTime()
}
function deleteQuestion({ index }: { index: number }) {
questionDataList.value.splice(index, 1)
updateTime()
}
function moveQuestion({ index, range }: { index: number; range: number }) {
console.log('move')
let start, end
if (range < 0) {
// 向上移动
start = index + range
end = index
} else if (range > 0) {
// 向下移动
start = index + 1
end = index + range + 1
} else {
// 无变化
return
}
const currentData = questionDataList.value[index]
// 新位置和老位置之间所有的题目
const comparedList = questionDataList.value.slice(start, end)
if (range < 0) {
// 向上移动
questionDataList.value.splice(index + range, 1 - range, currentData, ...comparedList)
} else if (range > 0) {
// 向下移动
questionDataList.value.splice(index, range + 1, ...comparedList, currentData)
}
updateTime()
}
return {
copyQuestion,
addQuestion,
deleteQuestion,
moveQuestion
}
}
function useCurrentEdit({
schema,
questionDataList
}: {
schema: any
questionDataList: Ref<any[]>
}) {
const currentEditOne = ref()
const currentEditStatus = ref('Success')
const currentEditKey = computed(() => {
if (currentEditOne.value === null) {
return null
}
let key = ''
switch (currentEditOne.value) {
case 'banner':
case 'mainTitle':
key = 'bannerConf'
break
case 'submit':
key = 'submitConf'
break
case 'logo':
key = 'bottomConf'
break
default:
key = `questionDataList.${currentEditOne.value}`
}
return key
})
const moduleConfig = computed(() => {
if (currentEditOne.value === null) {
return null
}
if (currentEditOne.value === 'banner' || currentEditOne.value === 'mainTitle') {
return schema?.bannerConf
} else if (currentEditOne.value === 'submit') {
return schema?.submitConf
} else if (currentEditOne.value === 'logo') {
return schema?.bottomConf
} else if (!Number.isNaN(currentEditOne.value)) {
return questionDataList.value?.[currentEditOne.value]
} else {
return null
}
})
const formConfigList = computed(() => {
if (currentEditOne.value === null) {
return null
}
return currentEditMeta.value?.formConfig || []
})
const currentEditMeta = computed(() => {
if (currentEditOne.value === null) {
return null
} else if (innerMetaConfig[currentEditOne.value as keyof typeof innerMetaConfig]) {
return innerMetaConfig[currentEditOne.value as keyof typeof innerMetaConfig]
} else {
const questionType = questionDataList.value?.[currentEditOne.value]?.type
return questionLoader.getMeta(questionType)
}
})
function setCurrentEditOne(data: any) {
currentEditOne.value = data
}
function changeCurrentEditStatus(status: string) {
currentEditStatus.value = status
}
return {
currentEditOne,
currentEditKey,
currentEditStatus,
moduleConfig,
formConfigList,
currentEditMeta,
setCurrentEditOne,
changeCurrentEditStatus
}
}
export const useEditStore = defineStore('edit', () => {
const surveyId = ref('')
const schemaUpdateTime = ref(Date.now())
const { schema, initSchema, getSchemaFromRemote } = useInitializeSchema(surveyId)
const questionDataList = toRef(schema, 'questionDataList')
function setQuestionDataList(data: any) {
schema.questionDataList = data
}
function setSurveyId(id: string) {
surveyId.value = id
}
const {
currentEditOne,
currentEditKey,
currentEditStatus,
moduleConfig,
formConfigList,
currentEditMeta,
setCurrentEditOne,
changeCurrentEditStatus
} = useCurrentEdit({ schema, questionDataList })
async function init() {
const { metaData } = schema
if (!metaData || (metaData as any)?._id !== surveyId.value) {
getSchemaFromRemote()
}
currentEditOne.value = null
currentEditStatus.value = 'Success'
}
function updateTime() {
schemaUpdateTime.value = Date.now()
}
const { copyQuestion, addQuestion, deleteQuestion, moveQuestion } = useQuestionDataListOperations(
questionDataList,
updateTime
)
function changeSchema({ key, value }: { key: string; value: any }) {
_set(schema, key, value)
updateTime()
}
function changeThemePreset(presets: any) {
Object.keys(presets).forEach((key) => {
_set(schema, key, presets[key])
})
}
return {
surveyId,
setSurveyId,
currentEditOne,
moduleConfig,
formConfigList,
currentEditKey,
currentEditStatus,
currentEditMeta,
setCurrentEditOne,
changeCurrentEditStatus,
schemaUpdateTime,
schema,
questionDataList,
setQuestionDataList,
init,
initSchema,
getSchemaFromRemote,
copyQuestion,
addQuestion,
deleteQuestion,
moveQuestion,
changeSchema,
changeThemePreset
}
})

View File

@ -59,7 +59,13 @@ export default defineConfig({
'clipboard', 'clipboard',
'qrcode', 'qrcode',
'moment', 'moment',
'moment/locale/zh-cn' 'moment/locale/zh-cn',
'echarts',
'nanoid',
'yup',
'crypto-js/sha256',
'element-plus/es/locale/lang/zh-cn',
'node-forge'
] ]
}, },
plugins: [ plugins: [