Merge branch 'feature/pinia' into develop
# Conflicts: # web/src/management/components/LeftMenu.vue # web/src/management/pages/edit/components/ModuleNavbar.vue # web/src/management/pages/edit/modules/contentModule/PublishPanel.vue # web/src/management/pages/edit/modules/contentModule/SavePanel.vue # web/src/management/pages/edit/modules/resultModule/CatalogPanel.vue # web/src/management/pages/edit/modules/settingModule/SettingPanel.vue # web/src/management/pages/list/components/BaseList.vue # web/src/management/pages/list/components/SpaceList.vue # web/src/management/pages/list/components/SpaceModify.vue # web/src/management/pages/list/index.vue # web/src/management/router/index.ts # web/src/management/store/edit/getters.js # web/src/management/store/list/index.js # web/src/management/utils/index.js # web/src/materials/questions/widgets/BinaryChoiceModule/meta.js # web/src/materials/questions/widgets/CheckboxModule/meta.js # web/src/materials/questions/widgets/RadioModule/meta.js # web/src/materials/questions/widgets/VoteModule/meta.js # web/src/render/pages/RenderPage.vue # web/src/render/store/actions.js # web/src/render/store/mutations.js # web/src/render/store/state.js
This commit is contained in:
commit
cf495b60d1
7
web/env.d.ts
vendored
7
web/env.d.ts
vendored
@ -1,8 +1 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
declare module "vuex" {
|
|
||||||
export * from "vuex/types/index.d.ts";
|
|
||||||
export * from "vuex/types/helpers.d.ts";
|
|
||||||
export * from "vuex/types/logger.d.ts";
|
|
||||||
export * from "vuex/types/vue.d.ts";
|
|
||||||
}
|
|
||||||
|
|
@ -26,11 +26,11 @@
|
|||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"nanoid": "^5.0.7",
|
"nanoid": "^5.0.7",
|
||||||
"node-forge": "^1.3.1",
|
"node-forge": "^1.3.1",
|
||||||
|
"pinia": "^2.1.7",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"vue": "^3.4.15",
|
"vue": "^3.4.15",
|
||||||
"vue-router": "^4.2.5",
|
"vue-router": "^4.2.5",
|
||||||
"vuedraggable": "^4.1.0",
|
"vuedraggable": "^4.1.0",
|
||||||
"vuex": "^4.0.2",
|
|
||||||
"xss": "^1.0.14",
|
"xss": "^1.0.14",
|
||||||
"yup": "^1.4.0"
|
"yup": "^1.4.0"
|
||||||
},
|
},
|
||||||
|
@ -24,13 +24,13 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, shallowRef, onBeforeMount, watch, computed } from 'vue'
|
import { ref, shallowRef, onBeforeMount, watch, computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { get as _get } from 'lodash-es'
|
import { get as _get } from 'lodash-es'
|
||||||
|
|
||||||
import '@wangeditor/editor/dist/css/style.css'
|
import '@wangeditor/editor/dist/css/style.css'
|
||||||
import './styles/reset-wangeditor.scss'
|
import './styles/reset-wangeditor.scss'
|
||||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||||
|
|
||||||
|
import { useUserStore } from '@/management/stores/user'
|
||||||
import { replacePxWithRem } from './utils'
|
import { replacePxWithRem } from './utils'
|
||||||
|
|
||||||
const emit = defineEmits(['input', 'onFocus', 'change', 'blur', 'created'])
|
const emit = defineEmits(['input', 'onFocus', 'change', 'blur', 'created'])
|
||||||
@ -66,8 +66,8 @@ const editorConfig = {
|
|||||||
MENU_CONF: {}
|
MENU_CONF: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const store = useStore()
|
const userStore = useUserStore()
|
||||||
const token = _get(store, 'state.user.userInfo.token')
|
const token = _get(userStore, 'userInfo.token')
|
||||||
|
|
||||||
// 图片
|
// 图片
|
||||||
editorConfig.MENU_CONF['uploadImage'] = {
|
editorConfig.MENU_CONF['uploadImage'] = {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// 静态数据
|
// test:静态数据,实际业务里无用
|
||||||
export const ruleConf = [
|
export const ruleConf = [
|
||||||
{
|
{
|
||||||
conditions: [
|
conditions: [
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import store from '@/management/store/index'
|
|
||||||
import router from '@/management/router/index'
|
import router from '@/management/router/index'
|
||||||
import { get as _get } from 'lodash-es'
|
import { get as _get } from 'lodash-es'
|
||||||
|
import { useUserStore } from '../stores/user'
|
||||||
|
|
||||||
export const CODE_MAP = {
|
export const CODE_MAP = {
|
||||||
SUCCESS: 200,
|
SUCCESS: 200,
|
||||||
@ -36,8 +36,9 @@ instance.interceptors.response.use(
|
|||||||
)
|
)
|
||||||
|
|
||||||
instance.interceptors.request.use((config) => {
|
instance.interceptors.request.use((config) => {
|
||||||
const hasLogined = _get(store, 'state.user.hasLogined')
|
const userStore = useUserStore()
|
||||||
const token = _get(store, 'state.user.userInfo.token')
|
const hasLogined = _get(userStore, 'hasLogined')
|
||||||
|
const token = _get(userStore, 'userInfo.token')
|
||||||
if (hasLogined && token) {
|
if (hasLogined && token) {
|
||||||
if (!config.headers) {
|
if (!config.headers) {
|
||||||
config.headers = {}
|
config.headers = {}
|
||||||
|
@ -16,11 +16,11 @@
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { type IMember, type ListItem } from '@/management/utils/types/workSpace'
|
import { type IMember, type ListItem } from '@/management/utils/types/workSpace'
|
||||||
import OperationSelect from './OperationSelect.vue'
|
import OperationSelect from './OperationSelect.vue'
|
||||||
|
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||||
|
|
||||||
const store = useStore()
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
members: IMember[]
|
members: IMember[]
|
||||||
@ -43,7 +43,7 @@ const list = computed({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
const currentUserId = computed(() => {
|
const currentUserId = computed(() => {
|
||||||
return store.state.list.spaceDetail?.currentUserId
|
return workSpaceStore.spaceDetail?.currentUserId
|
||||||
})
|
})
|
||||||
const handleRemove = (index: number) => {
|
const handleRemove = (index: number) => {
|
||||||
list.value.splice(index, 1)
|
list.value.splice(index, 1)
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import MemberList from './MemberList.vue'
|
import MemberList from './MemberList.vue'
|
||||||
import { getUserList } from '@/management/api/space'
|
import { getUserList } from '@/management/api/space'
|
||||||
import {
|
import {
|
||||||
@ -33,8 +32,9 @@ import {
|
|||||||
roleLabels
|
roleLabels
|
||||||
} from '@/management/utils/types/workSpace'
|
} from '@/management/utils/types/workSpace'
|
||||||
import { CODE_MAP } from '@/management/api/base'
|
import { CODE_MAP } from '@/management/api/base'
|
||||||
|
import { useUserStore } from '@/management/stores/user'
|
||||||
|
|
||||||
const store = useStore()
|
const userStore = useUserStore()
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
members?: IMember[]
|
members?: IMember[]
|
||||||
@ -65,7 +65,7 @@ const remoteMethod = async (query: string) => {
|
|||||||
if (res.code === CODE_MAP.SUCCESS) {
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
selectOptions.value = res.data.map((item: any) => {
|
selectOptions.value = res.data.map((item: any) => {
|
||||||
// 不可以选中自己
|
// 不可以选中自己
|
||||||
const currentUser = item.username === store.state.user.userInfo.username
|
const currentUser = item.username === userStore.userInfo?.username
|
||||||
return {
|
return {
|
||||||
value: item.userId,
|
value: item.userId,
|
||||||
label: item.username,
|
label: item.username,
|
||||||
|
@ -30,12 +30,12 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useEditStore } from '@/management/stores/edit'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
import LogoIcon from './LogoIcon.vue'
|
import LogoIcon from './LogoIcon.vue'
|
||||||
import { SurveyPermissions } from '@/management/utils/types/workSpace.ts'
|
import { SurveyPermissions } from '@/management/utils/types/workSpace.ts'
|
||||||
const store = useStore()
|
const editStore = useEditStore()
|
||||||
|
|
||||||
const tabArr = [
|
const tabArr = [
|
||||||
{
|
{
|
||||||
@ -62,7 +62,7 @@ const tabArr = [
|
|||||||
]
|
]
|
||||||
const tabs = ref([])
|
const tabs = ref([])
|
||||||
watch(
|
watch(
|
||||||
() => store.state.cooperPermissions,
|
() => editStore.cooperPermissions,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
tabs.value = []
|
tabs.value = []
|
||||||
// 如果有问卷管理权限,则加入问卷编辑和投放菜单
|
// 如果有问卷管理权限,则加入问卷编辑和投放菜单
|
||||||
|
@ -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))
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import store from './store'
|
import { createPinia } from 'pinia'
|
||||||
import plainText from './directive/plainText'
|
import plainText from './directive/plainText'
|
||||||
import safeHtml from './directive/safeHtml'
|
import safeHtml from './directive/safeHtml'
|
||||||
|
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
|
||||||
|
const pinia = createPinia()
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(store)
|
app.use(pinia)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
|
||||||
app.use(plainText)
|
app.use(plainText)
|
||||||
|
@ -133,9 +133,6 @@ const onPreviewImage = (e) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.table-row-cell {
|
.table-row-cell {
|
||||||
white-space: nowrap; /* 禁止自动换行 */
|
|
||||||
overflow: hidden; /* 超出部分隐藏 */
|
|
||||||
text-overflow: ellipsis; /* 显示省略号 */
|
|
||||||
:deep(img) {
|
:deep(img) {
|
||||||
height: 23px !important;
|
height: 23px !important;
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
|
@ -38,13 +38,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, computed, toRefs } from 'vue'
|
import { ref, reactive, computed, toRefs } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
import { createSurvey } from '@/management/api/survey'
|
import { createSurvey } from '@/management/api/survey'
|
||||||
|
|
||||||
import { SURVEY_TYPE_LIST } from '../types'
|
import { SURVEY_TYPE_LIST } from '../types'
|
||||||
|
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
selectType?: string
|
selectType?: string
|
||||||
@ -54,6 +52,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
selectType: 'normal'
|
selectType: 'normal'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
const ruleForm = ref<any>(null)
|
const ruleForm = ref<any>(null)
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@ -79,7 +78,6 @@ const checkForm = (fn: Function) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const store = useStore()
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
if (!state.canSubmit) {
|
if (!state.canSubmit) {
|
||||||
return
|
return
|
||||||
@ -94,8 +92,8 @@ const submit = () => {
|
|||||||
surveyType: selectType,
|
surveyType: selectType,
|
||||||
...state.form
|
...state.form
|
||||||
}
|
}
|
||||||
if (store.state.list.workSpaceId) {
|
if (workSpaceStore.workSpaceId) {
|
||||||
payload.workspaceId = store.state.list.workSpaceId
|
payload.workspaceId = workSpaceStore.workSpaceId
|
||||||
}
|
}
|
||||||
const res: any = await createSurvey(payload)
|
const res: any = await createSurvey(payload)
|
||||||
if (res?.code === 200 && res?.data?.id) {
|
if (res?.code === 200 && res?.data?.id) {
|
||||||
|
@ -35,7 +35,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'
|
||||||
@ -62,13 +62,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) => {
|
||||||
|
@ -28,8 +28,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 { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||||
|
|
||||||
@ -42,8 +41,9 @@ import SavePanel from '../modules/contentModule/SavePanel.vue'
|
|||||||
import PublishPanel from '../modules/contentModule/PublishPanel.vue'
|
import PublishPanel from '../modules/contentModule/PublishPanel.vue'
|
||||||
import CooperationPanel from '../modules/contentModule/CooperationPanel.vue'
|
import CooperationPanel from '../modules/contentModule/CooperationPanel.vue'
|
||||||
|
|
||||||
const store = useStore()
|
const editStore = useEditStore()
|
||||||
const title = computed(() => _get(store.state, 'edit.schema.metaData.title'))
|
const { schema, changeSchema } = editStore
|
||||||
|
const title = computed(() => (editStore.schema?.metaData as any)?.title || '')
|
||||||
// 校验 - 逻辑
|
// 校验 - 逻辑
|
||||||
const updateLogicConf = () => {
|
const updateLogicConf = () => {
|
||||||
let res = {
|
let res = {
|
||||||
@ -68,7 +68,7 @@ const updateLogicConf = () => {
|
|||||||
|
|
||||||
const showLogicConf = showLogicEngine.value.toJson()
|
const showLogicConf = showLogicEngine.value.toJson()
|
||||||
// 更新逻辑配置
|
// 更新逻辑配置
|
||||||
store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
changeSchema({ key: 'logicConf', value: { showLogicConf } })
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ const updateWhiteConf = () => {
|
|||||||
validated: true,
|
validated: true,
|
||||||
message: ''
|
message: ''
|
||||||
}
|
}
|
||||||
const baseConf = store.state.edit.schema.baseConf || {}
|
const baseConf = (schema?.baseConf as any) || {}
|
||||||
if (baseConf.passwordSwitch && !baseConf.password) {
|
if (baseConf.passwordSwitch && !baseConf.password) {
|
||||||
res = {
|
res = {
|
||||||
validated: false,
|
validated: false,
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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'
|
||||||
@ -21,7 +21,8 @@ interface Props {
|
|||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const isPublishing = ref<boolean>(false)
|
const isPublishing = ref<boolean>(false)
|
||||||
const store = useStore()
|
const editStore = useEditStore()
|
||||||
|
const { schema, getSchemaFromRemote } = editStore
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const validate = () => {
|
const validate = () => {
|
||||||
@ -59,7 +60,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')
|
||||||
@ -77,7 +78,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}`)
|
||||||
|
@ -15,10 +15,9 @@
|
|||||||
</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 { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
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'
|
||||||
|
|
||||||
@ -44,7 +43,9 @@ const saveText = computed(
|
|||||||
})[autoSaveStatus.value]
|
})[autoSaveStatus.value]
|
||||||
)
|
)
|
||||||
|
|
||||||
const store = useStore()
|
const editStore = useEditStore()
|
||||||
|
const { schemaUpdateTime } = storeToRefs(editStore)
|
||||||
|
const { schema } = editStore
|
||||||
|
|
||||||
const validate = () => {
|
const validate = () => {
|
||||||
let checked = true
|
let checked = true
|
||||||
@ -68,7 +69,7 @@ const validate = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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')
|
||||||
@ -144,7 +145,6 @@ const handleSave = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const schemaUpdateTime = computed(() => _get(store.state, 'edit.schemaUpdateTime'))
|
|
||||||
watch(schemaUpdateTime, () => {
|
watch(schemaUpdateTime, () => {
|
||||||
triggerAutoSave()
|
triggerAutoSave()
|
||||||
})
|
})
|
||||||
|
@ -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,34 +30,29 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref, watch } from 'vue'
|
import { 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 autoScrollData = computed(() => {
|
||||||
const skinConf = computed(() => store.state.edit.schema.skinConf)
|
// return {
|
||||||
const questionDataList = computed(() => store.state.edit.schema.questionDataList)
|
// currentEditOne: currentEditOne.value,
|
||||||
const currentEditOne = computed(() => store.state.edit.currentEditOne)
|
// len: questionDataList.value.length
|
||||||
const currentEditKey = computed(() => store.getters['edit/currentEditKey'])
|
// }
|
||||||
const autoScrollData = computed(() => {
|
// })
|
||||||
return {
|
|
||||||
currentEditOne: currentEditOne.value,
|
|
||||||
len: questionDataList.value.length
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const onSelectEditOne = async (currentEditOne) => {
|
|
||||||
store.commit('edit/setCurrentEditOne', currentEditOne)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleChange = (data) => {
|
const handleChange = (data) => {
|
||||||
if (currentEditOne.value === null) {
|
if (currentEditOne.value === null) {
|
||||||
@ -65,34 +60,33 @@ const handleChange = (data) => {
|
|||||||
}
|
}
|
||||||
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) => {
|
||||||
@ -114,22 +108,24 @@ watch(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
watch(autoScrollData, (newVal) => {
|
// 实际编辑题目不会只是从上到下而需要上下题目对比。
|
||||||
const { currentEditOne } = newVal
|
// 一直跳动到顶部影响编辑操作,若有场景需要可自行放开
|
||||||
if (typeof currentEditOne === 'number') {
|
// watch(autoScrollData, (newVal) => {
|
||||||
setTimeout(() => {
|
// const { currentEditOne } = newVal
|
||||||
const field = questionDataList.value?.[currentEditOne]?.field
|
// if (typeof currentEditOne === 'number') {
|
||||||
if (field) {
|
// setTimeout(() => {
|
||||||
const questionModule = materialGroup.value?.getQuestionRefByField(field)
|
// const field = questionDataList.value?.[currentEditOne]?.field
|
||||||
if (questionModule && questionModule.$el) {
|
// if (field) {
|
||||||
questionModule.$el.scrollIntoView({
|
// const questionModule = materialGroup.value?.getQuestionRefByField(field)
|
||||||
behavior: 'smooth'
|
// if (questionModule && questionModule.$el) {
|
||||||
})
|
// questionModule.$el.scrollIntoView({
|
||||||
}
|
// behavior: 'smooth'
|
||||||
}
|
// })
|
||||||
}, 0)
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// }, 0)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -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>
|
||||||
|
@ -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 {
|
||||||
|
@ -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) => {
|
||||||
|
@ -17,10 +17,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useStore } from 'vuex'
|
import { storeToRefs } from 'pinia'
|
||||||
import { EDIT_STATUS_MAP } from './components/enum'
|
|
||||||
|
|
||||||
const store = useStore()
|
import { EDIT_STATUS_MAP } from './components/enum'
|
||||||
|
import { useEditStore } from '@/management/stores/edit'
|
||||||
|
|
||||||
|
const editStore = useEditStore()
|
||||||
|
const { currentEditStatus } = storeToRefs(editStore)
|
||||||
const statusList = [
|
const statusList = [
|
||||||
{
|
{
|
||||||
type: EDIT_STATUS_MAP.SUCCESS,
|
type: EDIT_STATUS_MAP.SUCCESS,
|
||||||
@ -35,10 +38,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>
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
})
|
})
|
||||||
|
@ -38,13 +38,13 @@
|
|||||||
</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 {
|
import {
|
||||||
cloneDeep as _cloneDeep,
|
cloneDeep as _cloneDeep,
|
||||||
isArray as _isArray,
|
isArray as _isArray,
|
||||||
get as _get,
|
get as _get,
|
||||||
isFunction as _isFunction
|
isFunction as _isFunction
|
||||||
} from 'lodash-es'
|
} from 'lodash-es'
|
||||||
|
import { useEditStore } from '@/management/stores/edit'
|
||||||
|
|
||||||
import baseConfig from '@/management/pages/edit/setterConfig/baseConfig'
|
import baseConfig from '@/management/pages/edit/setterConfig/baseConfig'
|
||||||
import baseFormConfig from '@/management/pages/edit/setterConfig/baseFormConfig'
|
import baseFormConfig from '@/management/pages/edit/setterConfig/baseFormConfig'
|
||||||
@ -54,6 +54,9 @@ import setterLoader from '@/materials/setters/setterLoader'
|
|||||||
import WhiteList from './components/WhiteList.vue'
|
import WhiteList from './components/WhiteList.vue'
|
||||||
import TeamMemberList from './components/TeamMemberList.vue'
|
import TeamMemberList from './components/TeamMemberList.vue'
|
||||||
|
|
||||||
|
const editStore = useEditStore()
|
||||||
|
const { schema, changeSchema } = editStore
|
||||||
|
|
||||||
const formConfigList = ref<Array<any>>([])
|
const formConfigList = ref<Array<any>>([])
|
||||||
const components = shallowRef<any>({
|
const components = shallowRef<any>({
|
||||||
['WhiteList']: WhiteList,
|
['WhiteList']: WhiteList,
|
||||||
@ -64,8 +67,8 @@ const registerTypes = ref<any>({
|
|||||||
WhiteList: 'WhiteList',
|
WhiteList: 'WhiteList',
|
||||||
TeamMemberList: 'TeamMemberList'
|
TeamMemberList: 'TeamMemberList'
|
||||||
})
|
})
|
||||||
const store = useStore()
|
|
||||||
const schemaBaseConf = computed(() => store.state.edit?.schema?.baseConf || {})
|
const schemaBaseConf = computed(() => schema?.baseConf || {})
|
||||||
|
|
||||||
const setterList = computed(() => {
|
const setterList = computed(() => {
|
||||||
const list = _cloneDeep(formConfigList.value)
|
const list = _cloneDeep(formConfigList.value)
|
||||||
@ -79,12 +82,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
|
||||||
@ -103,9 +106,8 @@ const setterList = computed(() => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
})
|
})
|
||||||
@ -173,7 +175,6 @@ onMounted(async () => {
|
|||||||
padding-bottom: 19px;
|
padding-bottom: 19px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
border-bottom: 1px solid $border-color;
|
border-bottom: 1px solid $border-color;
|
||||||
padding-left: 30px;
|
|
||||||
|
|
||||||
span {
|
span {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, defineEmits, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { FORM_CHANGE_EVENT_KEY } from '@/materials/setters/constant'
|
import { FORM_CHANGE_EVENT_KEY } from '@/materials/setters/constant'
|
||||||
import { getMemberList } from '@/management/api/space'
|
import { getMemberList } from '@/management/api/space'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
@ -27,13 +27,14 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
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 editStore = useEditStore()
|
||||||
|
const { changeThemePreset } = editStore
|
||||||
const groupName = ref<string>('temp')
|
const groupName = ref<string>('temp')
|
||||||
const bannerList = computed(() => store?.state?.bannerList || [])
|
const bannerList = computed(() => editStore.bannerList || [])
|
||||||
const groupList = computed(() =>
|
const groupList = computed(() =>
|
||||||
Object.keys(bannerList.value).map((key) => ({
|
Object.keys(bannerList.value).map((key) => ({
|
||||||
label: bannerList.value[key].name,
|
label: bannerList.value[key].name,
|
||||||
@ -81,7 +82,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>
|
||||||
@ -108,7 +109,10 @@ const changePreset = (banner: any) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
.tag {
|
.tag {
|
||||||
margin: 5px 8px;
|
width: 55px;
|
||||||
|
margin: 5px 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
flex: auto;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&.current {
|
&.current {
|
||||||
color: $primary-color;
|
color: $primary-color;
|
||||||
|
@ -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,
|
||||||
|
@ -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/pages/edit/setterConfig/skinConfig'
|
import skinConfig from '@/management/pages/edit/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>
|
||||||
|
@ -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))
|
||||||
|
@ -13,17 +13,17 @@
|
|||||||
</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 CommonTemplate from '../../components/CommonTemplate.vue'
|
import CommonTemplate from '../../components/CommonTemplate.vue'
|
||||||
import CatalogPanel from '../../modules/skinModule/CatalogPanel.vue'
|
import CatalogPanel from '../../modules/skinModule/CatalogPanel.vue'
|
||||||
import PreviewPanel from '../../modules/skinModule/PreviewPanel.vue'
|
import PreviewPanel from '../../modules/skinModule/PreviewPanel.vue'
|
||||||
import SetterPanel from '../../modules/skinModule/SetterPanel.vue'
|
import SetterPanel from '../../modules/skinModule/SetterPanel.vue'
|
||||||
|
|
||||||
const store = useStore()
|
const editStore = useEditStore()
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
store.dispatch('getBannerData')
|
editStore.fetchBannerData()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -8,11 +8,17 @@ export default [
|
|||||||
title: '提交限制',
|
title: '提交限制',
|
||||||
key: 'limitConfig',
|
key: 'limitConfig',
|
||||||
formList: ['limit_tLimit']
|
formList: ['limit_tLimit']
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
title: '作答限制',
|
title: '作答限制',
|
||||||
key: 'respondConfig',
|
key: 'respondConfig',
|
||||||
formList: ['interview_pwd','answer_type','white_placeholder','white_list','team_list']
|
formList: [
|
||||||
|
'interview_pwd_switch',
|
||||||
|
'interview_pwd',
|
||||||
|
'answer_type',
|
||||||
|
'white_placeholder',
|
||||||
|
'white_list',
|
||||||
|
'team_list'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,12 +22,18 @@ export default {
|
|||||||
type: 'QuestionTimeHour',
|
type: 'QuestionTimeHour',
|
||||||
placement: 'top'
|
placement: 'top'
|
||||||
},
|
},
|
||||||
interview_pwd: {
|
interview_pwd_switch: {
|
||||||
keys: ['baseConf.passwordSwitch', 'baseConf.password'],
|
key: 'baseConf.passwordSwitch',
|
||||||
label: '访问密码',
|
label: '访问密码',
|
||||||
type: 'SwitchInput',
|
type: 'CustomedSwitch'
|
||||||
|
},
|
||||||
|
interview_pwd: {
|
||||||
|
type: 'InputSetter',
|
||||||
placeholder: '请输入6位字符串类型访问密码 ',
|
placeholder: '请输入6位字符串类型访问密码 ',
|
||||||
maxLength: 6
|
maxLength: 6,
|
||||||
|
relyFunc: (data) => {
|
||||||
|
return !!data?.passwordSwitch
|
||||||
|
}
|
||||||
},
|
},
|
||||||
answer_type: {
|
answer_type: {
|
||||||
key: 'baseConf.whitelistType',
|
key: 'baseConf.whitelistType',
|
||||||
@ -52,7 +58,7 @@ export default {
|
|||||||
key: 'baseConf.whitelistTip',
|
key: 'baseConf.whitelistTip',
|
||||||
label: '名单登录提示语',
|
label: '名单登录提示语',
|
||||||
placeholder: '请输入名单提示语',
|
placeholder: '请输入名单提示语',
|
||||||
type: 'InputWordLimit',
|
type: 'InputSetter',
|
||||||
maxLength: 40,
|
maxLength: 40,
|
||||||
relyFunc: (data) => {
|
relyFunc: (data) => {
|
||||||
return ['CUSTOM', 'MEMBER'].includes(data.whitelistType)
|
return ['CUSTOM', 'MEMBER'].includes(data.whitelistType)
|
||||||
|
@ -105,9 +105,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, unref } from 'vue'
|
import { ref, computed, unref } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { get, map } from 'lodash-es'
|
import { get, map } from 'lodash-es'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
@ -124,6 +124,8 @@ import CooperModify from '@/management/components/CooperModify/ModifyDialog.vue'
|
|||||||
import { CODE_MAP } from '@/management/api/base'
|
import { CODE_MAP } from '@/management/api/base'
|
||||||
import { QOP_MAP } from '@/management/utils/constant.ts'
|
import { QOP_MAP } from '@/management/utils/constant.ts'
|
||||||
import { deleteSurvey } from '@/management/api/survey'
|
import { deleteSurvey } from '@/management/api/survey'
|
||||||
|
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||||
|
import { useSurveyListStore } from '@/management/stores/surveyList'
|
||||||
import ModifyDialog from './ModifyDialog.vue'
|
import ModifyDialog from './ModifyDialog.vue'
|
||||||
import TagModule from './TagModule.vue'
|
import TagModule from './TagModule.vue'
|
||||||
import StateModule from './StateModule.vue'
|
import StateModule from './StateModule.vue'
|
||||||
@ -141,7 +143,9 @@ import {
|
|||||||
buttonOptionsDict
|
buttonOptionsDict
|
||||||
} from '@/management/config/listConfig'
|
} from '@/management/config/listConfig'
|
||||||
|
|
||||||
const store = useStore()
|
const surveyListStore = useSurveyListStore()
|
||||||
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
|
const { workSpaceId } = storeToRefs(workSpaceStore)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
loading: {
|
loading: {
|
||||||
@ -162,17 +166,9 @@ const fields = ['type', 'title', 'remark', 'owner', 'state', 'createDate', 'upda
|
|||||||
const showModify = ref(false)
|
const showModify = ref(false)
|
||||||
const modifyType = ref('')
|
const modifyType = ref('')
|
||||||
const questionInfo = ref({})
|
const questionInfo = ref({})
|
||||||
|
|
||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
const searchVal = computed(() => {
|
const { searchVal, selectValueMap, buttonValueMap } = storeToRefs(surveyListStore)
|
||||||
return store.state.list.searchVal
|
|
||||||
})
|
|
||||||
const selectValueMap = computed(() => {
|
|
||||||
return store.state.list.selectValueMap
|
|
||||||
})
|
|
||||||
const buttonValueMap = computed(() => {
|
|
||||||
return store.state.list.buttonValueMap
|
|
||||||
})
|
|
||||||
const currentComponent = computed(() => {
|
const currentComponent = computed(() => {
|
||||||
return (componentName) => {
|
return (componentName) => {
|
||||||
switch (componentName) {
|
switch (componentName) {
|
||||||
@ -247,9 +243,6 @@ const order = computed(() => {
|
|||||||
}, [])
|
}, [])
|
||||||
return JSON.stringify(formatOrder)
|
return JSON.stringify(formatOrder)
|
||||||
})
|
})
|
||||||
const workSpaceId = computed(() => {
|
|
||||||
return store.state.list.workSpaceId
|
|
||||||
})
|
|
||||||
|
|
||||||
const onRefresh = async () => {
|
const onRefresh = async () => {
|
||||||
const filterString = JSON.stringify(
|
const filterString = JSON.stringify(
|
||||||
@ -298,7 +291,7 @@ const getToolConfig = (row) => {
|
|||||||
label: '协作'
|
label: '协作'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
if (!store.state.list.workSpaceId) {
|
if (!workSpaceId.value) {
|
||||||
if (!row.isCollaborated) {
|
if (!row.isCollaborated) {
|
||||||
// 创建人显示协作按钮
|
// 创建人显示协作按钮
|
||||||
funcList = funcList.concat(permissionsBtn)
|
funcList = funcList.concat(permissionsBtn)
|
||||||
@ -430,19 +423,18 @@ const onRowClick = (row) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
const onSearchText = (e) => {
|
const onSearchText = (e) => {
|
||||||
store.commit('list/setSearchVal', e)
|
searchVal.value = e
|
||||||
currentPage.value = 1
|
currentPage.value = 1
|
||||||
onRefresh()
|
onRefresh()
|
||||||
}
|
}
|
||||||
const onSelectChange = (selectKey, selectValue) => {
|
const onSelectChange = (selectKey, selectValue) => {
|
||||||
store.commit('list/changeSelectValueMap', { key: selectKey, value: selectValue })
|
surveyListStore.changeSelectValueMap(selectKey, selectValue)
|
||||||
// selectValueMap.value[selectKey] = selectValue
|
|
||||||
currentPage.value = 1
|
currentPage.value = 1
|
||||||
onRefresh()
|
onRefresh()
|
||||||
}
|
}
|
||||||
const onButtonChange = (effectKey, effectValue) => {
|
const onButtonChange = (effectKey, effectValue) => {
|
||||||
store.commit('list/resetButtonValueMap')
|
surveyListStore.resetButtonValueMap()
|
||||||
store.commit('list/changeButtonValueMap', { key: effectKey, value: effectValue })
|
surveyListStore.changeButtonValueMap(effectKey, effectValue)
|
||||||
onRefresh()
|
onRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,16 +456,20 @@ const onCooperClose = () => {
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
.select {
|
.select {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search {
|
.search {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-wrapper {
|
.list-wrapper {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
||||||
.list-table {
|
.list-table {
|
||||||
min-height: 620px;
|
min-height: 620px;
|
||||||
}
|
}
|
||||||
@ -481,11 +477,13 @@ const onCooperClose = () => {
|
|||||||
|
|
||||||
.list-pagination {
|
.list-pagination {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
|
|
||||||
:deep(.el-pagination) {
|
:deep(.el-pagination) {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-table__header) {
|
:deep(.el-table__header) {
|
||||||
.tableview-header .el-table__cell {
|
.tableview-header .el-table__cell {
|
||||||
.cell {
|
.cell {
|
||||||
@ -495,21 +493,26 @@ const onCooperClose = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.tableview-row) {
|
:deep(.tableview-row) {
|
||||||
.tableview-cell {
|
.tableview-cell {
|
||||||
padding: 5px 0;
|
padding: 5px 0;
|
||||||
|
|
||||||
&.link {
|
&.link {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cell .cell-span {
|
.cell .cell-span {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-select-dropdown__wrap {
|
.el-select-dropdown__wrap {
|
||||||
background: #eee;
|
background: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-select-dropdown__item.hover {
|
.el-select-dropdown__item.hover {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,6 @@
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { ElMessageBox } from 'element-plus'
|
import { ElMessageBox } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message-box.scss'
|
import 'element-plus/theme-chalk/src/message-box.scss'
|
||||||
import { get, map } from 'lodash-es'
|
import { get, map } from 'lodash-es'
|
||||||
@ -90,10 +89,10 @@ import TextSearch from '@/management/pages/list/components/TextSearch.vue'
|
|||||||
import EmptyIndex from '@/management/components/EmptyIndex.vue'
|
import EmptyIndex from '@/management/components/EmptyIndex.vue'
|
||||||
import ToolBar from './ToolBar.vue'
|
import ToolBar from './ToolBar.vue'
|
||||||
import { UserRole } from '@/management/utils/types/workSpace'
|
import { UserRole } from '@/management/utils/types/workSpace'
|
||||||
|
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||||
|
|
||||||
const showSpaceModify = ref(false)
|
const showSpaceModify = ref(false)
|
||||||
const modifyType = ref('edit')
|
const modifyType = ref('edit')
|
||||||
const store = useStore()
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
loading: {
|
loading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -109,15 +108,17 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['refresh'])
|
const emit = defineEmits(['refresh'])
|
||||||
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
const fields = ['name', 'surveyTotal', 'memberTotal', 'owner', 'createDate']
|
const fields = ['name', 'surveyTotal', 'memberTotal', 'owner', 'createDate']
|
||||||
const fieldList = computed(() => {
|
const fieldList = computed(() => {
|
||||||
return map(fields, (f) => {
|
return map(fields, (f) => {
|
||||||
return get(spaceListConfig, f, null)
|
return get(spaceListConfig, f, null)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const isAdmin = (id: string) => {
|
const isAdmin = (id: string) => {
|
||||||
return (
|
return (
|
||||||
store.state.list.teamSpaceList.find((item: any) => item._id === id)?.currentUserRole ===
|
workSpaceStore.workSpaceList.find((item: any) => item._id === id)?.currentUserRole ===
|
||||||
UserRole.Admin
|
UserRole.Admin
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -152,7 +153,7 @@ const getTools = (data: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleModify = async (id: string) => {
|
const handleModify = async (id: string) => {
|
||||||
await store.dispatch('list/getSpaceDetail', id)
|
await workSpaceStore.getSpaceDetail(id)
|
||||||
modifyType.value = 'edit'
|
modifyType.value = 'edit'
|
||||||
showSpaceModify.value = true
|
showSpaceModify.value = true
|
||||||
}
|
}
|
||||||
@ -167,9 +168,8 @@ const handleDelete = (id: string) => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
await store.dispatch('list/deleteSpace', id)
|
await workSpaceStore.deleteSpace(id)
|
||||||
await store.dispatch('list/getSpaceList')
|
await workSpaceStore.getSpaceList()
|
||||||
curPage.value = 1
|
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
}
|
}
|
||||||
@ -184,9 +184,9 @@ const handleClick = (key: string, data: any) => {
|
|||||||
|
|
||||||
const onCloseModify = () => {
|
const onCloseModify = () => {
|
||||||
showSpaceModify.value = false
|
showSpaceModify.value = false
|
||||||
store.dispatch('list/getSpaceList')
|
workSpaceStore.getSpaceList()
|
||||||
curPage.value = 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({ onCloseModify })
|
defineExpose({ onCloseModify })
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -44,17 +44,17 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, shallowRef, onMounted } from 'vue'
|
import { computed, ref, shallowRef, onMounted } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { pick as _pick } from 'lodash-es'
|
import { pick as _pick } from 'lodash-es'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
import { QOP_MAP } from '@/management/utils/constant'
|
import { QOP_MAP } from '@/management/utils/constant'
|
||||||
import { type IMember, type IWorkspace, UserRole } from '@/management/utils/types/workSpace'
|
import { type IMember, type IWorkspace, UserRole } from '@/management/utils/types/workSpace'
|
||||||
|
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||||
|
|
||||||
import MemberSelect from '@/management/components/CooperModify/MemberSelect.vue'
|
import MemberSelect from '@/management/components/CooperModify/MemberSelect.vue'
|
||||||
|
|
||||||
const store = useStore()
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
const emit = defineEmits(['on-close-codify', 'onFocus', 'change', 'blur'])
|
const emit = defineEmits(['on-close-codify', 'onFocus', 'change', 'blur'])
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
@ -66,7 +66,8 @@ const ruleForm = shallowRef<any>(null)
|
|||||||
const formTitle = computed(() => {
|
const formTitle = computed(() => {
|
||||||
return props.type === QOP_MAP.ADD ? '创建团队空间' : '管理团队空间'
|
return props.type === QOP_MAP.ADD ? '创建团队空间' : '管理团队空间'
|
||||||
})
|
})
|
||||||
const formModel = ref<IWorkspace>({
|
const formModel = ref<Required<IWorkspace>>({
|
||||||
|
_id: '',
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
members: [] as IMember[]
|
members: [] as IMember[]
|
||||||
@ -88,28 +89,29 @@ const rules = {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
const spaceDetail = computed(() => {
|
const spaceDetail = computed(() => {
|
||||||
return store.state.list.spaceDetail
|
return workSpaceStore.spaceDetail
|
||||||
})
|
})
|
||||||
const formDisabled = computed(() => {
|
const formDisabled = computed(() => {
|
||||||
return spaceDetail.value?._id
|
return spaceDetail.value?._id
|
||||||
? store.state.list.teamSpaceList.find((item: any) => item._id === spaceDetail.value._id)
|
? workSpaceStore.workSpaceList.find((item: any) => item._id === spaceDetail.value?._id)
|
||||||
.currentUserRole !== UserRole.Admin
|
?.currentUserRole !== UserRole.Admin
|
||||||
: false
|
: false
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.type === QOP_MAP.EDIT) {
|
if (props.type === QOP_MAP.EDIT) {
|
||||||
formModel.value = _pick(spaceDetail.value, ['_id', 'name', 'description', 'members'])
|
formModel.value = _pick(spaceDetail.value as any, ['_id', 'name', 'description', 'members'])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const onClose = () => {
|
const onClose = () => {
|
||||||
formModel.value = {
|
formModel.value = {
|
||||||
|
_id: '',
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
members: [] as IMember[]
|
members: [] as IMember[]
|
||||||
}
|
}
|
||||||
// 清空空间详情
|
// 清空空间详情
|
||||||
store.commit('list/setSpaceDetail', null)
|
workSpaceStore.setSpaceDetail(null)
|
||||||
emit('on-close-codify')
|
emit('on-close-codify')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,10 +146,10 @@ const handleMembersChange = (val: IMember[]) => {
|
|||||||
formModel.value.members = val
|
formModel.value.members = val
|
||||||
}
|
}
|
||||||
const handleUpdate = async () => {
|
const handleUpdate = async () => {
|
||||||
await store.dispatch('list/updateSpace', formModel.value)
|
await workSpaceStore.updateSpace(formModel.value)
|
||||||
}
|
}
|
||||||
const handleAdd = async () => {
|
const handleAdd = async () => {
|
||||||
await store.dispatch('list/addSpace', formModel.value)
|
await workSpaceStore.addSpace(formModel.value)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -56,8 +56,8 @@
|
|||||||
ref="spaceListRef"
|
ref="spaceListRef"
|
||||||
@refresh="fetchSpaceList"
|
@refresh="fetchSpaceList"
|
||||||
:loading="spaceLoading"
|
:loading="spaceLoading"
|
||||||
:data="spaceList"
|
:data="workSpaceList"
|
||||||
:total="spaceTotal"
|
:total="workSpaceListTotal"
|
||||||
v-if="spaceType === SpaceType.Group"
|
v-if="spaceType === SpaceType.Group"
|
||||||
></SpaceList>
|
></SpaceList>
|
||||||
</div>
|
</div>
|
||||||
@ -73,83 +73,66 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import BaseList from './components/BaseList.vue'
|
import BaseList from './components/BaseList.vue'
|
||||||
import SpaceList from './components/SpaceList.vue'
|
import SpaceList from './components/SpaceList.vue'
|
||||||
import SliderBar from './components/SliderBar.vue'
|
import SliderBar from './components/SliderBar.vue'
|
||||||
import SpaceModify from './components/SpaceModify.vue'
|
import SpaceModify from './components/SpaceModify.vue'
|
||||||
import { SpaceType } from '@/management/utils/types/workSpace'
|
import { SpaceType } from '@/management/utils/types/workSpace'
|
||||||
|
import { useUserStore } from '@/management/stores/user'
|
||||||
|
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||||
|
import { useSurveyListStore } from '@/management/stores/surveyList'
|
||||||
|
|
||||||
const store = useStore()
|
const userStore = useUserStore()
|
||||||
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
|
const surveyListStore = useSurveyListStore()
|
||||||
|
|
||||||
|
const { surveyList, surveyTotal } = storeToRefs(surveyListStore)
|
||||||
|
const { spaceMenus, workSpaceId, spaceType, workSpaceList, workSpaceListTotal } =
|
||||||
|
storeToRefs(workSpaceStore)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userInfo = computed(() => {
|
const userInfo = computed(() => {
|
||||||
return store.state.user.userInfo
|
return userStore.userInfo
|
||||||
})
|
})
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const surveyList = computed(() => {
|
|
||||||
return store.state.list.surveyList
|
|
||||||
})
|
|
||||||
const surveyTotal = computed(() => {
|
|
||||||
return store.state.list.surveyTotal
|
|
||||||
})
|
|
||||||
const spaceListRef = ref<any>(null)
|
const spaceListRef = ref<any>(null)
|
||||||
const spaceLoading = ref(false)
|
const spaceLoading = ref(false)
|
||||||
const spaceList = computed(() => {
|
|
||||||
return store.state.list.teamSpaceList
|
|
||||||
})
|
|
||||||
const spaceTotal = computed(() => {
|
|
||||||
return store.state.list.teamSpaceListTotal
|
|
||||||
})
|
|
||||||
const fetchSpaceList = async (params?: any) => {
|
|
||||||
spaceLoading.value = true
|
|
||||||
store.commit('list/changeWorkSpace', '')
|
|
||||||
await store.dispatch('list/getSpaceList', params)
|
|
||||||
spaceLoading.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const activeIndex = ref('1')
|
const activeIndex = ref('1')
|
||||||
|
|
||||||
const spaceMenus = computed(() => {
|
const fetchSpaceList = async (params?: any) => {
|
||||||
return store.state.list.spaceMenus
|
spaceLoading.value = true
|
||||||
})
|
workSpaceStore.changeWorkSpace('')
|
||||||
const workSpaceId = computed(() => {
|
workSpaceStore.getSpaceList(params)
|
||||||
return store.state.list.workSpaceId
|
spaceLoading.value = false
|
||||||
})
|
}
|
||||||
const spaceType = computed(() => {
|
|
||||||
return store.state.list.spaceType
|
|
||||||
})
|
|
||||||
const handleSpaceSelect = (id: SpaceType | string) => {
|
const handleSpaceSelect = (id: SpaceType | string) => {
|
||||||
if (id === store.state.list.spaceType || id === store.state.list.workSpaceId) {
|
if (id === spaceType.value || id === workSpaceId.value) {
|
||||||
return void 0
|
return void 0
|
||||||
}
|
}
|
||||||
const changeSpaceType = (type: SpaceType) => {
|
|
||||||
store.commit('list/changeSpaceType', type)
|
|
||||||
}
|
|
||||||
const changeWorkSpace = (id: string) => {
|
|
||||||
store.commit('list/changeWorkSpace', id)
|
|
||||||
}
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case SpaceType.Personal:
|
case SpaceType.Personal:
|
||||||
changeSpaceType(SpaceType.Personal)
|
workSpaceStore.changeSpaceType(SpaceType.Personal)
|
||||||
changeWorkSpace('')
|
workSpaceStore.changeWorkSpace('')
|
||||||
break
|
break
|
||||||
case SpaceType.Group:
|
case SpaceType.Group:
|
||||||
changeSpaceType(SpaceType.Group)
|
workSpaceStore.changeSpaceType(SpaceType.Group)
|
||||||
changeWorkSpace('')
|
workSpaceStore.changeWorkSpace('')
|
||||||
fetchSpaceList()
|
fetchSpaceList()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
changeSpaceType(SpaceType.Teamwork)
|
workSpaceStore.changeSpaceType(SpaceType.Teamwork)
|
||||||
changeWorkSpace(id)
|
workSpaceStore.changeWorkSpace(id)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
fetchSurveyList()
|
fetchSurveyList()
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
|
||||||
fetchSpaceList()
|
|
||||||
fetchSurveyList()
|
|
||||||
})
|
|
||||||
const fetchSurveyList = async (params?: any) => {
|
const fetchSurveyList = async (params?: any) => {
|
||||||
if (!params) {
|
if (!params) {
|
||||||
params = {
|
params = {
|
||||||
@ -161,19 +144,25 @@ const fetchSurveyList = async (params?: any) => {
|
|||||||
params.workspaceId = workSpaceId.value
|
params.workspaceId = workSpaceId.value
|
||||||
}
|
}
|
||||||
loading.value = true
|
loading.value = true
|
||||||
await store.dispatch('list/getSurveyList', params)
|
await surveyListStore.getSurveyList(params)
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchSpaceList()
|
||||||
|
fetchSurveyList()
|
||||||
|
})
|
||||||
|
|
||||||
const modifyType = ref('add')
|
const modifyType = ref('add')
|
||||||
const showSpaceModify = ref(false)
|
const showSpaceModify = ref(false)
|
||||||
|
|
||||||
// 当前团队信息
|
// 当前团队信息
|
||||||
const currentTeamSpace = computed(() => {
|
const currentTeamSpace = computed(() => {
|
||||||
return store.state.list.teamSpaceList.find((item: any) => item._id === workSpaceId.value)
|
return workSpaceList.value.find((item: any) => item._id === workSpaceId.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
const onSetGroup = async () => {
|
const onSetGroup = async () => {
|
||||||
await store.dispatch('list/getSpaceDetail', workSpaceId.value)
|
await workSpaceStore.getSpaceDetail(workSpaceId.value)
|
||||||
modifyType.value = 'edit'
|
modifyType.value = 'edit'
|
||||||
showSpaceModify.value = true
|
showSpaceModify.value = true
|
||||||
}
|
}
|
||||||
@ -192,7 +181,7 @@ const onCreate = () => {
|
|||||||
router.push('/create')
|
router.push('/create')
|
||||||
}
|
}
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
store.dispatch('user/logout')
|
userStore.logout()
|
||||||
router.replace({ name: 'login' })
|
router.replace({ name: 'login' })
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -57,7 +57,6 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, reactive } from 'vue'
|
import { onMounted, ref, reactive } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
@ -66,8 +65,8 @@ import 'element-plus/theme-chalk/src/message.scss'
|
|||||||
import { login, register } from '@/management/api/auth'
|
import { login, register } from '@/management/api/auth'
|
||||||
import { refreshCaptcha as refreshCaptchaApi } from '@/management/api/captcha'
|
import { refreshCaptcha as refreshCaptchaApi } from '@/management/api/captcha'
|
||||||
import { CODE_MAP } from '@/management/api/base'
|
import { CODE_MAP } from '@/management/api/base'
|
||||||
|
import { useUserStore } from '@/management/stores/user'
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@ -150,7 +149,8 @@ const submitForm = (type: 'login' | 'register') => {
|
|||||||
ElMessage.error(res.errmsg)
|
ElMessage.error(res.errmsg)
|
||||||
throw new Error('登录/注册失败' + res.errmsg)
|
throw new Error('登录/注册失败' + res.errmsg)
|
||||||
}
|
}
|
||||||
store.dispatch('user/login', {
|
const userStore = useUserStore()
|
||||||
|
userStore.login({
|
||||||
username: res.data.username,
|
username: res.data.username,
|
||||||
token: res.data.token
|
token: res.data.token
|
||||||
})
|
})
|
||||||
|
@ -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(() => {
|
||||||
|
@ -5,11 +5,12 @@ import {
|
|||||||
type NavigationGuardNext
|
type NavigationGuardNext
|
||||||
} from 'vue-router'
|
} from 'vue-router'
|
||||||
import type { RouteRecordRaw } from 'vue-router'
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
import { useStore, type Store } from 'vuex'
|
|
||||||
import { SurveyPermissions } from '@/management/utils/types/workSpace'
|
import { SurveyPermissions } from '@/management/utils/types/workSpace'
|
||||||
import { analysisTypeMap } from '@/management/config/analysisConfig'
|
import { analysisTypeMap } from '@/management/config/analysisConfig'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
import { useUserStore } from '@/management/stores/user'
|
||||||
|
import { useEditStore } from '@/management/stores/edit'
|
||||||
|
|
||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
@ -161,10 +162,10 @@ const router = createRouter({
|
|||||||
})
|
})
|
||||||
|
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
const store = useStore()
|
const userStore = useUserStore()
|
||||||
// 初始化用户信息
|
// 初始化用户信息
|
||||||
if (!store.state.user?.initialized) {
|
if (!userStore?.initialized) {
|
||||||
await store.dispatch('user/init')
|
await userStore.init()
|
||||||
}
|
}
|
||||||
// 更新页面标题
|
// 更新页面标题
|
||||||
if (to.meta.title) {
|
if (to.meta.title) {
|
||||||
@ -172,7 +173,7 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (to.meta.needLogin) {
|
if (to.meta.needLogin) {
|
||||||
await handleLoginGuard(to, from, next, store)
|
await handleLoginGuard(to, from, next)
|
||||||
} else {
|
} else {
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
@ -181,11 +182,11 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
async function handleLoginGuard(
|
async function handleLoginGuard(
|
||||||
to: RouteLocationNormalized,
|
to: RouteLocationNormalized,
|
||||||
from: RouteLocationNormalized,
|
from: RouteLocationNormalized,
|
||||||
next: NavigationGuardNext,
|
next: NavigationGuardNext
|
||||||
store: Store<any>
|
|
||||||
) {
|
) {
|
||||||
if (store.state.user?.hasLogined) {
|
const userStore = useUserStore()
|
||||||
await handlePermissionsGuard(to, from, next, store)
|
if (userStore?.hasLogined) {
|
||||||
|
await handlePermissionsGuard(to, from, next)
|
||||||
} else {
|
} else {
|
||||||
next({
|
next({
|
||||||
name: 'login',
|
name: 'login',
|
||||||
@ -197,9 +198,9 @@ async function handleLoginGuard(
|
|||||||
async function handlePermissionsGuard(
|
async function handlePermissionsGuard(
|
||||||
to: RouteLocationNormalized,
|
to: RouteLocationNormalized,
|
||||||
from: RouteLocationNormalized,
|
from: RouteLocationNormalized,
|
||||||
next: NavigationGuardNext,
|
next: NavigationGuardNext
|
||||||
store: Store<any>
|
|
||||||
) {
|
) {
|
||||||
|
const editStore = useEditStore()
|
||||||
const currSurveyId = to?.params?.id || ''
|
const currSurveyId = to?.params?.id || ''
|
||||||
const prevSurveyId = from?.params?.id || ''
|
const prevSurveyId = from?.params?.id || ''
|
||||||
// 如果跳转页面不存在surveyId 或者不需要页面权限,则直接跳转
|
// 如果跳转页面不存在surveyId 或者不需要页面权限,则直接跳转
|
||||||
@ -208,8 +209,8 @@ async function handlePermissionsGuard(
|
|||||||
} else {
|
} else {
|
||||||
// 如果跳转编辑页面,且跳转页面和上一页的surveyId不同,判断是否有对应页面权限
|
// 如果跳转编辑页面,且跳转页面和上一页的surveyId不同,判断是否有对应页面权限
|
||||||
if (currSurveyId !== prevSurveyId) {
|
if (currSurveyId !== prevSurveyId) {
|
||||||
await store.dispatch('fetchCooperPermissions', currSurveyId)
|
await editStore.fetchCooperPermissions(currSurveyId as string)
|
||||||
if (hasRequiredPermissions(to.meta.permissions as string[], store.state.cooperPermissions)) {
|
if (hasRequiredPermissions(to.meta.permissions as string[], editStore.cooperPermissions)) {
|
||||||
next()
|
next()
|
||||||
} else {
|
} else {
|
||||||
ElMessage.warning('您没有该问卷的相关协作权限')
|
ElMessage.warning('您没有该问卷的相关协作权限')
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
import { getBannerData } from '@/management/api/skin.js'
|
|
||||||
import { getCollaboratorPermissions } from '@/management/api/space.ts'
|
|
||||||
import { CODE_MAP } from '../api/base'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
async getBannerData({ state, commit }) {
|
|
||||||
if (state.bannerList && state.bannerList.length > 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const res = await getBannerData()
|
|
||||||
if (res.code === 200) {
|
|
||||||
commit('setBannerList', res.data)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async fetchCooperPermissions({ commit }, id) {
|
|
||||||
const res = await getCollaboratorPermissions(id)
|
|
||||||
if (res.code === CODE_MAP.SUCCESS) {
|
|
||||||
commit('setCooperPermissions', res.data.permissions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
import { getNewField } from '@/management/utils'
|
|
||||||
import { cloneDeep as _cloneDeep, get as _get } from 'lodash-es'
|
|
||||||
import { getSurveyById } from '@/management/api/survey'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
async init({ state, dispatch }) {
|
|
||||||
const metaData = _get(state, 'schema.metaData')
|
|
||||||
if (!metaData || metaData._id !== state.surveyId) {
|
|
||||||
await dispatch('getSchemaFromRemote')
|
|
||||||
}
|
|
||||||
dispatch('resetState')
|
|
||||||
},
|
|
||||||
async getSchemaFromRemote({ commit, state }) {
|
|
||||||
const res = await getSurveyById(state.surveyId)
|
|
||||||
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
|
|
||||||
commit('initSchema', {
|
|
||||||
metaData,
|
|
||||||
codeData: {
|
|
||||||
bannerConf,
|
|
||||||
bottomConf,
|
|
||||||
skinConf,
|
|
||||||
baseConf,
|
|
||||||
submitConf,
|
|
||||||
questionDataList: dataConf.dataList,
|
|
||||||
logicConf
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
throw new Error(res.errmsg || '问卷不存在')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resetState({ commit }) {
|
|
||||||
commit('setCurrentEditOne', null)
|
|
||||||
commit('changeStatusPreview', { type: 'Success' })
|
|
||||||
},
|
|
||||||
// 复制题目到当前题目后
|
|
||||||
copyQuestion({ commit, state }, { index }) {
|
|
||||||
const newQuestion = _cloneDeep(state.schema.questionDataList[index])
|
|
||||||
newQuestion.field = getNewField(state.schema.questionDataList.map((item) => item.field))
|
|
||||||
commit('addQuestion', { question: newQuestion, index })
|
|
||||||
},
|
|
||||||
addQuestion({ commit }, { question, index }) {
|
|
||||||
commit('addQuestion', { question, index })
|
|
||||||
commit('updateSchemaUpdateTime', Date.now())
|
|
||||||
},
|
|
||||||
deleteQuestion({ commit }, { index }) {
|
|
||||||
commit('deleteQuestion', { index })
|
|
||||||
commit('updateSchemaUpdateTime', Date.now())
|
|
||||||
},
|
|
||||||
moveQuestion({ commit }, { index, range }) {
|
|
||||||
commit('moveQuestion', { index, range })
|
|
||||||
commit('updateSchemaUpdateTime', Date.now())
|
|
||||||
},
|
|
||||||
changeSchema({ commit }, { key, value }) {
|
|
||||||
commit('changeSchema', { key, value })
|
|
||||||
commit('updateSchemaUpdateTime', Date.now())
|
|
||||||
},
|
|
||||||
changeThemePreset({ commit }, presets) {
|
|
||||||
commit('changeThemePreset', presets)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
import submitFormConfig from '@/management/pages/edit/setterConfig/submitConfig'
|
|
||||||
import questionLoader from '@/materials/questions/questionLoader'
|
|
||||||
|
|
||||||
const innerMetaConfig = {
|
|
||||||
submit: {
|
|
||||||
title: '提交配置',
|
|
||||||
formConfig: submitFormConfig
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
moduleConfig(state) {
|
|
||||||
const currentEditOne = state.currentEditOne
|
|
||||||
if (currentEditOne === null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentEditOne === 'banner' || currentEditOne === 'mainTitle') {
|
|
||||||
return state?.schema?.bannerConf
|
|
||||||
} else if (currentEditOne === 'submit') {
|
|
||||||
return state?.schema?.submitConf
|
|
||||||
} else if (currentEditOne === 'logo') {
|
|
||||||
return state?.schema?.bottomConf
|
|
||||||
} else if (!Number.isNaN(currentEditOne)) {
|
|
||||||
return state?.schema?.questionDataList?.[currentEditOne]
|
|
||||||
} else {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formConfigList(state, getters) {
|
|
||||||
const currentEditOne = state.currentEditOne
|
|
||||||
if (currentEditOne === null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return getters?.currentEditMeta?.formConfig || []
|
|
||||||
},
|
|
||||||
currentEditMeta(state) {
|
|
||||||
const currentEditOne = state.currentEditOne
|
|
||||||
if (currentEditOne === null) {
|
|
||||||
return null
|
|
||||||
} else if (innerMetaConfig[currentEditOne]) {
|
|
||||||
return innerMetaConfig[currentEditOne]
|
|
||||||
} else {
|
|
||||||
const questionType = state.schema?.questionDataList?.[currentEditOne]?.type
|
|
||||||
return questionLoader.getMeta(questionType)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
currentEditKey(state) {
|
|
||||||
const currentEditOne = state.currentEditOne
|
|
||||||
if (currentEditOne === null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
let key = ''
|
|
||||||
switch (currentEditOne) {
|
|
||||||
case 'banner':
|
|
||||||
case 'mainTitle':
|
|
||||||
key = 'bannerConf'
|
|
||||||
break
|
|
||||||
case 'submit':
|
|
||||||
key = 'submitConf'
|
|
||||||
break
|
|
||||||
case 'logo':
|
|
||||||
key = 'bottomConf'
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
key = `questionDataList.${currentEditOne}`
|
|
||||||
}
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import state from './state'
|
|
||||||
import mutations from './mutations'
|
|
||||||
import actions from './actions'
|
|
||||||
import getters from './getters'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
namespaced: true,
|
|
||||||
state,
|
|
||||||
actions,
|
|
||||||
getters,
|
|
||||||
mutations
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
import { set as _set, merge as _merge } from 'lodash-es'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
setCurrentEditOne(state, data) {
|
|
||||||
state.currentEditOne = data
|
|
||||||
},
|
|
||||||
changeStatusPreview(state, { type }) {
|
|
||||||
state.currentEditStatus = type
|
|
||||||
},
|
|
||||||
updateSchemaUpdateTime(state) {
|
|
||||||
state.schemaUpdateTime = Date.now()
|
|
||||||
},
|
|
||||||
initSchema(state, { metaData, codeData }) {
|
|
||||||
state.schema.metaData = metaData
|
|
||||||
state.schema.bannerConf = _merge({}, state.schema.bannerConf, codeData.bannerConf)
|
|
||||||
state.schema.bottomConf = _merge({}, state.schema.bottomConf, codeData.bottomConf)
|
|
||||||
state.schema.skinConf = _merge({}, state.schema.skinConf, codeData.skinConf)
|
|
||||||
state.schema.baseConf = _merge({}, state.schema.baseConf, codeData.baseConf)
|
|
||||||
state.schema.submitConf = _merge({}, state.schema.submitConf, codeData.submitConf)
|
|
||||||
state.schema.questionDataList = codeData.questionDataList || []
|
|
||||||
state.schema.logicConf = codeData.logicConf
|
|
||||||
},
|
|
||||||
setSurveyId(state, data) {
|
|
||||||
state.surveyId = data
|
|
||||||
},
|
|
||||||
addQuestion(state, { question, index }) {
|
|
||||||
state.schema.questionDataList.splice(index, 0, question)
|
|
||||||
},
|
|
||||||
deleteQuestion(state, { index }) {
|
|
||||||
state.schema.questionDataList.splice(index, 1)
|
|
||||||
},
|
|
||||||
moveQuestion(state, { index, range }) {
|
|
||||||
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 = state.schema.questionDataList[index]
|
|
||||||
// 新位置和老位置之间所有的题目
|
|
||||||
const comparedList = state.schema.questionDataList.slice(start, end)
|
|
||||||
if (range < 0) {
|
|
||||||
// 向上移动
|
|
||||||
state.schema.questionDataList.splice(index + range, 1 - range, currentData, ...comparedList)
|
|
||||||
} else if (range > 0) {
|
|
||||||
// 向下移动
|
|
||||||
state.schema.questionDataList.splice(index, range + 1, ...comparedList, currentData)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeSchema(state, { key, value }) {
|
|
||||||
_set(state.schema, key, value)
|
|
||||||
},
|
|
||||||
changeThemePreset(state, presets) {
|
|
||||||
Object.keys(presets).forEach((key) => {
|
|
||||||
_set(state.schema, key, presets[key])
|
|
||||||
})
|
|
||||||
},
|
|
||||||
setQuestionDataList(state, data) {
|
|
||||||
state.schema.questionDataList = data
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
export default {
|
|
||||||
currentEditOne: null,
|
|
||||||
currentEditStatus: 'Success',
|
|
||||||
schemaUpdateTime: Date.now(),
|
|
||||||
surveyId: '', // url上取的surveyId
|
|
||||||
schema: {
|
|
||||||
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: []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
import { createStore } from 'vuex'
|
|
||||||
import edit from './edit'
|
|
||||||
import user from './user'
|
|
||||||
import list from './list'
|
|
||||||
import actions from './actions'
|
|
||||||
import mutations from './mutations'
|
|
||||||
import state from './state'
|
|
||||||
|
|
||||||
export default createStore({
|
|
||||||
state,
|
|
||||||
getters: {},
|
|
||||||
mutations,
|
|
||||||
actions,
|
|
||||||
modules: {
|
|
||||||
edit,
|
|
||||||
user,
|
|
||||||
list
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,263 +0,0 @@
|
|||||||
import {
|
|
||||||
createSpace,
|
|
||||||
getSpaceList,
|
|
||||||
getSpaceDetail,
|
|
||||||
updateSpace,
|
|
||||||
deleteSpace
|
|
||||||
} from '@/management/api/space'
|
|
||||||
import { CODE_MAP } from '@/management/api/base'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
|
||||||
import { getSurveyList as surveyList } from '@/management/api/survey'
|
|
||||||
import { set } from 'lodash-es'
|
|
||||||
import { SpaceType } from '@/management/utils/types/workSpace'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
namespaced: true,
|
|
||||||
state: {
|
|
||||||
// 空间管理
|
|
||||||
spaceMenus: [
|
|
||||||
{
|
|
||||||
icon: 'icon-wodekongjian',
|
|
||||||
name: '我的空间',
|
|
||||||
id: SpaceType.Personal
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: 'icon-tuanduikongjian',
|
|
||||||
name: '团队空间',
|
|
||||||
id: SpaceType.Group,
|
|
||||||
children: [
|
|
||||||
// {
|
|
||||||
// name: '小桔问卷调研团队',
|
|
||||||
// id: 'xxxx',
|
|
||||||
// }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
spaceType: SpaceType.Personal,
|
|
||||||
workSpaceId: '',
|
|
||||||
spaceDetail: null,
|
|
||||||
// 团队空间
|
|
||||||
teamSpaceList: [],
|
|
||||||
teamSpaceListTotal: 0,
|
|
||||||
// 列表管理
|
|
||||||
surveyList: [],
|
|
||||||
surveyTotal: 0,
|
|
||||||
searchVal: '',
|
|
||||||
selectValueMap: {
|
|
||||||
surveyType: '',
|
|
||||||
'curStatus.status': ''
|
|
||||||
},
|
|
||||||
buttonValueMap: {
|
|
||||||
'curStatus.date': '',
|
|
||||||
createDate: -1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getters: {
|
|
||||||
listFliter(state) {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
comparator: '',
|
|
||||||
condition: [
|
|
||||||
{
|
|
||||||
field: 'title',
|
|
||||||
value: state.searchVal,
|
|
||||||
comparator: '$regex'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
comparator: '',
|
|
||||||
condition: [
|
|
||||||
{
|
|
||||||
field: 'curStatus.status',
|
|
||||||
value: state.selectValueMap['curStatus.status']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
comparator: '',
|
|
||||||
condition: [
|
|
||||||
{
|
|
||||||
field: 'surveyType',
|
|
||||||
value: state.selectValueMap.surveyType
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
listOrder(state) {
|
|
||||||
const { buttonValueMap } = state
|
|
||||||
return Object.entries(buttonValueMap)
|
|
||||||
.filter(([, effectValue]) => effectValue)
|
|
||||||
.reduce((prev, item) => {
|
|
||||||
const [effectKey, effectValue] = item
|
|
||||||
prev.push({ field: effectKey, value: effectValue })
|
|
||||||
return prev
|
|
||||||
}, [])
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
updateSpaceMenus(state, teamSpace) {
|
|
||||||
// 更新空间列表下的团队空间
|
|
||||||
set(state, 'spaceMenus[1].children', teamSpace)
|
|
||||||
},
|
|
||||||
changeSpaceType(state, spaceType) {
|
|
||||||
state.spaceType = spaceType
|
|
||||||
},
|
|
||||||
changeWorkSpace(state, workSpaceId) {
|
|
||||||
// 切换空间清除筛选条件
|
|
||||||
this.commit('list/resetSelectValueMap')
|
|
||||||
this.commit('list/resetButtonValueMap')
|
|
||||||
this.commit('list/setSearchVal', '')
|
|
||||||
state.workSpaceId = workSpaceId
|
|
||||||
},
|
|
||||||
setSpaceDetail(state, data) {
|
|
||||||
state.spaceDetail = data
|
|
||||||
},
|
|
||||||
setTeamSpaceList(state, data) {
|
|
||||||
state.teamSpaceList = data
|
|
||||||
},
|
|
||||||
setTeamSpaceListTotal(state, teamSpaceListTotal) {
|
|
||||||
state.teamSpaceListTotal = teamSpaceListTotal
|
|
||||||
},
|
|
||||||
setSurveyList(state, list) {
|
|
||||||
state.surveyList = list
|
|
||||||
},
|
|
||||||
setSurveyTotal(state, total) {
|
|
||||||
state.surveyTotal = total
|
|
||||||
},
|
|
||||||
setSearchVal(state, data) {
|
|
||||||
state.searchVal = data
|
|
||||||
},
|
|
||||||
resetSelectValueMap(state) {
|
|
||||||
state.selectValueMap = {
|
|
||||||
surveyType: '',
|
|
||||||
'curStatus.status': ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeSelectValueMap(state, { key, value }) {
|
|
||||||
state.selectValueMap[key] = value
|
|
||||||
},
|
|
||||||
resetButtonValueMap(state) {
|
|
||||||
state.buttonValueMap = {
|
|
||||||
'curStatus.date': '',
|
|
||||||
createDate: -1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeButtonValueMap(state, { key, value }) {
|
|
||||||
state.buttonValueMap[key] = value
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
async getSpaceList({ commit }, p = { curPage: 1 }) {
|
|
||||||
try {
|
|
||||||
const res = await getSpaceList(p)
|
|
||||||
if (res.code === CODE_MAP.SUCCESS) {
|
|
||||||
const { list, count } = res.data
|
|
||||||
const teamSpace = list.map((item) => {
|
|
||||||
return {
|
|
||||||
id: item._id,
|
|
||||||
name: item.name
|
|
||||||
}
|
|
||||||
})
|
|
||||||
commit('setTeamSpaceListTotal', count)
|
|
||||||
commit('setTeamSpaceList', list)
|
|
||||||
commit('updateSpaceMenus', teamSpace)
|
|
||||||
} else {
|
|
||||||
ElMessage.error('getSpaceList' + res.errmsg)
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
ElMessage.error('getSpaceList' + err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async addSpace({}, params) {
|
|
||||||
const res = await createSpace({
|
|
||||||
name: params.name,
|
|
||||||
description: params.description,
|
|
||||||
members: params.members
|
|
||||||
})
|
|
||||||
|
|
||||||
if (res.code === CODE_MAP.SUCCESS) {
|
|
||||||
ElMessage.success('添加成功')
|
|
||||||
} else {
|
|
||||||
ElMessage.error('createSpace code err' + res.errmsg)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async getSpaceDetail({ state, commit }, id) {
|
|
||||||
try {
|
|
||||||
const workspaceId = id || state.workSpaceId
|
|
||||||
const res = await getSpaceDetail(workspaceId)
|
|
||||||
if (res.code === CODE_MAP.SUCCESS) {
|
|
||||||
commit('setSpaceDetail', res.data)
|
|
||||||
} else {
|
|
||||||
ElMessage.error('getSpaceList' + res.errmsg)
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
ElMessage.error('getSpaceList' + err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async updateSpace({}, params) {
|
|
||||||
const res = await updateSpace({
|
|
||||||
workspaceId: params._id,
|
|
||||||
name: params.name,
|
|
||||||
description: params.description,
|
|
||||||
members: params.members
|
|
||||||
})
|
|
||||||
|
|
||||||
if (res.code === CODE_MAP.SUCCESS) {
|
|
||||||
ElMessage.success('更新成功')
|
|
||||||
} else {
|
|
||||||
ElMessage.error(res.errmsg)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async deleteSpace({}, workspaceId) {
|
|
||||||
try {
|
|
||||||
const res = await deleteSpace(workspaceId)
|
|
||||||
|
|
||||||
if (res.code === CODE_MAP.SUCCESS) {
|
|
||||||
ElMessage.success('删除成功')
|
|
||||||
} else {
|
|
||||||
ElMessage.error(res.errmsg)
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
ElMessage.error(err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async getSurveyList({ state, getters, commit }, payload) {
|
|
||||||
const filterString = JSON.stringify(
|
|
||||||
getters.listFliter.filter((item) => {
|
|
||||||
return item.condition[0].value
|
|
||||||
})
|
|
||||||
)
|
|
||||||
const orderString = JSON.stringify(getters.listOrder)
|
|
||||||
try {
|
|
||||||
let params = {
|
|
||||||
curPage: payload?.curPage || 1,
|
|
||||||
pageSize: payload?.pageSize || 10, // 默认一页10条
|
|
||||||
filter: filterString,
|
|
||||||
order: orderString,
|
|
||||||
workspaceId: state.workSpaceId
|
|
||||||
}
|
|
||||||
// if(payload?.order) {
|
|
||||||
// params.order = payload.order
|
|
||||||
// }
|
|
||||||
// if(payload.filter) {
|
|
||||||
// params.filter = payload.filter
|
|
||||||
// }
|
|
||||||
// if(payload?.workspaceId) {
|
|
||||||
// params.workspaceId = payload.workspaceId
|
|
||||||
// }
|
|
||||||
const res = await surveyList(params)
|
|
||||||
if (res.code === CODE_MAP.SUCCESS) {
|
|
||||||
commit('setSurveyList', res.data.data)
|
|
||||||
commit('setSurveyTotal', res.data.count)
|
|
||||||
} else {
|
|
||||||
ElMessage.error(res.errmsg)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
ElMessage.error('getSurveyList status' + error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
export default {
|
|
||||||
setBannerList(state, data) {
|
|
||||||
state.bannerList = data
|
|
||||||
},
|
|
||||||
setCooperPermissions(state, data) {
|
|
||||||
state.cooperPermissions = data
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
import { SurveyPermissions } from '@/management/utils/types/workSpace'
|
|
||||||
export default {
|
|
||||||
bannerList: [],
|
|
||||||
cooperPermissions: Object.values(SurveyPermissions)
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
const USER_INFO_KEY = 'surveyUserInfo'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
namespaced: true,
|
|
||||||
state: {
|
|
||||||
userInfo: {
|
|
||||||
token: '',
|
|
||||||
username: ''
|
|
||||||
},
|
|
||||||
hasLogined: false,
|
|
||||||
loginTime: null,
|
|
||||||
initialized: false
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
setUserInfo(state, data) {
|
|
||||||
state.userInfo = data
|
|
||||||
},
|
|
||||||
setHsLogined(state, data) {
|
|
||||||
state.hasLogined = data
|
|
||||||
},
|
|
||||||
setLoginTime(state, data) {
|
|
||||||
state.loginTime = data
|
|
||||||
},
|
|
||||||
setInitialized(state, data) {
|
|
||||||
state.initialized = data
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
init({ dispatch, commit }) {
|
|
||||||
const localData = localStorage.getItem(USER_INFO_KEY)
|
|
||||||
if (localData) {
|
|
||||||
try {
|
|
||||||
const { userInfo, loginTime } = JSON.parse(localData)
|
|
||||||
if (Date.now() - loginTime > 7 * 3600000) {
|
|
||||||
localStorage.removeItem(USER_INFO_KEY)
|
|
||||||
} else {
|
|
||||||
dispatch('login', userInfo)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
commit('setInitialized', true)
|
|
||||||
},
|
|
||||||
login({ commit }, data) {
|
|
||||||
const loginTime = Date.now()
|
|
||||||
commit('setUserInfo', data)
|
|
||||||
commit('setHsLogined', true)
|
|
||||||
commit('setLoginTime', loginTime)
|
|
||||||
localStorage.setItem(
|
|
||||||
USER_INFO_KEY,
|
|
||||||
JSON.stringify({
|
|
||||||
userInfo: data,
|
|
||||||
loginTime: loginTime
|
|
||||||
})
|
|
||||||
)
|
|
||||||
},
|
|
||||||
logout({ commit }) {
|
|
||||||
commit('setUserInfo', null)
|
|
||||||
commit('setHsLogined', false)
|
|
||||||
localStorage.removeItem(USER_INFO_KEY)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
373
web/src/management/stores/edit.ts
Normal file
373
web/src/management/stores/edit.ts
Normal file
@ -0,0 +1,373 @@
|
|||||||
|
import { type Ref, ref, reactive, toRef, computed } from 'vue'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { merge as _merge, cloneDeep as _cloneDeep, set as _set } from 'lodash-es'
|
||||||
|
|
||||||
|
import { getSurveyById } from '@/management/api/survey'
|
||||||
|
import { getNewField } from '@/management/utils'
|
||||||
|
|
||||||
|
import submitFormConfig from '@/management/pages/edit/setterConfig/statusConfig'
|
||||||
|
|
||||||
|
import questionLoader from '@/materials/questions/questionLoader'
|
||||||
|
import { SurveyPermissions } from '@/management/utils/types/workSpace'
|
||||||
|
import { getBannerData } from '@/management/api/skin.js'
|
||||||
|
import { getCollaboratorPermissions } from '@/management/api/space'
|
||||||
|
import { CODE_MAP } from '../api/base'
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
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 || []
|
||||||
|
})
|
||||||
|
|
||||||
|
function setCurrentEditOne(data: any) {
|
||||||
|
currentEditOne.value = data
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeCurrentEditStatus(status: string) {
|
||||||
|
currentEditStatus.value = status
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentEditOne,
|
||||||
|
currentEditKey,
|
||||||
|
currentEditStatus,
|
||||||
|
moduleConfig,
|
||||||
|
formConfigList,
|
||||||
|
currentEditMeta,
|
||||||
|
setCurrentEditOne,
|
||||||
|
changeCurrentEditStatus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type IBannerItem = {
|
||||||
|
name: string
|
||||||
|
key: string
|
||||||
|
list: Array<Object>
|
||||||
|
}
|
||||||
|
type IBannerList = Record<string, IBannerItem>
|
||||||
|
export const useEditStore = defineStore('edit', () => {
|
||||||
|
const surveyId = ref('')
|
||||||
|
const bannerList: Ref<IBannerList> = ref({})
|
||||||
|
const cooperPermissions = ref(Object.values(SurveyPermissions))
|
||||||
|
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 fetchBannerData = async () => {
|
||||||
|
const res: any = await getBannerData()
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
bannerList.value = res.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const fetchCooperPermissions = async (id: string) => {
|
||||||
|
const res: any = await getCollaboratorPermissions(id)
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
cooperPermissions.value = res.data.permissions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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,
|
||||||
|
bannerList,
|
||||||
|
fetchBannerData,
|
||||||
|
cooperPermissions,
|
||||||
|
fetchCooperPermissions,
|
||||||
|
currentEditOne,
|
||||||
|
moduleConfig,
|
||||||
|
formConfigList,
|
||||||
|
currentEditKey,
|
||||||
|
currentEditStatus,
|
||||||
|
currentEditMeta,
|
||||||
|
setCurrentEditOne,
|
||||||
|
changeCurrentEditStatus,
|
||||||
|
schemaUpdateTime,
|
||||||
|
schema,
|
||||||
|
questionDataList,
|
||||||
|
setQuestionDataList,
|
||||||
|
init,
|
||||||
|
initSchema,
|
||||||
|
getSchemaFromRemote,
|
||||||
|
copyQuestion,
|
||||||
|
addQuestion,
|
||||||
|
deleteQuestion,
|
||||||
|
moveQuestion,
|
||||||
|
changeSchema,
|
||||||
|
changeThemePreset
|
||||||
|
}
|
||||||
|
})
|
170
web/src/management/stores/surveyList.ts
Normal file
170
web/src/management/stores/surveyList.ts
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
|
import { CODE_MAP } from '@/management/api/base'
|
||||||
|
import { getSurveyList as getSurveyListReq } from '@/management/api/survey'
|
||||||
|
|
||||||
|
import { useWorkSpaceStore } from './workSpace'
|
||||||
|
|
||||||
|
function useSearchSurvey() {
|
||||||
|
const searchVal = ref('')
|
||||||
|
const selectValueMap = ref<Record<string, any>>({
|
||||||
|
surveyType: '',
|
||||||
|
'curStatus.status': ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const buttonValueMap = ref<Record<string, any>>({
|
||||||
|
'curStatus.date': '',
|
||||||
|
createDate: -1
|
||||||
|
})
|
||||||
|
|
||||||
|
const listFilter = computed(() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
comparator: '',
|
||||||
|
condition: [
|
||||||
|
{
|
||||||
|
field: 'title',
|
||||||
|
value: searchVal.value,
|
||||||
|
comparator: '$regex'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
comparator: '',
|
||||||
|
condition: [
|
||||||
|
{
|
||||||
|
field: 'curStatus.status',
|
||||||
|
value: selectValueMap.value['curStatus.status']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
comparator: '',
|
||||||
|
condition: [
|
||||||
|
{
|
||||||
|
field: 'surveyType',
|
||||||
|
value: selectValueMap.value.surveyType
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const listOrder = computed(() => {
|
||||||
|
return Object.entries(buttonValueMap.value)
|
||||||
|
.filter(([, effectValue]) => effectValue)
|
||||||
|
.reduce((prev: { field: string; value: string | number }[], item) => {
|
||||||
|
const [effectKey, effectValue] = item
|
||||||
|
prev.push({ field: effectKey, value: effectValue })
|
||||||
|
return prev
|
||||||
|
}, [])
|
||||||
|
})
|
||||||
|
|
||||||
|
function resetSelectValueMap() {
|
||||||
|
selectValueMap.value = {
|
||||||
|
surveyType: '',
|
||||||
|
'curStatus.status': ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetButtonValueMap() {
|
||||||
|
buttonValueMap.value = {
|
||||||
|
'curStatus.date': '',
|
||||||
|
createDate: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeSelectValueMap(key: string, value: string | number) {
|
||||||
|
selectValueMap.value[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeButtonValueMap(key: string, value: string | number) {
|
||||||
|
buttonValueMap.value[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetSearch() {
|
||||||
|
searchVal.value = ''
|
||||||
|
resetSelectValueMap()
|
||||||
|
resetButtonValueMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
searchVal,
|
||||||
|
selectValueMap,
|
||||||
|
buttonValueMap,
|
||||||
|
listFilter,
|
||||||
|
listOrder,
|
||||||
|
resetSearch,
|
||||||
|
resetSelectValueMap,
|
||||||
|
resetButtonValueMap,
|
||||||
|
changeSelectValueMap,
|
||||||
|
changeButtonValueMap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSurveyListStore = defineStore('surveyList', () => {
|
||||||
|
const surveyList = ref([])
|
||||||
|
const surveyTotal = ref(0)
|
||||||
|
|
||||||
|
const {
|
||||||
|
searchVal,
|
||||||
|
selectValueMap,
|
||||||
|
buttonValueMap,
|
||||||
|
listFilter,
|
||||||
|
listOrder,
|
||||||
|
resetSearch,
|
||||||
|
resetSelectValueMap,
|
||||||
|
resetButtonValueMap,
|
||||||
|
changeSelectValueMap,
|
||||||
|
changeButtonValueMap
|
||||||
|
} = useSearchSurvey()
|
||||||
|
|
||||||
|
const workSpaceStore = useWorkSpaceStore()
|
||||||
|
async function getSurveyList(payload: { curPage?: number; pageSize?: number }) {
|
||||||
|
const filterString = JSON.stringify(
|
||||||
|
listFilter.value.filter((item) => {
|
||||||
|
return item.condition[0].value
|
||||||
|
})
|
||||||
|
)
|
||||||
|
const orderString = JSON.stringify(listOrder.value)
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
curPage: payload?.curPage || 1,
|
||||||
|
pageSize: payload?.pageSize || 10, // 默认一页10条
|
||||||
|
filter: filterString,
|
||||||
|
order: orderString,
|
||||||
|
workspaceId: workSpaceStore.workSpaceId
|
||||||
|
}
|
||||||
|
|
||||||
|
const res: any = await getSurveyListReq(params)
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
surveyList.value = res.data.data
|
||||||
|
surveyTotal.value = res.data.count
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.errmsg)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('getSurveyList status' + error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
surveyList,
|
||||||
|
surveyTotal,
|
||||||
|
searchVal,
|
||||||
|
selectValueMap,
|
||||||
|
buttonValueMap,
|
||||||
|
listFilter: listFilter,
|
||||||
|
listOrder,
|
||||||
|
resetSearch,
|
||||||
|
getSurveyList,
|
||||||
|
resetSelectValueMap,
|
||||||
|
resetButtonValueMap,
|
||||||
|
changeSelectValueMap,
|
||||||
|
changeButtonValueMap
|
||||||
|
}
|
||||||
|
})
|
54
web/src/management/stores/user.ts
Normal file
54
web/src/management/stores/user.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
type IUserInfo = {
|
||||||
|
username: string
|
||||||
|
token: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const USER_INFO_KEY = 'surveyUserInfo'
|
||||||
|
export const useUserStore = defineStore('user', () => {
|
||||||
|
const userInfo = ref<IUserInfo | null>({
|
||||||
|
username: '',
|
||||||
|
token: ''
|
||||||
|
})
|
||||||
|
const hasLogined = ref(false)
|
||||||
|
const loginTime = ref<number | null>(null)
|
||||||
|
const initialized = ref(false)
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
const localData = localStorage.getItem(USER_INFO_KEY)
|
||||||
|
if (localData) {
|
||||||
|
try {
|
||||||
|
const { userInfo: info, loginTime: time } = JSON.parse(localData)
|
||||||
|
if (Date.now() - time > 7 * 3600000) {
|
||||||
|
localStorage.removeItem(USER_INFO_KEY)
|
||||||
|
} else {
|
||||||
|
login(info)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initialized.value = true
|
||||||
|
}
|
||||||
|
const login = (data: IUserInfo) => {
|
||||||
|
userInfo.value = data
|
||||||
|
hasLogined.value = true
|
||||||
|
loginTime.value = Date.now()
|
||||||
|
localStorage.setItem(
|
||||||
|
USER_INFO_KEY,
|
||||||
|
JSON.stringify({
|
||||||
|
userInfo: data,
|
||||||
|
loginTime: loginTime
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const logout = () => {
|
||||||
|
userInfo.value = null
|
||||||
|
hasLogined.value = false
|
||||||
|
localStorage.removeItem(USER_INFO_KEY)
|
||||||
|
}
|
||||||
|
|
||||||
|
return { userInfo, hasLogined, loginTime, initialized, init, login, logout }
|
||||||
|
})
|
149
web/src/management/stores/workSpace.ts
Normal file
149
web/src/management/stores/workSpace.ts
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
|
import { CODE_MAP } from '@/management/api/base'
|
||||||
|
import {
|
||||||
|
createSpace,
|
||||||
|
updateSpace as updateSpaceReq,
|
||||||
|
deleteSpace as deleteSpaceReq,
|
||||||
|
getSpaceList as getSpaceListReq,
|
||||||
|
getSpaceDetail as getSpaceDetailReq
|
||||||
|
} from '@/management/api/space'
|
||||||
|
|
||||||
|
import { SpaceType } from '@/management/utils/types/workSpace'
|
||||||
|
import {
|
||||||
|
type SpaceDetail,
|
||||||
|
type SpaceItem,
|
||||||
|
type IWorkspace
|
||||||
|
} from '@/management/utils/types/workSpace'
|
||||||
|
|
||||||
|
import { useSurveyListStore } from './surveyList'
|
||||||
|
|
||||||
|
export const useWorkSpaceStore = defineStore('workSpace', () => {
|
||||||
|
// list空间
|
||||||
|
const spaceMenus = ref([
|
||||||
|
{
|
||||||
|
icon: 'icon-wodekongjian',
|
||||||
|
name: '我的空间',
|
||||||
|
id: SpaceType.Personal
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'icon-tuanduikongjian',
|
||||||
|
name: '团队空间',
|
||||||
|
id: SpaceType.Group,
|
||||||
|
children: []
|
||||||
|
}
|
||||||
|
])
|
||||||
|
const spaceType = ref(SpaceType.Personal)
|
||||||
|
const workSpaceId = ref('')
|
||||||
|
const spaceDetail = ref<SpaceDetail | null>(null)
|
||||||
|
const workSpaceList = ref<SpaceItem[]>([])
|
||||||
|
const workSpaceListTotal = ref(0)
|
||||||
|
|
||||||
|
const surveyListStore = useSurveyListStore()
|
||||||
|
|
||||||
|
async function getSpaceList(params = { curPage: 1 }) {
|
||||||
|
try {
|
||||||
|
const res: any = await getSpaceListReq(params)
|
||||||
|
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
const { list } = res.data
|
||||||
|
const workSpace = list.map((item: SpaceDetail) => {
|
||||||
|
return {
|
||||||
|
id: item._id,
|
||||||
|
name: item.name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
workSpaceList.value = list
|
||||||
|
spaceMenus.value[1].children = workSpace
|
||||||
|
} else {
|
||||||
|
ElMessage.error('getSpaceList' + res.errmsg)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
ElMessage.error('getSpaceList' + err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getSpaceDetail(id: string) {
|
||||||
|
try {
|
||||||
|
const _id = id || workSpaceId.value
|
||||||
|
const res: any = await getSpaceDetailReq(_id)
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
spaceDetail.value = res.data
|
||||||
|
} else {
|
||||||
|
ElMessage.error('getSpaceList' + res.errmsg)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
ElMessage.error('getSpaceList' + err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeSpaceType(id: SpaceType) {
|
||||||
|
spaceType.value = id
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeWorkSpace(id: string) {
|
||||||
|
workSpaceId.value = id
|
||||||
|
surveyListStore.resetSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteSpace(id: string) {
|
||||||
|
try {
|
||||||
|
const res: any = await deleteSpaceReq(id)
|
||||||
|
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.errmsg)
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
ElMessage.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateSpace(params: Required<IWorkspace>) {
|
||||||
|
const { _id: workspaceId, name, description, members } = params
|
||||||
|
const res: any = await updateSpaceReq({ workspaceId, name, description, members })
|
||||||
|
|
||||||
|
if (res?.code === CODE_MAP.SUCCESS) {
|
||||||
|
ElMessage.success('更新成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res?.errmsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addSpace(params: IWorkspace) {
|
||||||
|
const { name, description, members } = params
|
||||||
|
const res: any = await createSpace({ name, description, members })
|
||||||
|
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
ElMessage.success('添加成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.error('createSpace code err' + res.errmsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSpaceDetail(data: null | SpaceDetail) {
|
||||||
|
spaceDetail.value = data
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
spaceMenus,
|
||||||
|
spaceType,
|
||||||
|
workSpaceId,
|
||||||
|
spaceDetail,
|
||||||
|
workSpaceList,
|
||||||
|
workSpaceListTotal,
|
||||||
|
getSpaceList,
|
||||||
|
getSpaceDetail,
|
||||||
|
changeSpaceType,
|
||||||
|
changeWorkSpace,
|
||||||
|
addSpace,
|
||||||
|
deleteSpace,
|
||||||
|
updateSpace,
|
||||||
|
setSpaceDetail
|
||||||
|
}
|
||||||
|
})
|
@ -11,11 +11,12 @@ export interface MenuItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type IWorkspace = {
|
export type IWorkspace = {
|
||||||
id?: string
|
_id?: string
|
||||||
name: string
|
name: string
|
||||||
description: string
|
description: string
|
||||||
members: IMember[]
|
members: IMember[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IMember = {
|
export type IMember = {
|
||||||
userId: string
|
userId: string
|
||||||
username: string
|
username: string
|
||||||
@ -23,6 +24,24 @@ export type IMember = {
|
|||||||
_id?: string
|
_id?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SpaceDetail {
|
||||||
|
_id?: string
|
||||||
|
name: string
|
||||||
|
currentUserId?: string
|
||||||
|
description: string
|
||||||
|
members: IMember[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SpaceItem = Required<Omit<SpaceDetail, 'members'>> & {
|
||||||
|
createDate: string
|
||||||
|
curStatus: { date: number; status: string }
|
||||||
|
memberTotal: number
|
||||||
|
currentUserRole: string
|
||||||
|
owner: string
|
||||||
|
ownerId: string
|
||||||
|
surveyTotal: number
|
||||||
|
}
|
||||||
|
|
||||||
export enum SpaceType {
|
export enum SpaceType {
|
||||||
Personal = 'personal',
|
Personal = 'personal',
|
||||||
Group = 'group',
|
Group = 'group',
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<el-input
|
<el-input
|
||||||
:placeholder="formConfig.placeholder"
|
:placeholder="formConfig.placeholder"
|
||||||
v-model="modelValue"
|
v-model="modelValue"
|
||||||
|
:maxlength="formConfig.maxLength"
|
||||||
@blur="handleInputBlur"
|
@blur="handleInputBlur"
|
||||||
></el-input>
|
></el-input>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-input
|
|
||||||
:maxlength="maxLength"
|
|
||||||
v-model="modelValue"
|
|
||||||
:placeholder="placeholder"
|
|
||||||
show-word-limit
|
|
||||||
type="text"
|
|
||||||
@change="handleInputChange"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<script setup>
|
|
||||||
import { computed,ref } from 'vue'
|
|
||||||
import { FORM_CHANGE_EVENT_KEY } from '@/materials/setters/constant'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
formConfig: Object,
|
|
||||||
})
|
|
||||||
const emit = defineEmits([FORM_CHANGE_EVENT_KEY])
|
|
||||||
|
|
||||||
const modelValue = ref(props.formConfig.value || '')
|
|
||||||
|
|
||||||
const maxLength = computed(() => props.formConfig.maxLength || 10)
|
|
||||||
|
|
||||||
const placeholder = computed(() => props.formConfig.placeholder || '')
|
|
||||||
|
|
||||||
const handleInputChange = (value) => {
|
|
||||||
const key = props.formConfig.key
|
|
||||||
|
|
||||||
modelValue.value = value
|
|
||||||
emit(FORM_CHANGE_EVENT_KEY, { key, value })
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
@ -1,52 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="switch-input-wrap">
|
|
||||||
<el-switch v-model="passwordSwitch" @change="changeData(props.formConfig.keys[0],passwordSwitch)" />
|
|
||||||
<InputWordLimit
|
|
||||||
v-if="passwordSwitch"
|
|
||||||
class="mt16"
|
|
||||||
@form-change="handleFormChange"
|
|
||||||
:formConfig="{
|
|
||||||
...props.formConfig,
|
|
||||||
key: props.formConfig.keys[1],
|
|
||||||
value:props.formConfig?.value[1]
|
|
||||||
}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { FORM_CHANGE_EVENT_KEY } from '@/materials/setters/constant'
|
|
||||||
import InputWordLimit from './InputWordLimit.vue'
|
|
||||||
|
|
||||||
const store = useStore();
|
|
||||||
const props = defineProps({
|
|
||||||
formConfig: Object,
|
|
||||||
})
|
|
||||||
const emit = defineEmits([FORM_CHANGE_EVENT_KEY])
|
|
||||||
const passwordSwitch = ref(props.formConfig?.value[0] || false);
|
|
||||||
|
|
||||||
|
|
||||||
const changeData = (key, value) => {
|
|
||||||
emit(FORM_CHANGE_EVENT_KEY, {
|
|
||||||
key,
|
|
||||||
value
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
const handleFormChange = (data) => {
|
|
||||||
store.dispatch('edit/changeSchema', {
|
|
||||||
key: data.key,
|
|
||||||
value: data.value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.switch-input-wrap{
|
|
||||||
width: 100%;
|
|
||||||
.mt16{
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -2,12 +2,12 @@
|
|||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, watch } from 'vue'
|
import { watch } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { storeToRefs } from 'pinia'
|
||||||
import { get as _get } from 'lodash-es'
|
|
||||||
|
|
||||||
const store = useStore()
|
import { useSurveyStore } from './stores/survey'
|
||||||
const skinConf = computed(() => _get(store, 'state.skinConf', {}))
|
|
||||||
|
const { skinConf } = storeToRefs(useSurveyStore())
|
||||||
|
|
||||||
const updateSkinConfig = (value: any) => {
|
const updateSkinConfig = (value: any) => {
|
||||||
const root = document.documentElement
|
const root = document.documentElement
|
||||||
|
@ -13,17 +13,20 @@
|
|||||||
</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 MaterialGroup from './MaterialGroup.vue'
|
import MaterialGroup from './MaterialGroup.vue'
|
||||||
|
import { useQuestionStore } from '../stores/question'
|
||||||
|
import { useSurveyStore } from '../stores/survey'
|
||||||
|
|
||||||
const store = useStore()
|
const surveyStore = useSurveyStore()
|
||||||
|
const questionStore = useQuestionStore()
|
||||||
|
|
||||||
const renderData = computed(() => store.getters?.renderData)
|
const renderData = computed(() => questionStore.renderData)
|
||||||
const rules = computed(() => store.state.rules)
|
|
||||||
const formValues = computed(() => store.state.formValues)
|
const { rules, formValues } = storeToRefs(surveyStore)
|
||||||
|
|
||||||
const handleChangeData = (data: any) => {
|
const handleChangeData = (data: any) => {
|
||||||
store.dispatch('changeData', data)
|
surveyStore.changeData(data)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -13,9 +13,10 @@ import QuestionRuleContainer from '../../materials/questions/QuestionRuleContain
|
|||||||
import { useVoteMap } from '@/render/hooks/useVoteMap'
|
import { useVoteMap } from '@/render/hooks/useVoteMap'
|
||||||
import { useShowOthers } from '@/render/hooks/useShowOthers'
|
import { useShowOthers } from '@/render/hooks/useShowOthers'
|
||||||
import { useShowInput } from '@/render/hooks/useShowInput'
|
import { useShowInput } from '@/render/hooks/useShowInput'
|
||||||
import store from '@/render/store'
|
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
import { ruleEngine } from '@/render/hooks/useRuleEngine.js'
|
import { ruleEngine } from '@/render/hooks/useRuleEngine.js'
|
||||||
|
import { useQuestionStore } from '../stores/question'
|
||||||
|
import { useSurveyStore } from '../stores/survey'
|
||||||
|
|
||||||
import { NORMAL_CHOICES, RATES, QUESTION_TYPE } from '@/common/typeEnum.ts'
|
import { NORMAL_CHOICES, RATES, QUESTION_TYPE } from '@/common/typeEnum.ts'
|
||||||
|
|
||||||
@ -32,9 +33,11 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['change'])
|
const emit = defineEmits(['change'])
|
||||||
|
const questionStore = useQuestionStore()
|
||||||
|
const surveyStore = useSurveyStore()
|
||||||
|
|
||||||
const formValues = computed(() => {
|
const formValues = computed(() => {
|
||||||
return store.state.formValues
|
return surveyStore.formValues
|
||||||
})
|
})
|
||||||
const questionConfig = computed(() => {
|
const questionConfig = computed(() => {
|
||||||
let moduleConfig = props.moduleConfig
|
let moduleConfig = props.moduleConfig
|
||||||
@ -96,7 +99,7 @@ watch(
|
|||||||
key: field,
|
key: field,
|
||||||
value: value
|
value: value
|
||||||
}
|
}
|
||||||
store.commit('changeFormData', data)
|
surveyStore.changeData(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -105,7 +108,7 @@ const handleChange = (data) => {
|
|||||||
emit('change', data)
|
emit('change', data)
|
||||||
// 处理投票题
|
// 处理投票题
|
||||||
if (props.moduleConfig.type === QUESTION_TYPE.VOTE) {
|
if (props.moduleConfig.type === QUESTION_TYPE.VOTE) {
|
||||||
store.dispatch('updateVoteData', data)
|
questionStore.updateVoteData(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
:close-on-press-escape="false"
|
:close-on-press-escape="false"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
align-center
|
align-center
|
||||||
|
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="verify-white-head">
|
<div class="verify-white-head">
|
||||||
@ -17,23 +16,33 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="verify-white-body">
|
<div class="verify-white-body">
|
||||||
<el-input v-if="isPwd" v-model="state.password" class="wd255 mb16" placeholder="请输入6位字符串类型访问密码" />
|
<el-input
|
||||||
<el-input v-if="isValue" v-model="state.value" class="wd255 mb16" :placeholder="placeholder" />
|
v-if="isPwd"
|
||||||
|
v-model="state.password"
|
||||||
|
class="wd255 mb16"
|
||||||
|
placeholder="请输入6位字符串类型访问密码"
|
||||||
|
/>
|
||||||
|
<el-input
|
||||||
|
v-if="isValue"
|
||||||
|
v-model="state.value"
|
||||||
|
class="wd255 mb16"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
/>
|
||||||
<div class="submit-btn" @click="handleSubmit">验证并开始答题</div>
|
<div class="submit-btn" @click="handleSubmit">验证并开始答题</div>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, computed, watch } from 'vue'
|
import { ref, reactive, computed, watch } from 'vue'
|
||||||
import { validate } from '../api/survey'
|
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
|
||||||
|
import { validate } from '../api/survey'
|
||||||
|
import { useSurveyStore } from '../stores/survey'
|
||||||
|
|
||||||
const whiteVisible = ref(false)
|
const whiteVisible = ref(false)
|
||||||
|
|
||||||
|
const surveyStore = useSurveyStore()
|
||||||
const store = useStore()
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
password: '',
|
password: '',
|
||||||
value: '',
|
value: '',
|
||||||
@ -66,7 +75,7 @@ const placeholder = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (state.is_submit) return;
|
if (state.is_submit) return
|
||||||
const params = {
|
const params = {
|
||||||
surveyPath: surveyPath.value
|
surveyPath: surveyPath.value
|
||||||
}
|
}
|
||||||
@ -82,22 +91,23 @@ const handleSubmit = async() => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
whiteVisible.value = false
|
whiteVisible.value = false
|
||||||
store.commit('setWhiteData',params)
|
surveyStore.setWhiteData(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(()=>baseConf.value, () => {
|
watch(
|
||||||
|
() => baseConf.value,
|
||||||
|
() => {
|
||||||
if (whiteVisible.value) return
|
if (whiteVisible.value) return
|
||||||
if (isValue.value || isPwd.value) {
|
if (isValue.value || isPwd.value) {
|
||||||
whiteVisible.value = true;
|
whiteVisible.value = true
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.verify-white-wrap {
|
.verify-white-wrap {
|
||||||
.verify-white-body {
|
.verify-white-body {
|
||||||
padding:0 14px
|
padding: 0 14px;
|
||||||
}
|
}
|
||||||
.verify-white-head {
|
.verify-white-head {
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
@ -111,19 +121,18 @@ watch(()=>baseConf.value, () => {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #92949D;
|
color: #92949d;
|
||||||
}
|
}
|
||||||
.verify-white-title {
|
.verify-white-title {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #292A36;
|
color: #292a36;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
}
|
}
|
||||||
.submit-btn {
|
.submit-btn {
|
||||||
background: #FAA600;
|
background: #faa600;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
width: 255px;
|
width: 255px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import store from '../store/index'
|
import { useSurveyStore } from '../stores/survey'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
export const useProgressBar = () => {
|
export const useProgressBar = () => {
|
||||||
|
const surveyStore = useSurveyStore()
|
||||||
const isVariableEmpty = (variable) => {
|
const isVariableEmpty = (variable) => {
|
||||||
if (variable === undefined || variable === null) {
|
if (variable === undefined || variable === null) {
|
||||||
return true
|
return true
|
||||||
@ -22,7 +23,7 @@ export const useProgressBar = () => {
|
|||||||
fillCount: 0,
|
fillCount: 0,
|
||||||
topicCount: 0
|
topicCount: 0
|
||||||
}
|
}
|
||||||
const formValues = store.state.formValues
|
const formValues = surveyStore.formValues
|
||||||
for (let key in formValues) {
|
for (let key in formValues) {
|
||||||
if (key.split('_').length > 1) continue
|
if (key.split('_').length > 1) continue
|
||||||
|
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
import store from '../store/index'
|
import { useQuestionStore } from '../stores/question'
|
||||||
|
import { useSurveyStore } from '../stores/survey'
|
||||||
|
|
||||||
export const useShowInput = (questionKey) => {
|
export const useShowInput = (questionKey) => {
|
||||||
const formValues = store.state.formValues
|
const questionStore = useQuestionStore()
|
||||||
|
const surveyStore = useSurveyStore()
|
||||||
|
const formValues = surveyStore.formValues
|
||||||
const questionVal = formValues[questionKey]
|
const questionVal = formValues[questionKey]
|
||||||
let rangeConfig = store.state.questionData[questionKey].rangeConfig
|
let rangeConfig = questionStore.questionData[questionKey].rangeConfig
|
||||||
let othersValue = {}
|
let othersValue = {}
|
||||||
if (rangeConfig && Object.keys(rangeConfig).length > 0) {
|
if (rangeConfig && Object.keys(rangeConfig).length > 0) {
|
||||||
for (let key in rangeConfig) {
|
for (let key in rangeConfig) {
|
||||||
@ -18,7 +22,8 @@ export const useShowInput = (questionKey) => {
|
|||||||
key: rangeKey,
|
key: rangeKey,
|
||||||
value: ''
|
value: ''
|
||||||
}
|
}
|
||||||
store.commit('changeFormData', data)
|
|
||||||
|
surveyStore.changeData(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
import store from '../store/index'
|
import { useQuestionStore } from '../stores/question'
|
||||||
|
import { useSurveyStore } from '../stores/survey'
|
||||||
|
|
||||||
export const useShowOthers = (questionKey) => {
|
export const useShowOthers = (questionKey) => {
|
||||||
const formValues = store.state.formValues
|
const questionStore = useQuestionStore()
|
||||||
|
const surveyStore = useSurveyStore()
|
||||||
|
const formValues = surveyStore.formValues
|
||||||
const questionVal = formValues[questionKey]
|
const questionVal = formValues[questionKey]
|
||||||
let othersValue = {}
|
let othersValue = {}
|
||||||
let options = store.state.questionData[questionKey].options.map((optionItem) => {
|
let options = questionStore.questionData[questionKey].options.map((optionItem) => {
|
||||||
if (optionItem.others) {
|
if (optionItem.others) {
|
||||||
const opKey = `${questionKey}_${optionItem.hash}`
|
const opKey = `${questionKey}_${optionItem.hash}`
|
||||||
othersValue[opKey] = formValues[opKey]
|
othersValue[opKey] = formValues[opKey]
|
||||||
@ -13,7 +17,7 @@ export const useShowOthers = (questionKey) => {
|
|||||||
key: opKey,
|
key: opKey,
|
||||||
value: ''
|
value: ''
|
||||||
}
|
}
|
||||||
store.commit('changeFormData', data)
|
surveyStore.changeData(data)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...optionItem,
|
...optionItem,
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import store from '../store/index'
|
import { useQuestionStore } from '../stores/question'
|
||||||
export const useVoteMap = (questionKey) => {
|
|
||||||
let voteTotal = store.state.voteMap?.[questionKey]?.total || 0
|
|
||||||
|
|
||||||
const options = store.state.questionData[questionKey].options.map((option) => {
|
export const useVoteMap = (questionKey) => {
|
||||||
|
const questionStore = useQuestionStore()
|
||||||
|
let voteTotal = questionStore.voteMap?.[questionKey]?.total || 0
|
||||||
|
|
||||||
|
const options = questionStore.questionData[questionKey].options.map((option) => {
|
||||||
const optionHash = option.hash
|
const optionHash = option.hash
|
||||||
const voteCount = store.state.voteMap?.[questionKey]?.[optionHash] || 0
|
const voteCount = questionStore.voteMap?.[questionKey]?.[optionHash] || 0
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...option,
|
...option,
|
||||||
|
@ -2,15 +2,16 @@ import { createApp } from 'vue'
|
|||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import EventBus from './utils/eventbus'
|
import EventBus from './utils/eventbus'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import store from './store'
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
const pinia = createPinia()
|
||||||
|
|
||||||
const $bus = new EventBus()
|
const $bus = new EventBus()
|
||||||
app.provide('$bus', $bus)
|
app.provide('$bus', $bus)
|
||||||
// 挂载到this上
|
// 挂载到this上
|
||||||
app.config.globalProperties.$bus = $bus
|
app.config.globalProperties.$bus = $bus
|
||||||
|
app.use(pinia)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.use(store)
|
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
@ -2,35 +2,41 @@
|
|||||||
<div class="result-page-wrap">
|
<div class="result-page-wrap">
|
||||||
<div class="result-page">
|
<div class="result-page">
|
||||||
<div class="page-content">
|
<div class="page-content">
|
||||||
<img class="img" :src="errorImageUrl" />
|
<img class="img" :src="errorImage" />
|
||||||
<div class="msg" v-html="errorMsg"></div>
|
<div class="msg" v-html="errorMsg"></div>
|
||||||
</div>
|
</div>
|
||||||
<LogoIcon :logo-conf="logoConf" :readonly="true" />
|
<LogoIcon :logo-conf="logoConf" :readonly="true" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { storeToRefs } from 'pinia'
|
||||||
// @ts-ignore
|
|
||||||
import communalLoader from '@materials/communals/communalLoader.js'
|
import communalLoader from '@materials/communals/communalLoader.js'
|
||||||
|
import { useErrorInfo } from '../stores/errorInfo'
|
||||||
|
import { useSurveyStore } from '../stores/survey'
|
||||||
|
|
||||||
const LogoIcon = communalLoader.loadComponent('LogoIcon')
|
const LogoIcon = communalLoader.loadComponent('LogoIcon')
|
||||||
|
|
||||||
const store = useStore()
|
const surveyStore = useSurveyStore()
|
||||||
|
const errorStore = useErrorInfo()
|
||||||
const errorImageUrl = computed(() => {
|
const { errorInfo } = storeToRefs(errorStore)
|
||||||
const errorType = store.state?.errorInfo?.errorType
|
|
||||||
const imageMap = {
|
const imageMap = {
|
||||||
overTime: '/imgs/icons/overtime.webp',
|
overTime: '/imgs/icons/overtime.webp',
|
||||||
default: '/imgs/icons/error.webp'
|
default: '/imgs/icons/error.webp'
|
||||||
}
|
}
|
||||||
|
|
||||||
return imageMap[errorType as 'overTime'] || imageMap.default
|
const errorImage = computed(() => {
|
||||||
|
const errorType = errorInfo.value.errorType
|
||||||
|
|
||||||
|
return imageMap[errorType] || imageMap.default
|
||||||
})
|
})
|
||||||
|
|
||||||
const errorMsg = computed(() => store.state?.errorInfo?.errorMsg || '提交失败')
|
const errorMsg = computed(() => {
|
||||||
const logoConf = computed(() => store.state?.bottomConf || {})
|
return errorInfo.value.errorMsg || '提交失败'
|
||||||
|
})
|
||||||
|
const logoConf = computed(() => surveyStore.bottomConf || {})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.result-page-wrap {
|
.result-page-wrap {
|
||||||
|
@ -3,17 +3,16 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted } from 'vue'
|
import { onMounted } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
import { getPublishedSurveyInfo, getPreviewSchema } from '../api/survey'
|
import { getPublishedSurveyInfo, getPreviewSchema } from '../api/survey'
|
||||||
import useCommandComponent from '../hooks/useCommandComponent'
|
import useCommandComponent from '../hooks/useCommandComponent'
|
||||||
|
import { useSurveyStore } from '../stores/survey'
|
||||||
|
|
||||||
import AlertDialog from '../components/AlertDialog.vue'
|
import AlertDialog from '../components/AlertDialog.vue'
|
||||||
import { initRuleEngine } from '@/render/hooks/useRuleEngine.js'
|
import { initRuleEngine } from '@/render/hooks/useRuleEngine.js'
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const surveyStore = useSurveyStore()
|
||||||
const loadData = (res: any, surveyPath: string) => {
|
const loadData = (res: any, surveyPath: string) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const data = res.data
|
const data = res.data
|
||||||
@ -30,8 +29,8 @@ const loadData = (res: any, surveyPath: string) => {
|
|||||||
|
|
||||||
document.title = data.title
|
document.title = data.title
|
||||||
|
|
||||||
store.commit('setSurveyPath', surveyPath)
|
surveyStore.setSurveyPath(surveyPath)
|
||||||
store.dispatch('init', questionData)
|
surveyStore.initSurvey(questionData)
|
||||||
initRuleEngine(logicConf?.showLogicConf)
|
initRuleEngine(logicConf?.showLogicConf)
|
||||||
} else {
|
} else {
|
||||||
throw new Error(res.errmsg)
|
throw new Error(res.errmsg)
|
||||||
@ -40,7 +39,7 @@ const loadData = (res: any, surveyPath: string) => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const surveyId = route.params.surveyId
|
const surveyId = route.params.surveyId
|
||||||
console.log({ surveyId })
|
console.log({ surveyId })
|
||||||
store.commit('setSurveyPath', surveyId)
|
surveyStore.setSurveyPath(surveyId)
|
||||||
getDetail(surveyId as string)
|
getDetail(surveyId as string)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ const getDetail = async (surveyPath: string) => {
|
|||||||
} else {
|
} else {
|
||||||
const res: any = await getPublishedSurveyInfo({ surveyPath })
|
const res: any = await getPublishedSurveyInfo({ surveyPath })
|
||||||
loadData(res, surveyPath)
|
loadData(res, surveyPath)
|
||||||
store.dispatch('getEncryptInfo')
|
surveyStore.getEncryptInfo()
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import communalLoader from '@materials/communals/communalLoader.js'
|
import communalLoader from '@materials/communals/communalLoader.js'
|
||||||
@ -29,6 +29,8 @@ import AlertDialog from '../components/AlertDialog.vue'
|
|||||||
import ConfirmDialog from '../components/ConfirmDialog.vue'
|
import ConfirmDialog from '../components/ConfirmDialog.vue'
|
||||||
import ProgressBar from '../components/ProgressBar.vue'
|
import ProgressBar from '../components/ProgressBar.vue'
|
||||||
|
|
||||||
|
import { useSurveyStore } from '../stores/survey'
|
||||||
|
import { useQuestionStore } from '../stores/question'
|
||||||
import { submitForm } from '../api/survey'
|
import { submitForm } from '../api/survey'
|
||||||
import encrypt from '../utils/encrypt'
|
import encrypt from '../utils/encrypt'
|
||||||
|
|
||||||
@ -55,15 +57,13 @@ const boxRef = ref<HTMLElement>()
|
|||||||
const alert = useCommandComponent(AlertDialog)
|
const alert = useCommandComponent(AlertDialog)
|
||||||
const confirm = useCommandComponent(ConfirmDialog)
|
const confirm = useCommandComponent(ConfirmDialog)
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const surveyStore = useSurveyStore()
|
||||||
|
const questionStore = useQuestionStore()
|
||||||
|
|
||||||
const bannerConf = computed(() => store.state?.bannerConf || {})
|
const renderData = computed(() => questionStore.renderData)
|
||||||
const renderData = computed(() => store.getters.renderData)
|
const { bannerConf, submitConf, bottomConf: logoConf, whiteData } = storeToRefs(surveyStore)
|
||||||
const submitConf = computed(() => store.state?.submitConf || {})
|
const surveyPath = computed(() => surveyStore.surveyPath || '')
|
||||||
const logoConf = computed(() => store.state?.bottomConf || {})
|
|
||||||
const surveyPath = computed(() => store.state?.surveyPath || '')
|
|
||||||
const whiteData = computed(() => store.state?.whiteData || {})
|
|
||||||
|
|
||||||
const validate = (cbk: (v: boolean) => void) => {
|
const validate = (cbk: (v: boolean) => void) => {
|
||||||
const index = 0
|
const index = 0
|
||||||
@ -71,9 +71,9 @@ const validate = (cbk: (v: boolean) => void) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const normalizationRequestBody = () => {
|
const normalizationRequestBody = () => {
|
||||||
const enterTime = store.state.enterTime
|
const enterTime = surveyStore.enterTime
|
||||||
const encryptInfo = store.state.encryptInfo
|
const encryptInfo = surveyStore.encryptInfo as any
|
||||||
const formValues = store.state.formValues
|
const formValues = surveyStore.formValues
|
||||||
|
|
||||||
const result: any = {
|
const result: any = {
|
||||||
surveyPath: surveyPath.value,
|
surveyPath: surveyPath.value,
|
||||||
@ -84,7 +84,7 @@ const normalizationRequestBody = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (encryptInfo?.encryptType) {
|
if (encryptInfo?.encryptType) {
|
||||||
result.encryptType = encryptInfo?.encryptType
|
result.encryptType = encryptInfo.encryptType
|
||||||
result.data = encrypt[result.encryptType as 'rsa']({
|
result.data = encrypt[result.encryptType as 'rsa']({
|
||||||
data: result.data,
|
data: result.data,
|
||||||
secretKey: encryptInfo?.data?.secretKey
|
secretKey: encryptInfo?.data?.secretKey
|
||||||
@ -121,7 +121,7 @@ const submitSurver = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
const confirmAgain = store.state.submitConf.confirmAgain
|
const confirmAgain = (surveyStore.submitConf as any).confirmAgain
|
||||||
const { again_text, is_again } = confirmAgain
|
const { again_text, is_again } = confirmAgain
|
||||||
|
|
||||||
if (is_again) {
|
if (is_again) {
|
||||||
|
@ -11,16 +11,16 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useSurveyStore } from '../stores/survey'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import communalLoader from '@materials/communals/communalLoader.js'
|
import communalLoader from '@materials/communals/communalLoader.js'
|
||||||
|
|
||||||
const LogoIcon = communalLoader.loadComponent('LogoIcon')
|
const LogoIcon = communalLoader.loadComponent('LogoIcon')
|
||||||
const store = useStore()
|
const surveyStore = useSurveyStore()
|
||||||
|
|
||||||
const logoConf = computed(() => store.state?.bottomConf || {})
|
const logoConf = computed(() => surveyStore?.bottomConf || {})
|
||||||
const successMsg = computed(() => {
|
const successMsg = computed(() => {
|
||||||
const msgContent = store.state?.submitConf?.msgContent || {}
|
const msgContent = (surveyStore?.submitConf as any)?.msgContent || {}
|
||||||
return msgContent?.msg_200 || '提交成功'
|
return msgContent?.msg_200 || '提交成功'
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,177 +0,0 @@
|
|||||||
import moment from 'moment'
|
|
||||||
// 引入中文
|
|
||||||
import 'moment/locale/zh-cn'
|
|
||||||
// 设置中文
|
|
||||||
moment.locale('zh-cn')
|
|
||||||
import adapter from '../adapter'
|
|
||||||
import { queryVote, getEncryptInfo } from '@/render/api/survey'
|
|
||||||
import { RuleMatch } from '@/common/logicEngine/RulesMatch'
|
|
||||||
/**
|
|
||||||
* CODE_MAP不从management引入,在dev阶段,会导致B端 router被加载,进而导致C端路由被添加 baseUrl: /management
|
|
||||||
*/
|
|
||||||
const CODE_MAP = {
|
|
||||||
SUCCESS: 200,
|
|
||||||
ERROR: 500,
|
|
||||||
NO_AUTH: 403
|
|
||||||
}
|
|
||||||
const VOTE_INFO_KEY = 'voteinfo'
|
|
||||||
import router from '../router'
|
|
||||||
export default {
|
|
||||||
// 初始化
|
|
||||||
init({ commit, dispatch }, { bannerConf, baseConf, bottomConf, dataConf, skinConf, submitConf }) {
|
|
||||||
commit('setEnterTime')
|
|
||||||
const { begTime, endTime, answerBegTime, answerEndTime } = baseConf
|
|
||||||
const { msgContent } = submitConf
|
|
||||||
const now = Date.now()
|
|
||||||
if (now < new Date(begTime).getTime()) {
|
|
||||||
router.push({ name: 'errorPage' })
|
|
||||||
commit('setErrorInfo', {
|
|
||||||
errorType: 'overTime',
|
|
||||||
errorMsg: `<p>问卷未到开始填写时间,暂时无法进行填写<p/>
|
|
||||||
<p>开始时间为: ${begTime}</p>`
|
|
||||||
})
|
|
||||||
return
|
|
||||||
} else if (now > new Date(endTime).getTime()) {
|
|
||||||
router.push({ name: 'errorPage' })
|
|
||||||
commit('setErrorInfo', {
|
|
||||||
errorType: 'overTime',
|
|
||||||
errorMsg: msgContent.msg_9001 || '您来晚了,感谢支持问卷~'
|
|
||||||
})
|
|
||||||
return
|
|
||||||
} else if (answerBegTime && answerEndTime) {
|
|
||||||
const momentNow = moment()
|
|
||||||
const todayStr = momentNow.format('yyyy-MM-DD')
|
|
||||||
const momentStartTime = moment(`${todayStr} ${answerBegTime}`)
|
|
||||||
const momentEndTime = moment(`${todayStr} ${answerEndTime}`)
|
|
||||||
if (momentNow.isBefore(momentStartTime) || momentNow.isAfter(momentEndTime)) {
|
|
||||||
router.push({ name: 'errorPage' })
|
|
||||||
commit('setErrorInfo', {
|
|
||||||
errorType: 'overTime',
|
|
||||||
errorMsg: `<p>不在答题时间范围内,暂时无法进行填写<p/>
|
|
||||||
<p>答题时间为: ${answerBegTime} ~ ${answerEndTime}</p>`
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
router.push({ name: 'renderPage' })
|
|
||||||
|
|
||||||
// 根据初始的schema生成questionData, questionSeq, rules, formValues, 这四个字段
|
|
||||||
const { questionData, questionSeq, rules, formValues } = adapter.generateData({
|
|
||||||
bannerConf,
|
|
||||||
baseConf,
|
|
||||||
bottomConf,
|
|
||||||
dataConf,
|
|
||||||
skinConf,
|
|
||||||
submitConf
|
|
||||||
})
|
|
||||||
|
|
||||||
// 将数据设置到state上
|
|
||||||
commit('assignState', {
|
|
||||||
questionData,
|
|
||||||
questionSeq,
|
|
||||||
rules,
|
|
||||||
bannerConf,
|
|
||||||
baseConf,
|
|
||||||
bottomConf,
|
|
||||||
dataConf,
|
|
||||||
skinConf,
|
|
||||||
submitConf,
|
|
||||||
formValues
|
|
||||||
})
|
|
||||||
// 获取已投票数据
|
|
||||||
dispatch('initVoteData')
|
|
||||||
},
|
|
||||||
// 用户输入或者选择后,更新表单数据
|
|
||||||
changeData({ commit }, data) {
|
|
||||||
commit('changeFormData', data)
|
|
||||||
},
|
|
||||||
// 初始化投票题的数据
|
|
||||||
async initVoteData({ state, commit }) {
|
|
||||||
const questionData = state.questionData
|
|
||||||
const surveyPath = state.surveyPath
|
|
||||||
|
|
||||||
const fieldList = []
|
|
||||||
|
|
||||||
for (const field in questionData) {
|
|
||||||
const { type } = questionData[field]
|
|
||||||
if (/vote/.test(type)) {
|
|
||||||
fieldList.push(field)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldList.length <= 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
localStorage.removeItem(VOTE_INFO_KEY)
|
|
||||||
const voteRes = await queryVote({
|
|
||||||
surveyPath,
|
|
||||||
fieldList: fieldList.join(',')
|
|
||||||
})
|
|
||||||
|
|
||||||
if (voteRes.code === 200) {
|
|
||||||
localStorage.setItem(
|
|
||||||
VOTE_INFO_KEY,
|
|
||||||
JSON.stringify({
|
|
||||||
...voteRes.data
|
|
||||||
})
|
|
||||||
)
|
|
||||||
commit('setVoteMap', voteRes.data)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateVoteData({ state, commit }, data) {
|
|
||||||
const { key: questionKey, value: questionVal } = data
|
|
||||||
// 更新前获取接口缓存在localStorage中的数据
|
|
||||||
const localData = localStorage.getItem(VOTE_INFO_KEY)
|
|
||||||
const voteinfo = JSON.parse(localData)
|
|
||||||
const currentQuestion = state.questionData[questionKey]
|
|
||||||
const options = currentQuestion.options
|
|
||||||
const voteTotal = voteinfo?.[questionKey]?.total || 0
|
|
||||||
let totalPayload = {
|
|
||||||
questionKey,
|
|
||||||
voteKey: 'total',
|
|
||||||
voteValue: voteTotal
|
|
||||||
}
|
|
||||||
options.forEach((option) => {
|
|
||||||
const optionhash = option.hash
|
|
||||||
const voteCount = voteinfo?.[questionKey]?.[optionhash] || 0
|
|
||||||
// 如果选中值包含该选项,对应voteCount 和 voteTotal + 1
|
|
||||||
if (
|
|
||||||
Array.isArray(questionVal) ? questionVal.includes(optionhash) : questionVal === optionhash
|
|
||||||
) {
|
|
||||||
const countPayload = {
|
|
||||||
questionKey,
|
|
||||||
voteKey: optionhash,
|
|
||||||
voteValue: voteCount + 1
|
|
||||||
}
|
|
||||||
totalPayload.voteValue += 1
|
|
||||||
commit('updateVoteMapByKey', countPayload)
|
|
||||||
} else {
|
|
||||||
const countPayload = {
|
|
||||||
questionKey,
|
|
||||||
voteKey: optionhash,
|
|
||||||
voteValue: voteCount
|
|
||||||
}
|
|
||||||
commit('updateVoteMapByKey', countPayload)
|
|
||||||
}
|
|
||||||
commit('updateVoteMapByKey', totalPayload)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
async getEncryptInfo({ commit }) {
|
|
||||||
try {
|
|
||||||
const res = await getEncryptInfo()
|
|
||||||
if (res.code === CODE_MAP.SUCCESS) {
|
|
||||||
commit('setEncryptInfo', res.data)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async initRuleEngine({ commit }, ruleConf) {
|
|
||||||
const ruleEngine = new RuleMatch(ruleConf)
|
|
||||||
commit('setRuleEgine', ruleEngine)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
export default {
|
|
||||||
// 题目列表
|
|
||||||
renderData: (state) => {
|
|
||||||
const { questionSeq, questionData } = state
|
|
||||||
|
|
||||||
let index = 1
|
|
||||||
return (
|
|
||||||
questionSeq &&
|
|
||||||
questionSeq.reduce((pre, item) => {
|
|
||||||
const questionArr = []
|
|
||||||
|
|
||||||
item.forEach((questionKey) => {
|
|
||||||
const question = { ...questionData[questionKey] }
|
|
||||||
// 开启显示序号
|
|
||||||
if (question.showIndex) {
|
|
||||||
question.indexNumber = index++
|
|
||||||
}
|
|
||||||
|
|
||||||
questionArr.push(question)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (questionArr && questionArr.length) {
|
|
||||||
pre.push(questionArr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return pre
|
|
||||||
}, [])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import { createStore } from 'vuex'
|
|
||||||
|
|
||||||
import state from './state'
|
|
||||||
import getters from './getters'
|
|
||||||
import mutations from './mutations'
|
|
||||||
import actions from './actions'
|
|
||||||
|
|
||||||
export default createStore({
|
|
||||||
state,
|
|
||||||
getters,
|
|
||||||
mutations,
|
|
||||||
actions
|
|
||||||
})
|
|
@ -1,56 +0,0 @@
|
|||||||
import { forEach, set } from 'lodash-es'
|
|
||||||
export default {
|
|
||||||
// 将数据设置到state上
|
|
||||||
assignState(state, data) {
|
|
||||||
forEach(data, (value, key) => {
|
|
||||||
state[key] = value
|
|
||||||
})
|
|
||||||
},
|
|
||||||
setQuestionData(state, data) {
|
|
||||||
state.questionData = data
|
|
||||||
},
|
|
||||||
setErrorInfo(state, { errorType, errorMsg }) {
|
|
||||||
state.errorInfo = {
|
|
||||||
errorType,
|
|
||||||
errorMsg
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeFormData(state, data) {
|
|
||||||
let { key, value } = data
|
|
||||||
// console.log('formValues', key, value)
|
|
||||||
set(state, `formValues.${key}`, value)
|
|
||||||
},
|
|
||||||
changeSelectMoreData(state, data) {
|
|
||||||
const { key, value, field } = data
|
|
||||||
set(state, `questionData.${field}.othersValue.${key}`, value)
|
|
||||||
},
|
|
||||||
setEnterTime(state) {
|
|
||||||
state.enterTime = Date.now()
|
|
||||||
},
|
|
||||||
setSurveyPath(state, data) {
|
|
||||||
state.surveyPath = data
|
|
||||||
},
|
|
||||||
setVoteMap(state, data) {
|
|
||||||
state.voteMap = data
|
|
||||||
},
|
|
||||||
updateVoteMapByKey(state, data) {
|
|
||||||
const { questionKey, voteKey, voteValue } = data
|
|
||||||
// 兼容为空的情况
|
|
||||||
if (!state.voteMap[questionKey]) {
|
|
||||||
state.voteMap[questionKey] = {}
|
|
||||||
}
|
|
||||||
state.voteMap[questionKey][voteKey] = voteValue
|
|
||||||
},
|
|
||||||
setQuestionSeq(state, data) {
|
|
||||||
state.questionSeq = data
|
|
||||||
},
|
|
||||||
setEncryptInfo(state, data) {
|
|
||||||
state.encryptInfo = data
|
|
||||||
},
|
|
||||||
setRuleEgine(state, ruleEngine) {
|
|
||||||
state.ruleEngine = ruleEngine
|
|
||||||
},
|
|
||||||
setWhiteData(state, data) {
|
|
||||||
state.whiteData = data
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
import { isMobile } from '../utils/index'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
surveyPath: '',
|
|
||||||
questionData: null,
|
|
||||||
isMobile: isMobile(),
|
|
||||||
errorInfo: {
|
|
||||||
errorType: '',
|
|
||||||
errorMsg: ''
|
|
||||||
},
|
|
||||||
enterTime: null,
|
|
||||||
questionSeq: [], // 题目的顺序,因为可能会有分页的情况,所以是一个二维数组[[qid1, qid2], [qid3,qid4]]
|
|
||||||
voteMap: {},
|
|
||||||
encryptInfo: null,
|
|
||||||
ruleEngine: null,
|
|
||||||
whiteData: {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
22
web/src/render/stores/errorInfo.js
Normal file
22
web/src/render/stores/errorInfo.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const useErrorInfo = defineStore('errorInfo', () => {
|
||||||
|
const errorInfo = ref({
|
||||||
|
errorType: '',
|
||||||
|
errorMsg: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const setErrorInfo = ({ errorType, errorMsg }) => {
|
||||||
|
errorInfo.value = {
|
||||||
|
errorType,
|
||||||
|
errorMsg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
errorInfo,
|
||||||
|
|
||||||
|
setErrorInfo
|
||||||
|
}
|
||||||
|
})
|
157
web/src/render/stores/question.js
Normal file
157
web/src/render/stores/question.js
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { set } from 'lodash-es'
|
||||||
|
import { useSurveyStore } from '@/render/stores/survey'
|
||||||
|
import { queryVote } from '@/render/api/survey'
|
||||||
|
|
||||||
|
const VOTE_INFO_KEY = 'voteinfo'
|
||||||
|
|
||||||
|
export const useQuestionStore = defineStore('question', () => {
|
||||||
|
const voteMap = ref({})
|
||||||
|
const questionData = ref(null)
|
||||||
|
const questionSeq = ref([]) // 题目的顺序,因为可能会有分页的情况,所以是一个二维数组[[qid1, qid2], [qid3,qid4]]
|
||||||
|
|
||||||
|
// 题目列表
|
||||||
|
const renderData = computed(() => {
|
||||||
|
let index = 1
|
||||||
|
return (
|
||||||
|
questionSeq.value &&
|
||||||
|
questionSeq.value.reduce((pre, item) => {
|
||||||
|
const questionArr = []
|
||||||
|
|
||||||
|
item.forEach((questionKey) => {
|
||||||
|
const question = { ...questionData.value[questionKey] }
|
||||||
|
// 开启显示序号
|
||||||
|
if (question.showIndex) {
|
||||||
|
question.indexNumber = index++
|
||||||
|
}
|
||||||
|
|
||||||
|
questionArr.push(question)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (questionArr && questionArr.length) {
|
||||||
|
pre.push(questionArr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pre
|
||||||
|
}, [])
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const setQuestionData = (data) => {
|
||||||
|
questionData.value = data
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeSelectMoreData = (data) => {
|
||||||
|
const { key, value, field } = data
|
||||||
|
set(questionData.value, `${field}.othersValue.${key}`, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const setQuestionSeq = (data) => {
|
||||||
|
questionSeq.value = data
|
||||||
|
}
|
||||||
|
|
||||||
|
const setVoteMap = (data) => {
|
||||||
|
voteMap.value = data
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateVoteMapByKey = (data) => {
|
||||||
|
const { questionKey, voteKey, voteValue } = data
|
||||||
|
// 兼容为空的情况
|
||||||
|
if (!voteMap.value[questionKey]) {
|
||||||
|
voteMap.value[questionKey] = {}
|
||||||
|
}
|
||||||
|
voteMap.value[questionKey][voteKey] = voteValue
|
||||||
|
}
|
||||||
|
|
||||||
|
//初始化投票题的数据
|
||||||
|
const initVoteData = async () => {
|
||||||
|
const surveyStore = useSurveyStore()
|
||||||
|
const surveyPath = surveyStore.surveyPath
|
||||||
|
|
||||||
|
const fieldList = []
|
||||||
|
|
||||||
|
for (const field in questionData.value) {
|
||||||
|
const { type } = questionData.value[field]
|
||||||
|
if (/vote/.test(type)) {
|
||||||
|
fieldList.push(field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldList.length <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
localStorage.removeItem(VOTE_INFO_KEY)
|
||||||
|
const voteRes = await queryVote({
|
||||||
|
surveyPath,
|
||||||
|
fieldList: fieldList.join(',')
|
||||||
|
})
|
||||||
|
|
||||||
|
if (voteRes.code === 200) {
|
||||||
|
localStorage.setItem(
|
||||||
|
VOTE_INFO_KEY,
|
||||||
|
JSON.stringify({
|
||||||
|
...voteRes.data
|
||||||
|
})
|
||||||
|
)
|
||||||
|
setVoteMap(voteRes.data)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateVoteData = (data) => {
|
||||||
|
const { key: questionKey, value: questionVal } = data
|
||||||
|
// 更新前获取接口缓存在localStorage中的数据
|
||||||
|
const localData = localStorage.getItem(VOTE_INFO_KEY)
|
||||||
|
const voteinfo = JSON.parse(localData)
|
||||||
|
const currentQuestion = questionData.value[questionKey]
|
||||||
|
const options = currentQuestion.options
|
||||||
|
const voteTotal = voteinfo?.[questionKey]?.total || 0
|
||||||
|
let totalPayload = {
|
||||||
|
questionKey,
|
||||||
|
voteKey: 'total',
|
||||||
|
voteValue: voteTotal
|
||||||
|
}
|
||||||
|
options.forEach((option) => {
|
||||||
|
const optionhash = option.hash
|
||||||
|
const voteCount = voteinfo?.[questionKey]?.[optionhash] || 0
|
||||||
|
// 如果选中值包含该选项,对应voteCount 和 voteTotal + 1
|
||||||
|
if (
|
||||||
|
Array.isArray(questionVal) ? questionVal.includes(optionhash) : questionVal === optionhash
|
||||||
|
) {
|
||||||
|
const countPayload = {
|
||||||
|
questionKey,
|
||||||
|
voteKey: optionhash,
|
||||||
|
voteValue: voteCount + 1
|
||||||
|
}
|
||||||
|
totalPayload.voteValue += 1
|
||||||
|
updateVoteMapByKey(countPayload)
|
||||||
|
} else {
|
||||||
|
const countPayload = {
|
||||||
|
questionKey,
|
||||||
|
voteKey: optionhash,
|
||||||
|
voteValue: voteCount
|
||||||
|
}
|
||||||
|
updateVoteMapByKey(countPayload)
|
||||||
|
}
|
||||||
|
updateVoteMapByKey(totalPayload)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
voteMap,
|
||||||
|
questionData,
|
||||||
|
questionSeq,
|
||||||
|
renderData,
|
||||||
|
setQuestionData,
|
||||||
|
changeSelectMoreData,
|
||||||
|
setQuestionSeq,
|
||||||
|
setVoteMap,
|
||||||
|
updateVoteMapByKey,
|
||||||
|
initVoteData,
|
||||||
|
updateVoteData
|
||||||
|
}
|
||||||
|
})
|
182
web/src/render/stores/survey.js
Normal file
182
web/src/render/stores/survey.js
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { pick } from 'lodash-es'
|
||||||
|
|
||||||
|
import { isMobile as isInMobile } from '@/render/utils/index'
|
||||||
|
import { getEncryptInfo as getEncryptInfoApi } from '@/render/api/survey'
|
||||||
|
import { useQuestionStore } from '@/render/stores/question'
|
||||||
|
import { useErrorInfo } from '@/render/stores/errorInfo'
|
||||||
|
|
||||||
|
import moment from 'moment'
|
||||||
|
// 引入中文
|
||||||
|
import 'moment/locale/zh-cn'
|
||||||
|
// 设置中文
|
||||||
|
moment.locale('zh-cn')
|
||||||
|
|
||||||
|
import adapter from '../adapter'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CODE_MAP不从management引入,在dev阶段,会导致B端 router被加载,进而导致C端路由被添加 baseUrl: /management
|
||||||
|
*/
|
||||||
|
const CODE_MAP = {
|
||||||
|
SUCCESS: 200,
|
||||||
|
ERROR: 500,
|
||||||
|
NO_AUTH: 403
|
||||||
|
}
|
||||||
|
export const useSurveyStore = defineStore('survey', () => {
|
||||||
|
const surveyPath = ref('')
|
||||||
|
const isMobile = ref(isInMobile())
|
||||||
|
const enterTime = ref(0)
|
||||||
|
const encryptInfo = ref(null)
|
||||||
|
const rules = ref({})
|
||||||
|
const bannerConf = ref({})
|
||||||
|
const baseConf = ref({})
|
||||||
|
const bottomConf = ref({})
|
||||||
|
const dataConf = ref({})
|
||||||
|
const skinConf = ref({})
|
||||||
|
const submitConf = ref({})
|
||||||
|
const formValues = ref({})
|
||||||
|
const whiteData = ref({})
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const questionStore = useQuestionStore()
|
||||||
|
const { setErrorInfo } = useErrorInfo()
|
||||||
|
|
||||||
|
const setWhiteData = (data) => {
|
||||||
|
whiteData.value = data
|
||||||
|
}
|
||||||
|
|
||||||
|
const setSurveyPath = (data) => {
|
||||||
|
surveyPath.value = data
|
||||||
|
}
|
||||||
|
|
||||||
|
const setEnterTime = () => {
|
||||||
|
enterTime.value = Date.now()
|
||||||
|
}
|
||||||
|
|
||||||
|
const getEncryptInfo = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getEncryptInfoApi()
|
||||||
|
if (res.code === CODE_MAP.SUCCESS) {
|
||||||
|
encryptInfo.value = res.data
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const canFillQuestionnaire = (baseConf, submitConf) => {
|
||||||
|
const { begTime, endTime, answerBegTime, answerEndTime } = baseConf
|
||||||
|
const { msgContent } = submitConf
|
||||||
|
const now = Date.now()
|
||||||
|
let isSuccess = true
|
||||||
|
|
||||||
|
if (now < new Date(begTime).getTime()) {
|
||||||
|
isSuccess = false
|
||||||
|
setErrorInfo({
|
||||||
|
errorType: 'overTime',
|
||||||
|
errorMsg: `<p>问卷未到开始填写时间,暂时无法进行填写<p/>
|
||||||
|
<p>开始时间为: ${begTime}</p>`
|
||||||
|
})
|
||||||
|
} else if (now > new Date(endTime).getTime()) {
|
||||||
|
isSuccess = false
|
||||||
|
setErrorInfo({
|
||||||
|
errorType: 'overTime',
|
||||||
|
errorMsg: msgContent.msg_9001 || '您来晚了,感谢支持问卷~'
|
||||||
|
})
|
||||||
|
} else if (answerBegTime && answerEndTime) {
|
||||||
|
const momentNow = moment()
|
||||||
|
const todayStr = momentNow.format('yyyy-MM-DD')
|
||||||
|
const momentStartTime = moment(`${todayStr} ${answerBegTime}`)
|
||||||
|
const momentEndTime = moment(`${todayStr} ${answerEndTime}`)
|
||||||
|
if (momentNow.isBefore(momentStartTime) || momentNow.isAfter(momentEndTime)) {
|
||||||
|
isSuccess = false
|
||||||
|
setErrorInfo({
|
||||||
|
errorType: 'overTime',
|
||||||
|
errorMsg: `<p>不在答题时间范围内,暂时无法进行填写<p/>
|
||||||
|
<p>答题时间为: ${answerBegTime} ~ ${answerEndTime}</p>`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSuccess) {
|
||||||
|
router.push({ name: 'errorPage' })
|
||||||
|
}
|
||||||
|
|
||||||
|
return isSuccess
|
||||||
|
}
|
||||||
|
const initSurvey = (option) => {
|
||||||
|
setEnterTime()
|
||||||
|
|
||||||
|
if (!canFillQuestionnaire(option.baseConf, option.submitConf)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据初始的schema生成questionData, questionSeq, rules, formValues, 这四个字段
|
||||||
|
const {
|
||||||
|
questionData,
|
||||||
|
questionSeq,
|
||||||
|
rules: _rules,
|
||||||
|
formValues: _formValues
|
||||||
|
} = adapter.generateData(
|
||||||
|
pick(option, [
|
||||||
|
'bannerConf',
|
||||||
|
'baseConf',
|
||||||
|
'bottomConf',
|
||||||
|
'dataConf',
|
||||||
|
'skinConf',
|
||||||
|
'submitConf',
|
||||||
|
'whiteData'
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
questionStore.questionData = questionData
|
||||||
|
questionStore.questionSeq = questionSeq
|
||||||
|
|
||||||
|
// 将数据设置到state上
|
||||||
|
rules.value = _rules
|
||||||
|
bannerConf.value = option.bannerConf
|
||||||
|
baseConf.value = option.baseConf
|
||||||
|
bottomConf.value = option.bottomConf
|
||||||
|
dataConf.value = option.dataConf
|
||||||
|
skinConf.value = option.skinConf
|
||||||
|
submitConf.value = option.submitConf
|
||||||
|
formValues.value = _formValues
|
||||||
|
whiteData.value = option.whiteData
|
||||||
|
|
||||||
|
// 获取已投票数据
|
||||||
|
questionStore.initVoteData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户输入或者选择后,更新表单数据
|
||||||
|
const changeData = (data) => {
|
||||||
|
let { key, value } = data
|
||||||
|
if (key in formValues.value) {
|
||||||
|
formValues.value[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
surveyPath,
|
||||||
|
isMobile,
|
||||||
|
enterTime,
|
||||||
|
encryptInfo,
|
||||||
|
rules,
|
||||||
|
bannerConf,
|
||||||
|
baseConf,
|
||||||
|
bottomConf,
|
||||||
|
dataConf,
|
||||||
|
skinConf,
|
||||||
|
submitConf,
|
||||||
|
formValues,
|
||||||
|
whiteData,
|
||||||
|
|
||||||
|
initSurvey,
|
||||||
|
changeData,
|
||||||
|
setWhiteData,
|
||||||
|
setSurveyPath,
|
||||||
|
setEnterTime,
|
||||||
|
getEncryptInfo
|
||||||
|
}
|
||||||
|
})
|
@ -61,7 +61,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: [
|
||||||
|
Loading…
Reference in New Issue
Block a user