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" />
|
||||
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",
|
||||
"nanoid": "^5.0.7",
|
||||
"node-forge": "^1.3.1",
|
||||
"pinia": "^2.1.7",
|
||||
"qrcode": "^1.5.3",
|
||||
"vue": "^3.4.15",
|
||||
"vue-router": "^4.2.5",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vuex": "^4.0.2",
|
||||
"xss": "^1.0.14",
|
||||
"yup": "^1.4.0"
|
||||
},
|
||||
|
@ -24,13 +24,13 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, shallowRef, onBeforeMount, watch, computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
import './styles/reset-wangeditor.scss'
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
|
||||
import { useUserStore } from '@/management/stores/user'
|
||||
import { replacePxWithRem } from './utils'
|
||||
|
||||
const emit = defineEmits(['input', 'onFocus', 'change', 'blur', 'created'])
|
||||
@ -66,8 +66,8 @@ const editorConfig = {
|
||||
MENU_CONF: {}
|
||||
}
|
||||
|
||||
const store = useStore()
|
||||
const token = _get(store, 'state.user.userInfo.token')
|
||||
const userStore = useUserStore()
|
||||
const token = _get(userStore, 'userInfo.token')
|
||||
|
||||
// 图片
|
||||
editorConfig.MENU_CONF['uploadImage'] = {
|
||||
|
@ -1,4 +1,4 @@
|
||||
// 静态数据
|
||||
// test:静态数据,实际业务里无用
|
||||
export const ruleConf = [
|
||||
{
|
||||
conditions: [
|
||||
|
@ -1,7 +1,7 @@
|
||||
import axios from 'axios'
|
||||
import store from '@/management/store/index'
|
||||
import router from '@/management/router/index'
|
||||
import { get as _get } from 'lodash-es'
|
||||
import { useUserStore } from '../stores/user'
|
||||
|
||||
export const CODE_MAP = {
|
||||
SUCCESS: 200,
|
||||
@ -36,8 +36,9 @@ instance.interceptors.response.use(
|
||||
)
|
||||
|
||||
instance.interceptors.request.use((config) => {
|
||||
const hasLogined = _get(store, 'state.user.hasLogined')
|
||||
const token = _get(store, 'state.user.userInfo.token')
|
||||
const userStore = useUserStore()
|
||||
const hasLogined = _get(userStore, 'hasLogined')
|
||||
const token = _get(userStore, 'userInfo.token')
|
||||
if (hasLogined && token) {
|
||||
if (!config.headers) {
|
||||
config.headers = {}
|
||||
|
@ -16,11 +16,11 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { type IMember, type ListItem } from '@/management/utils/types/workSpace'
|
||||
import OperationSelect from './OperationSelect.vue'
|
||||
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||
|
||||
const store = useStore()
|
||||
const workSpaceStore = useWorkSpaceStore()
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
members: IMember[]
|
||||
@ -43,7 +43,7 @@ const list = computed({
|
||||
}
|
||||
})
|
||||
const currentUserId = computed(() => {
|
||||
return store.state.list.spaceDetail?.currentUserId
|
||||
return workSpaceStore.spaceDetail?.currentUserId
|
||||
})
|
||||
const handleRemove = (index: number) => {
|
||||
list.value.splice(index, 1)
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import MemberList from './MemberList.vue'
|
||||
import { getUserList } from '@/management/api/space'
|
||||
import {
|
||||
@ -33,8 +32,9 @@ import {
|
||||
roleLabels
|
||||
} from '@/management/utils/types/workSpace'
|
||||
import { CODE_MAP } from '@/management/api/base'
|
||||
import { useUserStore } from '@/management/stores/user'
|
||||
|
||||
const store = useStore()
|
||||
const userStore = useUserStore()
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
members?: IMember[]
|
||||
@ -65,7 +65,7 @@ const remoteMethod = async (query: string) => {
|
||||
if (res.code === CODE_MAP.SUCCESS) {
|
||||
selectOptions.value = res.data.map((item: any) => {
|
||||
// 不可以选中自己
|
||||
const currentUser = item.username === store.state.user.userInfo.username
|
||||
const currentUser = item.username === userStore.userInfo?.username
|
||||
return {
|
||||
value: item.userId,
|
||||
label: item.username,
|
||||
|
@ -30,12 +30,12 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { useRoute } from 'vue-router'
|
||||
const route = useRoute()
|
||||
import LogoIcon from './LogoIcon.vue'
|
||||
import { SurveyPermissions } from '@/management/utils/types/workSpace.ts'
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
|
||||
const tabArr = [
|
||||
{
|
||||
@ -62,7 +62,7 @@ const tabArr = [
|
||||
]
|
||||
const tabs = ref([])
|
||||
watch(
|
||||
() => store.state.cooperPermissions,
|
||||
() => editStore.cooperPermissions,
|
||||
(newVal) => {
|
||||
tabs.value = []
|
||||
// 如果有问卷管理权限,则加入问卷编辑和投放菜单
|
||||
|
@ -1,17 +1,19 @@
|
||||
import { computed } from 'vue'
|
||||
import store from '@/management/store'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { cleanRichText } from '@/common/xss'
|
||||
export const useQuestionInfo = (field) => {
|
||||
const editStore = useEditStore()
|
||||
const { questionDataList } = storeToRefs(editStore)
|
||||
|
||||
const getQuestionTitle = computed(() => {
|
||||
const questionDataList = store.state.edit.schema.questionDataList
|
||||
return () => {
|
||||
return questionDataList.find((item) => item.field === field)?.title
|
||||
return questionDataList.value.find((item) => item.field === field)?.title
|
||||
}
|
||||
})
|
||||
const getOptionTitle = computed(() => {
|
||||
const questionDataList = store.state.edit.schema.questionDataList
|
||||
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) {
|
||||
return options
|
||||
.filter((item) => value.includes(item.hash))
|
||||
|
@ -1,14 +1,15 @@
|
||||
import { createApp } from 'vue'
|
||||
import store from './store'
|
||||
import { createPinia } from 'pinia'
|
||||
import plainText from './directive/plainText'
|
||||
import safeHtml from './directive/safeHtml'
|
||||
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
const pinia = createPinia()
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(store)
|
||||
app.use(pinia)
|
||||
app.use(router)
|
||||
|
||||
app.use(plainText)
|
||||
|
@ -133,9 +133,6 @@ const onPreviewImage = (e) => {
|
||||
}
|
||||
|
||||
.table-row-cell {
|
||||
white-space: nowrap; /* 禁止自动换行 */
|
||||
overflow: hidden; /* 超出部分隐藏 */
|
||||
text-overflow: ellipsis; /* 显示省略号 */
|
||||
:deep(img) {
|
||||
height: 23px !important;
|
||||
width: auto !important;
|
||||
|
@ -38,13 +38,11 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, toRefs } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
|
||||
import { createSurvey } from '@/management/api/survey'
|
||||
|
||||
import { SURVEY_TYPE_LIST } from '../types'
|
||||
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||
|
||||
interface Props {
|
||||
selectType?: string
|
||||
@ -54,6 +52,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
selectType: 'normal'
|
||||
})
|
||||
|
||||
const workSpaceStore = useWorkSpaceStore()
|
||||
const ruleForm = ref<any>(null)
|
||||
|
||||
const state = reactive({
|
||||
@ -79,7 +78,6 @@ const checkForm = (fn: Function) => {
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const submit = () => {
|
||||
if (!state.canSubmit) {
|
||||
return
|
||||
@ -94,8 +92,8 @@ const submit = () => {
|
||||
surveyType: selectType,
|
||||
...state.form
|
||||
}
|
||||
if (store.state.list.workSpaceId) {
|
||||
payload.workspaceId = store.state.list.workSpaceId
|
||||
if (workSpaceStore.workSpaceId) {
|
||||
payload.workspaceId = workSpaceStore.workSpaceId
|
||||
}
|
||||
const res: any = await createSurvey(payload)
|
||||
if (res?.code === 200 && res?.data?.id) {
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
<script>
|
||||
import { computed, defineComponent, ref, getCurrentInstance } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import QuestionContainerB from '@/materials/questions/QuestionContainerB'
|
||||
import QuestionWrapper from '@/management/pages/edit/components/QuestionWrapper.vue'
|
||||
import draggable from 'vuedraggable'
|
||||
@ -62,13 +62,13 @@ export default defineComponent({
|
||||
},
|
||||
emits: ['change', 'select', 'changeSeq'],
|
||||
setup(props, { emit }) {
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const renderData = computed({
|
||||
get() {
|
||||
return filterQuestionPreviewData(props.questionDataList)
|
||||
},
|
||||
set(questionDataList) {
|
||||
store.commit('edit/setQuestionDataList', questionDataList)
|
||||
set(value) {
|
||||
editStore.setQuestionDataList(value)
|
||||
}
|
||||
})
|
||||
const handleSelect = (index) => {
|
||||
|
@ -28,8 +28,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
|
||||
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 CooperationPanel from '../modules/contentModule/CooperationPanel.vue'
|
||||
|
||||
const store = useStore()
|
||||
const title = computed(() => _get(store.state, 'edit.schema.metaData.title'))
|
||||
const editStore = useEditStore()
|
||||
const { schema, changeSchema } = editStore
|
||||
const title = computed(() => (editStore.schema?.metaData as any)?.title || '')
|
||||
// 校验 - 逻辑
|
||||
const updateLogicConf = () => {
|
||||
let res = {
|
||||
@ -68,7 +68,7 @@ const updateLogicConf = () => {
|
||||
|
||||
const showLogicConf = showLogicEngine.value.toJson()
|
||||
// 更新逻辑配置
|
||||
store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
||||
changeSchema({ key: 'logicConf', value: { showLogicConf } })
|
||||
|
||||
return res
|
||||
}
|
||||
@ -82,7 +82,7 @@ const updateWhiteConf = () => {
|
||||
validated: true,
|
||||
message: ''
|
||||
}
|
||||
const baseConf = store.state.edit.schema.baseConf || {}
|
||||
const baseConf = (schema?.baseConf as any) || {}
|
||||
if (baseConf.passwordSwitch && !baseConf.password) {
|
||||
res = {
|
||||
validated: false,
|
||||
|
@ -15,7 +15,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
@ -26,16 +26,17 @@ import Navbar from './components/ModuleNavbar.vue'
|
||||
|
||||
import { initShowLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const { schema, init, setSurveyId } = editStore
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
onMounted(async () => {
|
||||
store.commit('edit/setSurveyId', route.params.id)
|
||||
setSurveyId(route.params.id as string)
|
||||
|
||||
try {
|
||||
await store.dispatch('edit/init')
|
||||
await initShowLogicEngine(store.state.edit.schema.logicConf.showLogicConf || {})
|
||||
await init()
|
||||
await initShowLogicEngine(schema.logicConf.showLogicConf || {})
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err.message)
|
||||
|
||||
|
@ -25,9 +25,9 @@
|
||||
</el-popover>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
import { ref, watch } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import moment from 'moment'
|
||||
import 'moment/locale/zh-cn'
|
||||
moment.locale('zh-cn')
|
||||
@ -44,21 +44,21 @@ const publishList = ref<Array<any>>([])
|
||||
const currentTab = ref<'daily' | 'publish'>('daily')
|
||||
const visible = ref<boolean>(false)
|
||||
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const { surveyId, schemaUpdateTime } = storeToRefs(editStore)
|
||||
|
||||
const queryHistories = async () => {
|
||||
if (dirtyMonitor.value) {
|
||||
loading.value = true
|
||||
dirtyMonitor.value = false
|
||||
|
||||
const surveyId = _get(store.state, 'edit.surveyId')
|
||||
const [dHis, pHis] = await Promise.all([
|
||||
getSurveyHistory({
|
||||
surveyId,
|
||||
surveyId: surveyId.value,
|
||||
historyType: 'dailyHis'
|
||||
}),
|
||||
getSurveyHistory({
|
||||
surveyId,
|
||||
surveyId: surveyId.value,
|
||||
historyType: 'publishHis'
|
||||
})
|
||||
]).finally(() => {
|
||||
@ -81,7 +81,6 @@ const handlePopoverShow = async () => {
|
||||
}
|
||||
const loading = ref<boolean>(false)
|
||||
const dirtyMonitor = ref<boolean>(true)
|
||||
const schemaUpdateTime = computed(() => _get(store.state, 'edit.schemaUpdateTime'))
|
||||
|
||||
watch(
|
||||
schemaUpdateTime,
|
||||
|
@ -5,7 +5,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
@ -21,7 +21,8 @@ interface Props {
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const isPublishing = ref<boolean>(false)
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const { schema, getSchemaFromRemote } = editStore
|
||||
const router = useRouter()
|
||||
|
||||
const validate = () => {
|
||||
@ -59,7 +60,7 @@ const handlePublish = async () => {
|
||||
return
|
||||
}
|
||||
|
||||
const saveData = buildData(store.state.edit.schema)
|
||||
const saveData = buildData(schema)
|
||||
if (!saveData.surveyId) {
|
||||
isPublishing.value = false
|
||||
ElMessage.error('未获取到问卷id')
|
||||
@ -77,7 +78,7 @@ const handlePublish = async () => {
|
||||
const publishRes: any = await publishSurvey({ surveyId: saveData.surveyId })
|
||||
if (publishRes.code === 200) {
|
||||
ElMessage.success('发布成功')
|
||||
store.dispatch('edit/getSchemaFromRemote')
|
||||
getSchemaFromRemote()
|
||||
router.push({ name: 'publish' })
|
||||
} else {
|
||||
ElMessage.error(`发布失败 ${publishRes.errmsg}`)
|
||||
|
@ -15,10 +15,9 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, nextTick, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { get as _get } from 'lodash-es'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
|
||||
@ -44,7 +43,9 @@ const saveText = computed(
|
||||
})[autoSaveStatus.value]
|
||||
)
|
||||
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const { schemaUpdateTime } = storeToRefs(editStore)
|
||||
const { schema } = editStore
|
||||
|
||||
const validate = () => {
|
||||
let checked = true
|
||||
@ -68,7 +69,7 @@ const validate = () => {
|
||||
}
|
||||
|
||||
const saveData = async () => {
|
||||
const saveData = buildData(store.state.edit.schema)
|
||||
const saveData = buildData(schema)
|
||||
|
||||
if (!saveData.surveyId) {
|
||||
ElMessage.error('未获取到问卷id')
|
||||
@ -144,7 +145,6 @@ const handleSave = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const schemaUpdateTime = computed(() => _get(store.state, 'edit.schemaUpdateTime'))
|
||||
watch(schemaUpdateTime, () => {
|
||||
triggerAutoSave()
|
||||
})
|
||||
|
@ -6,13 +6,13 @@
|
||||
:bannerConf="bannerConf"
|
||||
:readonly="false"
|
||||
:is-selected="currentEditOne === 'mainTitle'"
|
||||
@select="onSelectEditOne('mainTitle')"
|
||||
@select="setCurrentEditOne('mainTitle')"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<MaterialGroup
|
||||
:current-edit-one="parseInt(currentEditOne)"
|
||||
:questionDataList="questionDataList"
|
||||
@select="onSelectEditOne"
|
||||
@select="setCurrentEditOne"
|
||||
@change="handleChange"
|
||||
@changeSeq="onQuestionOperation"
|
||||
ref="materialGroup"
|
||||
@ -22,7 +22,7 @@
|
||||
:readonly="false"
|
||||
:skin-conf="skinConf"
|
||||
:is-selected="currentEditOne === 'submit'"
|
||||
@select="onSelectEditOne('submit')"
|
||||
@select="setCurrentEditOne('submit')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -30,34 +30,29 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { ref, watch, toRefs } from 'vue'
|
||||
import communalLoader from '@materials/communals/communalLoader.js'
|
||||
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 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 materialGroup = ref(null)
|
||||
|
||||
const bannerConf = computed(() => store.state.edit.schema.bannerConf)
|
||||
const submitConf = computed(() => store.state.edit.schema.submitConf)
|
||||
const skinConf = computed(() => store.state.edit.schema.skinConf)
|
||||
const questionDataList = computed(() => store.state.edit.schema.questionDataList)
|
||||
const currentEditOne = computed(() => store.state.edit.currentEditOne)
|
||||
const currentEditKey = computed(() => store.getters['edit/currentEditKey'])
|
||||
const autoScrollData = computed(() => {
|
||||
return {
|
||||
currentEditOne: currentEditOne.value,
|
||||
len: questionDataList.value.length
|
||||
}
|
||||
})
|
||||
|
||||
const onSelectEditOne = async (currentEditOne) => {
|
||||
store.commit('edit/setCurrentEditOne', currentEditOne)
|
||||
}
|
||||
const { bannerConf, submitConf, skinConf } = toRefs(schema)
|
||||
// const autoScrollData = computed(() => {
|
||||
// return {
|
||||
// currentEditOne: currentEditOne.value,
|
||||
// len: questionDataList.value.length
|
||||
// }
|
||||
// })
|
||||
|
||||
const handleChange = (data) => {
|
||||
if (currentEditOne.value === null) {
|
||||
@ -65,34 +60,33 @@ const handleChange = (data) => {
|
||||
}
|
||||
const { key, value } = data
|
||||
const resultKey = `${currentEditKey.value}.${key}`
|
||||
store.dispatch('edit/changeSchema', { key: resultKey, value })
|
||||
changeSchema({ key: resultKey, value })
|
||||
}
|
||||
|
||||
const onMainClick = (e) => {
|
||||
if (e.target === mainOperation.value) {
|
||||
store.commit('edit/setCurrentEditOne', null)
|
||||
setCurrentEditOne(null)
|
||||
}
|
||||
}
|
||||
|
||||
const onQuestionOperation = (data) => {
|
||||
switch (data.type) {
|
||||
case 'move':
|
||||
store.dispatch('edit/moveQuestion', {
|
||||
moveQuestion({
|
||||
index: data.index,
|
||||
range: data.range
|
||||
})
|
||||
break
|
||||
case 'delete':
|
||||
store.dispatch('edit/deleteQuestion', { index: data.index })
|
||||
deleteQuestion({ index: data.index })
|
||||
break
|
||||
case 'copy':
|
||||
store.dispatch('edit/copyQuestion', { index: data.index })
|
||||
copyQuestion({ index: data.index })
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
skinConf,
|
||||
(newVal) => {
|
||||
@ -114,22 +108,24 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
watch(autoScrollData, (newVal) => {
|
||||
const { currentEditOne } = newVal
|
||||
if (typeof currentEditOne === 'number') {
|
||||
setTimeout(() => {
|
||||
const field = questionDataList.value?.[currentEditOne]?.field
|
||||
if (field) {
|
||||
const questionModule = materialGroup.value?.getQuestionRefByField(field)
|
||||
if (questionModule && questionModule.$el) {
|
||||
questionModule.$el.scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
})
|
||||
}
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
// 实际编辑题目不会只是从上到下而需要上下题目对比。
|
||||
// 一直跳动到顶部影响编辑操作,若有场景需要可自行放开
|
||||
// watch(autoScrollData, (newVal) => {
|
||||
// const { currentEditOne } = newVal
|
||||
// if (typeof currentEditOne === 'number') {
|
||||
// setTimeout(() => {
|
||||
// const field = questionDataList.value?.[currentEditOne]?.field
|
||||
// if (field) {
|
||||
// const questionModule = materialGroup.value?.getQuestionRefByField(field)
|
||||
// if (questionModule && questionModule.$el) {
|
||||
// questionModule.$el.scrollIntoView({
|
||||
// behavior: 'smooth'
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// }, 0)
|
||||
// }
|
||||
// })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -17,23 +17,19 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
|
||||
import SetterField from '@/management/pages/edit/components/SetterField.vue'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const currentEditOne = computed(() => store.state?.edit?.currentEditOne)
|
||||
const formConfigList = computed(() => store.getters['edit/formConfigList'])
|
||||
const moduleConfig = computed(() => store.getters['edit/moduleConfig'])
|
||||
const currentEditKey = computed(() => store.getters['edit/currentEditKey'])
|
||||
const currentEditMeta = computed(() => store.getters['edit/currentEditMeta'])
|
||||
|
||||
const editStore = useEditStore()
|
||||
const { currentEditOne, currentEditKey, currentEditMeta, formConfigList, moduleConfig } =
|
||||
storeToRefs(editStore)
|
||||
const { changeSchema } = editStore
|
||||
const handleFormChange = (data: any) => {
|
||||
const { key, value } = data
|
||||
const resultKey = `${currentEditKey.value}.${key}`
|
||||
store.dispatch('edit/changeSchema', { key: resultKey, value })
|
||||
changeSchema({ key: resultKey, value })
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@ -12,7 +12,7 @@
|
||||
:title="element.title"
|
||||
:indexNumber="element.indexNumber"
|
||||
:showIndex="element.showIndex"
|
||||
@select="handleSelect(index)"
|
||||
@select="setCurrentEditOne(index)"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
@ -20,34 +20,30 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import draggable from 'vuedraggable'
|
||||
|
||||
import CatalogItem from './CatalogItem.vue'
|
||||
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 questions = store.state.edit.schema.questionDataList
|
||||
return filterQuestionPreviewData(questions) || []
|
||||
return filterQuestionPreviewData(questionDataList.value) || []
|
||||
})
|
||||
|
||||
const handleDragEnd = ({ newIndex, oldIndex }: any) => {
|
||||
const currentActivityKey = store.state.edit.currentEditOne
|
||||
|
||||
if (currentActivityKey === oldIndex) {
|
||||
handleSelect(newIndex)
|
||||
if (currentEditOne.value === oldIndex) {
|
||||
setCurrentEditOne(newIndex)
|
||||
}
|
||||
|
||||
store.dispatch('edit/moveQuestion', {
|
||||
moveQuestion({
|
||||
index: oldIndex,
|
||||
range: newIndex - oldIndex
|
||||
})
|
||||
}
|
||||
|
||||
const handleSelect = (idx: number) => {
|
||||
store.commit('edit/setCurrentEditOne', idx)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.question-catalog-wrapper {
|
||||
|
@ -45,20 +45,24 @@ import { DND_GROUP } from '@/management/config/dnd'
|
||||
|
||||
import questionMenuConfig, { questionTypeList } from '@/management/config/questionMenuConfig'
|
||||
import { getQuestionByType } from '@/management/utils/index'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get, isNumber as _isNumber } from 'lodash-es'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { isNumber as _isNumber } from 'lodash-es'
|
||||
import { computed, ref } from 'vue'
|
||||
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 previewImg = ref('')
|
||||
const isShowPreviewImage = ref(false)
|
||||
const previewTop = ref(0)
|
||||
const questionDataList = computed(() => _get(store, 'state.edit.schema.questionDataList'))
|
||||
const newQuestionIndex = computed(() => {
|
||||
const currentEditOne = _get(store, 'state.edit.currentEditOne')
|
||||
const index = _isNumber(currentEditOne) ? currentEditOne + 1 : questionDataList.value.length
|
||||
const index = _isNumber(currentEditOne.value)
|
||||
? currentEditOne.value + 1
|
||||
: questionDataList.value.length
|
||||
return index
|
||||
})
|
||||
|
||||
@ -78,8 +82,8 @@ const getNewQuestion = ({ type }) => {
|
||||
|
||||
const onQuestionType = ({ type }) => {
|
||||
const newQuestion = getNewQuestion({ type })
|
||||
store.dispatch('edit/addQuestion', { question: newQuestion, index: newQuestionIndex.value })
|
||||
store.commit('edit/setCurrentEditOne', newQuestionIndex.value)
|
||||
addQuestion({ question: newQuestion, index: newQuestionIndex.value })
|
||||
setCurrentEditOne(newQuestionIndex.value)
|
||||
}
|
||||
|
||||
const showPreview = ({ snapshot }, id) => {
|
||||
|
@ -17,10 +17,13 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useStore } from 'vuex'
|
||||
import { EDIT_STATUS_MAP } from './components/enum'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
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 = [
|
||||
{
|
||||
type: EDIT_STATUS_MAP.SUCCESS,
|
||||
@ -35,10 +38,8 @@ const statusList = [
|
||||
]
|
||||
|
||||
const handleChangePreview = (data: any) => {
|
||||
const currentStatus = store.state?.edit?.currentEditStatus
|
||||
|
||||
if (currentStatus && currentStatus !== data.type) {
|
||||
store.commit('edit/changeStatusPreview', data)
|
||||
if (currentEditStatus.value !== data.type) {
|
||||
editStore.changeCurrentEditStatus(data.type)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -12,9 +12,9 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
import { toRef } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
|
||||
import SuccessContent from './components/SuccessContent.vue'
|
||||
import OverTime from './components/OverTime.vue'
|
||||
@ -25,11 +25,10 @@ const components = {
|
||||
[EDIT_STATUS_MAP.OVERTIME]: OverTime
|
||||
}
|
||||
|
||||
const store = useStore()
|
||||
const currentEditStatus = computed(() => store.state?.edit?.currentEditStatus)
|
||||
const moduleConfig = computed(() => {
|
||||
return _get(store.state, 'edit.schema.submitConf')
|
||||
})
|
||||
const editStore = useEditStore()
|
||||
const { currentEditStatus } = storeToRefs(editStore)
|
||||
const { schema } = editStore
|
||||
const moduleConfig = toRef(schema, 'submitConf')
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.result-config-preview {
|
||||
|
@ -23,8 +23,9 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, shallowRef } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { computed, ref, shallowRef, toRef } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { get as _get } from 'lodash-es'
|
||||
|
||||
import FormItem from '@/materials/setters/widgets/FormItem.vue'
|
||||
@ -36,15 +37,16 @@ const textMap = {
|
||||
OverTime: '问卷过期页面配置'
|
||||
}
|
||||
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const { currentEditStatus } = storeToRefs(editStore)
|
||||
const { schema, changeSchema } = editStore
|
||||
|
||||
const components = shallowRef<any>({})
|
||||
const registerTypes = ref<any>({})
|
||||
const moduleConfig = computed(() => _get(store.state, 'edit.schema.submitConf'))
|
||||
const currentEditText = computed(() => (textMap as any)[store.state.edit.currentEditStatus])
|
||||
const moduleConfig = toRef(schema, 'submitConf')
|
||||
const currentEditText = computed(() => (textMap as any)[currentEditStatus.value])
|
||||
const formFields = computed(() => {
|
||||
const currentStatus = store.state.edit.currentEditStatus
|
||||
const formList = (statusConfig as any)[currentStatus] || []
|
||||
const formList = (statusConfig as any)[currentEditStatus.value] || []
|
||||
const list = formList.map((item: any) => {
|
||||
const value = _get(moduleConfig.value, item.key, item.value)
|
||||
|
||||
@ -57,7 +59,7 @@ const formFields = computed(() => {
|
||||
})
|
||||
|
||||
const handleFormChange = ({ key, value }: any) => {
|
||||
store.dispatch('edit/changeSchema', {
|
||||
changeSchema({
|
||||
key: `submitConf.${key}`,
|
||||
value
|
||||
})
|
||||
|
@ -38,13 +38,13 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, onMounted, shallowRef } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import {
|
||||
cloneDeep as _cloneDeep,
|
||||
isArray as _isArray,
|
||||
get as _get,
|
||||
isFunction as _isFunction
|
||||
} from 'lodash-es'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
|
||||
import baseConfig from '@/management/pages/edit/setterConfig/baseConfig'
|
||||
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 TeamMemberList from './components/TeamMemberList.vue'
|
||||
|
||||
const editStore = useEditStore()
|
||||
const { schema, changeSchema } = editStore
|
||||
|
||||
const formConfigList = ref<Array<any>>([])
|
||||
const components = shallowRef<any>({
|
||||
['WhiteList']: WhiteList,
|
||||
@ -64,8 +67,8 @@ const registerTypes = ref<any>({
|
||||
WhiteList: 'WhiteList',
|
||||
TeamMemberList: 'TeamMemberList'
|
||||
})
|
||||
const store = useStore()
|
||||
const schemaBaseConf = computed(() => store.state.edit?.schema?.baseConf || {})
|
||||
|
||||
const schemaBaseConf = computed(() => schema?.baseConf || {})
|
||||
|
||||
const setterList = computed(() => {
|
||||
const list = _cloneDeep(formConfigList.value)
|
||||
@ -79,12 +82,12 @@ const setterList = computed(() => {
|
||||
if (_isArray(formKey)) {
|
||||
formValue = []
|
||||
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)
|
||||
dataConfig[key] = val
|
||||
}
|
||||
} else {
|
||||
formValue = _get(store.state.edit.schema, formKey, formItem.value)
|
||||
formValue = _get(schema, formKey, formItem.value)
|
||||
dataConfig[formKey] = formValue
|
||||
}
|
||||
formItem.value = formValue
|
||||
@ -103,9 +106,8 @@ const setterList = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
const handleFormChange = (data: any) => {
|
||||
store.dispatch('edit/changeSchema', {
|
||||
changeSchema({
|
||||
key: data.key,
|
||||
value: data.value
|
||||
})
|
||||
@ -173,7 +175,6 @@ onMounted(async () => {
|
||||
padding-bottom: 19px;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid $border-color;
|
||||
padding-left: 30px;
|
||||
|
||||
span {
|
||||
position: relative;
|
||||
|
@ -21,7 +21,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<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 { getMemberList } from '@/management/api/space'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
@ -27,13 +27,14 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
|
||||
import skinPresets from '@/management/config/skinPresets.js'
|
||||
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const { changeThemePreset } = editStore
|
||||
const groupName = ref<string>('temp')
|
||||
const bannerList = computed(() => store?.state?.bannerList || [])
|
||||
const bannerList = computed(() => editStore.bannerList || [])
|
||||
const groupList = computed(() =>
|
||||
Object.keys(bannerList.value).map((key) => ({
|
||||
label: bannerList.value[key].name,
|
||||
@ -81,7 +82,7 @@ const changePreset = (banner: any) => {
|
||||
presets = Object.assign(presets, (skinPresets as any)[name])
|
||||
}
|
||||
|
||||
store.dispatch('edit/changeThemePreset', presets)
|
||||
changeThemePreset(presets)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@ -108,7 +109,10 @@ const changePreset = (banner: any) => {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.tag {
|
||||
margin: 5px 8px;
|
||||
width: 55px;
|
||||
margin: 5px 2px;
|
||||
cursor: pointer;
|
||||
flex: auto;
|
||||
cursor: pointer;
|
||||
&.current {
|
||||
color: $primary-color;
|
||||
|
@ -24,9 +24,10 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import { defineComponent, toRefs } from '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'
|
||||
|
||||
const HeaderContent = () => communalLoader.loadComponent('HeaderContent')
|
||||
@ -43,15 +44,10 @@ export default defineComponent({
|
||||
LogoIcon: LogoIcon()
|
||||
},
|
||||
setup() {
|
||||
const store = useStore()
|
||||
|
||||
const bannerConf = computed(() => store.state.edit.schema.bannerConf)
|
||||
const submitConf = computed(() => store.state.edit.schema.submitConf)
|
||||
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'])
|
||||
const editStore = useEditStore()
|
||||
const { questionDataList, currentEditOne, currentEditKey } = storeToRefs(editStore)
|
||||
const { schema } = editStore
|
||||
const { bannerConf, submitConf, skinConf, bottomConf } = toRefs(schema)
|
||||
|
||||
return {
|
||||
bannerConf,
|
||||
|
@ -24,23 +24,23 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { ref } from 'vue'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { get as _get } from 'lodash-es'
|
||||
|
||||
import skinConfig from '@/management/pages/edit/setterConfig/skinConfig'
|
||||
import SetterField from '@/management/pages/edit/components/SetterField.vue'
|
||||
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const { schema, changeSchema } = editStore
|
||||
const collapse = ref<string>('')
|
||||
const schema = computed(() => _get(store.state, 'edit.schema'))
|
||||
|
||||
const handleFormChange = (data: any, collapse: string) => {
|
||||
const { key, value } = data
|
||||
const currentEditKey = `${collapse}`
|
||||
const resultKey = `${currentEditKey}.${key}`
|
||||
|
||||
store.dispatch('edit/changeSchema', { key: resultKey, value })
|
||||
changeSchema({ key: resultKey, value })
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@ -5,17 +5,15 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
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 RulePanel from '../../modules/logicModule/RulePanel.vue'
|
||||
import { filterQuestionPreviewData } from '@/management/utils/index'
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const questionDataList = computed(() => {
|
||||
return store.state.edit.schema.questionDataList
|
||||
})
|
||||
const editStore = useEditStore()
|
||||
const { questionDataList } = storeToRefs(editStore)
|
||||
|
||||
const renderData = computed(() => {
|
||||
return filterQuestionPreviewData(cloneDeep(questionDataList.value))
|
||||
|
@ -13,17 +13,17 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
|
||||
import CommonTemplate from '../../components/CommonTemplate.vue'
|
||||
import CatalogPanel from '../../modules/skinModule/CatalogPanel.vue'
|
||||
import PreviewPanel from '../../modules/skinModule/PreviewPanel.vue'
|
||||
import SetterPanel from '../../modules/skinModule/SetterPanel.vue'
|
||||
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
|
||||
onMounted(() => {
|
||||
store.dispatch('getBannerData')
|
||||
editStore.fetchBannerData()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@ -8,11 +8,17 @@ export default [
|
||||
title: '提交限制',
|
||||
key: 'limitConfig',
|
||||
formList: ['limit_tLimit']
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: '作答限制',
|
||||
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',
|
||||
placement: 'top'
|
||||
},
|
||||
interview_pwd: {
|
||||
keys: ['baseConf.passwordSwitch', 'baseConf.password'],
|
||||
interview_pwd_switch: {
|
||||
key: 'baseConf.passwordSwitch',
|
||||
label: '访问密码',
|
||||
type: 'SwitchInput',
|
||||
type: 'CustomedSwitch'
|
||||
},
|
||||
interview_pwd: {
|
||||
type: 'InputSetter',
|
||||
placeholder: '请输入6位字符串类型访问密码 ',
|
||||
maxLength: 6
|
||||
maxLength: 6,
|
||||
relyFunc: (data) => {
|
||||
return !!data?.passwordSwitch
|
||||
}
|
||||
},
|
||||
answer_type: {
|
||||
key: 'baseConf.whitelistType',
|
||||
@ -52,7 +58,7 @@ export default {
|
||||
key: 'baseConf.whitelistTip',
|
||||
label: '名单登录提示语',
|
||||
placeholder: '请输入名单提示语',
|
||||
type: 'InputWordLimit',
|
||||
type: 'InputSetter',
|
||||
maxLength: 40,
|
||||
relyFunc: (data) => {
|
||||
return ['CUSTOM', 'MEMBER'].includes(data.whitelistType)
|
||||
|
@ -105,9 +105,9 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, unref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { get, map } from 'lodash-es'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
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 { QOP_MAP } from '@/management/utils/constant.ts'
|
||||
import { deleteSurvey } from '@/management/api/survey'
|
||||
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||
import { useSurveyListStore } from '@/management/stores/surveyList'
|
||||
import ModifyDialog from './ModifyDialog.vue'
|
||||
import TagModule from './TagModule.vue'
|
||||
import StateModule from './StateModule.vue'
|
||||
@ -141,7 +143,9 @@ import {
|
||||
buttonOptionsDict
|
||||
} from '@/management/config/listConfig'
|
||||
|
||||
const store = useStore()
|
||||
const surveyListStore = useSurveyListStore()
|
||||
const workSpaceStore = useWorkSpaceStore()
|
||||
const { workSpaceId } = storeToRefs(workSpaceStore)
|
||||
const router = useRouter()
|
||||
const props = defineProps({
|
||||
loading: {
|
||||
@ -162,17 +166,9 @@ const fields = ['type', 'title', 'remark', 'owner', 'state', 'createDate', 'upda
|
||||
const showModify = ref(false)
|
||||
const modifyType = ref('')
|
||||
const questionInfo = ref({})
|
||||
|
||||
const currentPage = ref(1)
|
||||
const searchVal = computed(() => {
|
||||
return store.state.list.searchVal
|
||||
})
|
||||
const selectValueMap = computed(() => {
|
||||
return store.state.list.selectValueMap
|
||||
})
|
||||
const buttonValueMap = computed(() => {
|
||||
return store.state.list.buttonValueMap
|
||||
})
|
||||
const { searchVal, selectValueMap, buttonValueMap } = storeToRefs(surveyListStore)
|
||||
|
||||
const currentComponent = computed(() => {
|
||||
return (componentName) => {
|
||||
switch (componentName) {
|
||||
@ -247,9 +243,6 @@ const order = computed(() => {
|
||||
}, [])
|
||||
return JSON.stringify(formatOrder)
|
||||
})
|
||||
const workSpaceId = computed(() => {
|
||||
return store.state.list.workSpaceId
|
||||
})
|
||||
|
||||
const onRefresh = async () => {
|
||||
const filterString = JSON.stringify(
|
||||
@ -298,7 +291,7 @@ const getToolConfig = (row) => {
|
||||
label: '协作'
|
||||
}
|
||||
]
|
||||
if (!store.state.list.workSpaceId) {
|
||||
if (!workSpaceId.value) {
|
||||
if (!row.isCollaborated) {
|
||||
// 创建人显示协作按钮
|
||||
funcList = funcList.concat(permissionsBtn)
|
||||
@ -430,19 +423,18 @@ const onRowClick = (row) => {
|
||||
})
|
||||
}
|
||||
const onSearchText = (e) => {
|
||||
store.commit('list/setSearchVal', e)
|
||||
searchVal.value = e
|
||||
currentPage.value = 1
|
||||
onRefresh()
|
||||
}
|
||||
const onSelectChange = (selectKey, selectValue) => {
|
||||
store.commit('list/changeSelectValueMap', { key: selectKey, value: selectValue })
|
||||
// selectValueMap.value[selectKey] = selectValue
|
||||
surveyListStore.changeSelectValueMap(selectKey, selectValue)
|
||||
currentPage.value = 1
|
||||
onRefresh()
|
||||
}
|
||||
const onButtonChange = (effectKey, effectValue) => {
|
||||
store.commit('list/resetButtonValueMap')
|
||||
store.commit('list/changeButtonValueMap', { key: effectKey, value: effectValue })
|
||||
surveyListStore.resetButtonValueMap()
|
||||
surveyListStore.changeButtonValueMap(effectKey, effectValue)
|
||||
onRefresh()
|
||||
}
|
||||
|
||||
@ -464,16 +456,20 @@ const onCooperClose = () => {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.select {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.search {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.list-wrapper {
|
||||
padding: 10px 20px;
|
||||
background: #fff;
|
||||
|
||||
.list-table {
|
||||
min-height: 620px;
|
||||
}
|
||||
@ -481,11 +477,13 @@ const onCooperClose = () => {
|
||||
|
||||
.list-pagination {
|
||||
margin-top: 20px;
|
||||
|
||||
:deep(.el-pagination) {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__header) {
|
||||
.tableview-header .el-table__cell {
|
||||
.cell {
|
||||
@ -495,21 +493,26 @@ const onCooperClose = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.tableview-row) {
|
||||
.tableview-cell {
|
||||
padding: 5px 0;
|
||||
|
||||
&.link {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cell .cell-span {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-select-dropdown__wrap {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.el-select-dropdown__item.hover {
|
||||
background: #fff;
|
||||
}
|
||||
|
@ -76,7 +76,6 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message-box.scss'
|
||||
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 ToolBar from './ToolBar.vue'
|
||||
import { UserRole } from '@/management/utils/types/workSpace'
|
||||
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||
|
||||
const showSpaceModify = ref(false)
|
||||
const modifyType = ref('edit')
|
||||
const store = useStore()
|
||||
const props = defineProps({
|
||||
loading: {
|
||||
type: Boolean,
|
||||
@ -109,15 +108,17 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['refresh'])
|
||||
const workSpaceStore = useWorkSpaceStore()
|
||||
const fields = ['name', 'surveyTotal', 'memberTotal', 'owner', 'createDate']
|
||||
const fieldList = computed(() => {
|
||||
return map(fields, (f) => {
|
||||
return get(spaceListConfig, f, null)
|
||||
})
|
||||
})
|
||||
|
||||
const isAdmin = (id: string) => {
|
||||
return (
|
||||
store.state.list.teamSpaceList.find((item: any) => item._id === id)?.currentUserRole ===
|
||||
workSpaceStore.workSpaceList.find((item: any) => item._id === id)?.currentUserRole ===
|
||||
UserRole.Admin
|
||||
)
|
||||
}
|
||||
@ -152,7 +153,7 @@ const getTools = (data: any) => {
|
||||
}
|
||||
|
||||
const handleModify = async (id: string) => {
|
||||
await store.dispatch('list/getSpaceDetail', id)
|
||||
await workSpaceStore.getSpaceDetail(id)
|
||||
modifyType.value = 'edit'
|
||||
showSpaceModify.value = true
|
||||
}
|
||||
@ -167,9 +168,8 @@ const handleDelete = (id: string) => {
|
||||
}
|
||||
)
|
||||
.then(async () => {
|
||||
await store.dispatch('list/deleteSpace', id)
|
||||
await store.dispatch('list/getSpaceList')
|
||||
curPage.value = 1
|
||||
await workSpaceStore.deleteSpace(id)
|
||||
await workSpaceStore.getSpaceList()
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
@ -184,9 +184,9 @@ const handleClick = (key: string, data: any) => {
|
||||
|
||||
const onCloseModify = () => {
|
||||
showSpaceModify.value = false
|
||||
store.dispatch('list/getSpaceList')
|
||||
curPage.value = 1
|
||||
workSpaceStore.getSpaceList()
|
||||
}
|
||||
|
||||
defineExpose({ onCloseModify })
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@ -44,17 +44,17 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, shallowRef, onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { pick as _pick } from 'lodash-es'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
|
||||
import { QOP_MAP } from '@/management/utils/constant'
|
||||
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'
|
||||
|
||||
const store = useStore()
|
||||
const workSpaceStore = useWorkSpaceStore()
|
||||
const emit = defineEmits(['on-close-codify', 'onFocus', 'change', 'blur'])
|
||||
const props = defineProps({
|
||||
type: String,
|
||||
@ -66,7 +66,8 @@ const ruleForm = shallowRef<any>(null)
|
||||
const formTitle = computed(() => {
|
||||
return props.type === QOP_MAP.ADD ? '创建团队空间' : '管理团队空间'
|
||||
})
|
||||
const formModel = ref<IWorkspace>({
|
||||
const formModel = ref<Required<IWorkspace>>({
|
||||
_id: '',
|
||||
name: '',
|
||||
description: '',
|
||||
members: [] as IMember[]
|
||||
@ -88,28 +89,29 @@ const rules = {
|
||||
]
|
||||
}
|
||||
const spaceDetail = computed(() => {
|
||||
return store.state.list.spaceDetail
|
||||
return workSpaceStore.spaceDetail
|
||||
})
|
||||
const formDisabled = computed(() => {
|
||||
return spaceDetail.value?._id
|
||||
? store.state.list.teamSpaceList.find((item: any) => item._id === spaceDetail.value._id)
|
||||
.currentUserRole !== UserRole.Admin
|
||||
? workSpaceStore.workSpaceList.find((item: any) => item._id === spaceDetail.value?._id)
|
||||
?.currentUserRole !== UserRole.Admin
|
||||
: false
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
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 = () => {
|
||||
formModel.value = {
|
||||
_id: '',
|
||||
name: '',
|
||||
description: '',
|
||||
members: [] as IMember[]
|
||||
}
|
||||
// 清空空间详情
|
||||
store.commit('list/setSpaceDetail', null)
|
||||
workSpaceStore.setSpaceDetail(null)
|
||||
emit('on-close-codify')
|
||||
}
|
||||
|
||||
@ -144,10 +146,10 @@ const handleMembersChange = (val: IMember[]) => {
|
||||
formModel.value.members = val
|
||||
}
|
||||
const handleUpdate = async () => {
|
||||
await store.dispatch('list/updateSpace', formModel.value)
|
||||
await workSpaceStore.updateSpace(formModel.value)
|
||||
}
|
||||
const handleAdd = async () => {
|
||||
await store.dispatch('list/addSpace', formModel.value)
|
||||
await workSpaceStore.addSpace(formModel.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -56,8 +56,8 @@
|
||||
ref="spaceListRef"
|
||||
@refresh="fetchSpaceList"
|
||||
:loading="spaceLoading"
|
||||
:data="spaceList"
|
||||
:total="spaceTotal"
|
||||
:data="workSpaceList"
|
||||
:total="workSpaceListTotal"
|
||||
v-if="spaceType === SpaceType.Group"
|
||||
></SpaceList>
|
||||
</div>
|
||||
@ -73,83 +73,66 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useRouter } from 'vue-router'
|
||||
import BaseList from './components/BaseList.vue'
|
||||
import SpaceList from './components/SpaceList.vue'
|
||||
import SliderBar from './components/SliderBar.vue'
|
||||
import SpaceModify from './components/SpaceModify.vue'
|
||||
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 userInfo = computed(() => {
|
||||
return store.state.user.userInfo
|
||||
return userStore.userInfo
|
||||
})
|
||||
|
||||
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 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 spaceMenus = computed(() => {
|
||||
return store.state.list.spaceMenus
|
||||
})
|
||||
const workSpaceId = computed(() => {
|
||||
return store.state.list.workSpaceId
|
||||
})
|
||||
const spaceType = computed(() => {
|
||||
return store.state.list.spaceType
|
||||
})
|
||||
const fetchSpaceList = async (params?: any) => {
|
||||
spaceLoading.value = true
|
||||
workSpaceStore.changeWorkSpace('')
|
||||
workSpaceStore.getSpaceList(params)
|
||||
spaceLoading.value = false
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
const changeSpaceType = (type: SpaceType) => {
|
||||
store.commit('list/changeSpaceType', type)
|
||||
}
|
||||
const changeWorkSpace = (id: string) => {
|
||||
store.commit('list/changeWorkSpace', id)
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case SpaceType.Personal:
|
||||
changeSpaceType(SpaceType.Personal)
|
||||
changeWorkSpace('')
|
||||
workSpaceStore.changeSpaceType(SpaceType.Personal)
|
||||
workSpaceStore.changeWorkSpace('')
|
||||
break
|
||||
case SpaceType.Group:
|
||||
changeSpaceType(SpaceType.Group)
|
||||
changeWorkSpace('')
|
||||
workSpaceStore.changeSpaceType(SpaceType.Group)
|
||||
workSpaceStore.changeWorkSpace('')
|
||||
fetchSpaceList()
|
||||
break
|
||||
default:
|
||||
changeSpaceType(SpaceType.Teamwork)
|
||||
changeWorkSpace(id)
|
||||
workSpaceStore.changeSpaceType(SpaceType.Teamwork)
|
||||
workSpaceStore.changeWorkSpace(id)
|
||||
break
|
||||
}
|
||||
fetchSurveyList()
|
||||
}
|
||||
onMounted(() => {
|
||||
fetchSpaceList()
|
||||
fetchSurveyList()
|
||||
})
|
||||
|
||||
const fetchSurveyList = async (params?: any) => {
|
||||
if (!params) {
|
||||
params = {
|
||||
@ -161,19 +144,25 @@ const fetchSurveyList = async (params?: any) => {
|
||||
params.workspaceId = workSpaceId.value
|
||||
}
|
||||
loading.value = true
|
||||
await store.dispatch('list/getSurveyList', params)
|
||||
await surveyListStore.getSurveyList(params)
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchSpaceList()
|
||||
fetchSurveyList()
|
||||
})
|
||||
|
||||
const modifyType = ref('add')
|
||||
const showSpaceModify = ref(false)
|
||||
|
||||
// 当前团队信息
|
||||
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 () => {
|
||||
await store.dispatch('list/getSpaceDetail', workSpaceId.value)
|
||||
await workSpaceStore.getSpaceDetail(workSpaceId.value)
|
||||
modifyType.value = 'edit'
|
||||
showSpaceModify.value = true
|
||||
}
|
||||
@ -192,7 +181,7 @@ const onCreate = () => {
|
||||
router.push('/create')
|
||||
}
|
||||
const handleLogout = () => {
|
||||
store.dispatch('user/logout')
|
||||
userStore.logout()
|
||||
router.replace({ name: 'login' })
|
||||
}
|
||||
</script>
|
||||
|
@ -57,7 +57,6 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, reactive } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
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 { refreshCaptcha as refreshCaptchaApi } from '@/management/api/captcha'
|
||||
import { CODE_MAP } from '@/management/api/base'
|
||||
import { useUserStore } from '@/management/stores/user'
|
||||
|
||||
const store = useStore()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
@ -150,7 +149,8 @@ const submitForm = (type: 'login' | 'register') => {
|
||||
ElMessage.error(res.errmsg)
|
||||
throw new Error('登录/注册失败' + res.errmsg)
|
||||
}
|
||||
store.dispatch('user/login', {
|
||||
const userStore = useUserStore()
|
||||
userStore.login({
|
||||
username: res.data.username,
|
||||
token: res.data.token
|
||||
})
|
||||
|
@ -25,8 +25,8 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { computed, onMounted, toRef } from 'vue'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { get as _get } from 'lodash-es'
|
||||
|
||||
@ -44,14 +44,15 @@ const defaultConfig = {
|
||||
img: '/imgs/icons/unpublished.webp'
|
||||
}
|
||||
|
||||
const store = useStore()
|
||||
const metaData = computed(() => _get(store.state, 'edit.schema.metaData'))
|
||||
const editStore = useEditStore()
|
||||
const { schema, init, setSurveyId } = editStore
|
||||
const metaData = toRef(schema, 'metaData')
|
||||
const curStatus = computed(() => _get(metaData.value, 'curStatus.status', 'new'))
|
||||
const mainChannel = computed(() => {
|
||||
let fullUrl = ''
|
||||
|
||||
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 }
|
||||
@ -60,10 +61,10 @@ const mainChannel = computed(() => {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
onMounted(async () => {
|
||||
store.commit('edit/setSurveyId', route.params.id)
|
||||
setSurveyId(route.params.id as string)
|
||||
|
||||
try {
|
||||
await store.dispatch('edit/init')
|
||||
await init()
|
||||
} catch (err: any) {
|
||||
ElMessage.error(err.message)
|
||||
setTimeout(() => {
|
||||
|
@ -5,11 +5,12 @@ import {
|
||||
type NavigationGuardNext
|
||||
} from 'vue-router'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import { useStore, type Store } from 'vuex'
|
||||
import { SurveyPermissions } from '@/management/utils/types/workSpace'
|
||||
import { analysisTypeMap } from '@/management/config/analysisConfig'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
import { useUserStore } from '@/management/stores/user'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
@ -161,10 +162,10 @@ const router = createRouter({
|
||||
})
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
const store = useStore()
|
||||
const userStore = useUserStore()
|
||||
// 初始化用户信息
|
||||
if (!store.state.user?.initialized) {
|
||||
await store.dispatch('user/init')
|
||||
if (!userStore?.initialized) {
|
||||
await userStore.init()
|
||||
}
|
||||
// 更新页面标题
|
||||
if (to.meta.title) {
|
||||
@ -172,7 +173,7 @@ router.beforeEach(async (to, from, next) => {
|
||||
}
|
||||
|
||||
if (to.meta.needLogin) {
|
||||
await handleLoginGuard(to, from, next, store)
|
||||
await handleLoginGuard(to, from, next)
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
@ -181,11 +182,11 @@ router.beforeEach(async (to, from, next) => {
|
||||
async function handleLoginGuard(
|
||||
to: RouteLocationNormalized,
|
||||
from: RouteLocationNormalized,
|
||||
next: NavigationGuardNext,
|
||||
store: Store<any>
|
||||
next: NavigationGuardNext
|
||||
) {
|
||||
if (store.state.user?.hasLogined) {
|
||||
await handlePermissionsGuard(to, from, next, store)
|
||||
const userStore = useUserStore()
|
||||
if (userStore?.hasLogined) {
|
||||
await handlePermissionsGuard(to, from, next)
|
||||
} else {
|
||||
next({
|
||||
name: 'login',
|
||||
@ -197,9 +198,9 @@ async function handleLoginGuard(
|
||||
async function handlePermissionsGuard(
|
||||
to: RouteLocationNormalized,
|
||||
from: RouteLocationNormalized,
|
||||
next: NavigationGuardNext,
|
||||
store: Store<any>
|
||||
next: NavigationGuardNext
|
||||
) {
|
||||
const editStore = useEditStore()
|
||||
const currSurveyId = to?.params?.id || ''
|
||||
const prevSurveyId = from?.params?.id || ''
|
||||
// 如果跳转页面不存在surveyId 或者不需要页面权限,则直接跳转
|
||||
@ -208,8 +209,8 @@ async function handlePermissionsGuard(
|
||||
} else {
|
||||
// 如果跳转编辑页面,且跳转页面和上一页的surveyId不同,判断是否有对应页面权限
|
||||
if (currSurveyId !== prevSurveyId) {
|
||||
await store.dispatch('fetchCooperPermissions', currSurveyId)
|
||||
if (hasRequiredPermissions(to.meta.permissions as string[], store.state.cooperPermissions)) {
|
||||
await editStore.fetchCooperPermissions(currSurveyId as string)
|
||||
if (hasRequiredPermissions(to.meta.permissions as string[], editStore.cooperPermissions)) {
|
||||
next()
|
||||
} else {
|
||||
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
|
||||
}
|
||||
})
|
@ -51,7 +51,7 @@ export const getQuestionByType = (type, fields) => {
|
||||
}
|
||||
|
||||
newQuestion.field = getNewField(fields) // 动态生成题目id
|
||||
if ('options ' in newQuestion) {
|
||||
if ('options' in newQuestion) {
|
||||
// 动态更新选项的hash-id
|
||||
const hashList = []
|
||||
for (const option of newQuestion.options) {
|
||||
|
@ -11,11 +11,12 @@ export interface MenuItem {
|
||||
}
|
||||
|
||||
export type IWorkspace = {
|
||||
id?: string
|
||||
_id?: string
|
||||
name: string
|
||||
description: string
|
||||
members: IMember[]
|
||||
}
|
||||
|
||||
export type IMember = {
|
||||
userId: string
|
||||
username: string
|
||||
@ -23,6 +24,24 @@ export type IMember = {
|
||||
_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 {
|
||||
Personal = 'personal',
|
||||
Group = 'group',
|
||||
|
@ -2,6 +2,7 @@
|
||||
<el-input
|
||||
:placeholder="formConfig.placeholder"
|
||||
v-model="modelValue"
|
||||
:maxlength="formConfig.maxLength"
|
||||
@blur="handleInputBlur"
|
||||
></el-input>
|
||||
</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>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
import { watch } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const store = useStore()
|
||||
const skinConf = computed(() => _get(store, 'state.skinConf', {}))
|
||||
import { useSurveyStore } from './stores/survey'
|
||||
|
||||
const { skinConf } = storeToRefs(useSurveyStore())
|
||||
|
||||
const updateSkinConfig = (value: any) => {
|
||||
const root = document.documentElement
|
||||
|
@ -33,7 +33,7 @@ export const getEncryptInfo = () => {
|
||||
return axios.get('/clientEncrypt/getEncryptInfo')
|
||||
}
|
||||
|
||||
export const validate = ({ surveyPath,password, whitelist }) => {
|
||||
export const validate = ({ surveyPath, password, whitelist }) => {
|
||||
return axios.post(`/responseSchema/${surveyPath}/validate`, {
|
||||
password,
|
||||
whitelist
|
||||
|
@ -13,17 +13,20 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
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 rules = computed(() => store.state.rules)
|
||||
const formValues = computed(() => store.state.formValues)
|
||||
const renderData = computed(() => questionStore.renderData)
|
||||
|
||||
const { rules, formValues } = storeToRefs(surveyStore)
|
||||
|
||||
const handleChangeData = (data: any) => {
|
||||
store.dispatch('changeData', data)
|
||||
surveyStore.changeData(data)
|
||||
}
|
||||
</script>
|
||||
|
@ -13,9 +13,10 @@ import QuestionRuleContainer from '../../materials/questions/QuestionRuleContain
|
||||
import { useVoteMap } from '@/render/hooks/useVoteMap'
|
||||
import { useShowOthers } from '@/render/hooks/useShowOthers'
|
||||
import { useShowInput } from '@/render/hooks/useShowInput'
|
||||
import store from '@/render/store'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
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'
|
||||
|
||||
@ -32,9 +33,11 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['change'])
|
||||
const questionStore = useQuestionStore()
|
||||
const surveyStore = useSurveyStore()
|
||||
|
||||
const formValues = computed(() => {
|
||||
return store.state.formValues
|
||||
return surveyStore.formValues
|
||||
})
|
||||
const questionConfig = computed(() => {
|
||||
let moduleConfig = props.moduleConfig
|
||||
@ -96,7 +99,7 @@ watch(
|
||||
key: field,
|
||||
value: value
|
||||
}
|
||||
store.commit('changeFormData', data)
|
||||
surveyStore.changeData(data)
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -105,7 +108,7 @@ const handleChange = (data) => {
|
||||
emit('change', data)
|
||||
// 处理投票题
|
||||
if (props.moduleConfig.type === QUESTION_TYPE.VOTE) {
|
||||
store.dispatch('updateVoteData', data)
|
||||
questionStore.updateVoteData(data)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,43 +1,52 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="whiteVisible"
|
||||
title="验证"
|
||||
:show-close="false"
|
||||
class="verify-white-wrap"
|
||||
width="315"
|
||||
:close-on-press-escape="false"
|
||||
:close-on-click-modal="false"
|
||||
align-center
|
||||
|
||||
>
|
||||
<template #header>
|
||||
<div class="verify-white-head">
|
||||
<div class="verify-white-title">验证</div>
|
||||
<div v-if="whitelistTip" class="verify-white-tips">{{ whitelistTip }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="verify-white-body">
|
||||
<el-input 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>
|
||||
</el-dialog>
|
||||
v-model="whiteVisible"
|
||||
title="验证"
|
||||
:show-close="false"
|
||||
class="verify-white-wrap"
|
||||
width="315"
|
||||
:close-on-press-escape="false"
|
||||
:close-on-click-modal="false"
|
||||
align-center
|
||||
>
|
||||
<template #header>
|
||||
<div class="verify-white-head">
|
||||
<div class="verify-white-title">验证</div>
|
||||
<div v-if="whitelistTip" class="verify-white-tips">{{ whitelistTip }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="verify-white-body">
|
||||
<el-input
|
||||
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>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref,reactive,computed,watch} from 'vue'
|
||||
import { validate } from '../api/survey'
|
||||
import { useStore } from 'vuex'
|
||||
import { ref, reactive, computed, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import 'element-plus/theme-chalk/src/message.scss'
|
||||
|
||||
import { validate } from '../api/survey'
|
||||
import { useSurveyStore } from '../stores/survey'
|
||||
|
||||
const whiteVisible = ref(false)
|
||||
|
||||
|
||||
const store = useStore()
|
||||
const surveyStore = useSurveyStore()
|
||||
const state = reactive({
|
||||
password: '',
|
||||
value: '',
|
||||
is_submit:false
|
||||
password: '',
|
||||
value: '',
|
||||
is_submit: false
|
||||
})
|
||||
|
||||
const baseConf = computed(() => store.state.baseConf || {})
|
||||
@ -48,91 +57,91 @@ const whitelistTip = computed(() => baseConf.value.whitelistTip)
|
||||
const surveyPath = computed(() => store.state?.surveyPath || '')
|
||||
|
||||
const isValue = computed(() => {
|
||||
if(!whitelistType.value) return false
|
||||
return whitelistType.value!='ALL'
|
||||
if (!whitelistType.value) return false
|
||||
return whitelistType.value != 'ALL'
|
||||
})
|
||||
|
||||
const placeholder = computed(() => {
|
||||
if (whitelistType.value == 'MEMBER') {
|
||||
return '请输入用户名'
|
||||
}
|
||||
if(memberType.value == 'MOBILE'){
|
||||
return '请输入手机号'
|
||||
}
|
||||
if(memberType.value == 'EMAIL'){
|
||||
return '请输入邮箱'
|
||||
}
|
||||
return ''
|
||||
if (whitelistType.value == 'MEMBER') {
|
||||
return '请输入用户名'
|
||||
}
|
||||
if (memberType.value == 'MOBILE') {
|
||||
return '请输入手机号'
|
||||
}
|
||||
if (memberType.value == 'EMAIL') {
|
||||
return '请输入邮箱'
|
||||
}
|
||||
return ''
|
||||
})
|
||||
|
||||
const handleSubmit = async() => {
|
||||
if (state.is_submit) return;
|
||||
const params = {
|
||||
surveyPath:surveyPath.value
|
||||
}
|
||||
if (isValue.value) {
|
||||
params.whitelist = state.value
|
||||
}
|
||||
if(isPwd.value){
|
||||
params.password = state.password
|
||||
}
|
||||
const res = await validate(params)
|
||||
if (res.code != 200) {
|
||||
ElMessage.error(res.errmsg || '验证失败')
|
||||
return
|
||||
}
|
||||
whiteVisible.value = false
|
||||
store.commit('setWhiteData',params)
|
||||
const handleSubmit = async () => {
|
||||
if (state.is_submit) return
|
||||
const params = {
|
||||
surveyPath: surveyPath.value
|
||||
}
|
||||
if (isValue.value) {
|
||||
params.whitelist = state.value
|
||||
}
|
||||
if (isPwd.value) {
|
||||
params.password = state.password
|
||||
}
|
||||
const res = await validate(params)
|
||||
if (res.code != 200) {
|
||||
ElMessage.error(res.errmsg || '验证失败')
|
||||
return
|
||||
}
|
||||
whiteVisible.value = false
|
||||
surveyStore.setWhiteData(params)
|
||||
}
|
||||
|
||||
watch(()=>baseConf.value, () => {
|
||||
if (whiteVisible.value) return
|
||||
if(isValue.value || isPwd.value){
|
||||
whiteVisible.value = true;
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
watch(
|
||||
() => baseConf.value,
|
||||
() => {
|
||||
if (whiteVisible.value) return
|
||||
if (isValue.value || isPwd.value) {
|
||||
whiteVisible.value = true
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.verify-white-wrap{
|
||||
.verify-white-body{
|
||||
padding:0 14px
|
||||
}
|
||||
.verify-white-head{
|
||||
padding:0 14px;
|
||||
margin-bottom: 8px;
|
||||
margin-top:2px;
|
||||
}
|
||||
.mb16{
|
||||
margin-bottom:16px;
|
||||
}
|
||||
.verify-white-tips{
|
||||
text-align: center;
|
||||
margin-top:8px;
|
||||
font-size: 14px;
|
||||
color: #92949D;
|
||||
}
|
||||
.verify-white-title{
|
||||
font-size: 16px;
|
||||
color: #292A36;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
.submit-btn{
|
||||
background: #FAA600;
|
||||
border-radius: 2px;
|
||||
width:255px;
|
||||
height:32px;
|
||||
color:#fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top:4px;
|
||||
margin-bottom:14px;
|
||||
}
|
||||
.verify-white-wrap {
|
||||
.verify-white-body {
|
||||
padding: 0 14px;
|
||||
}
|
||||
.verify-white-head {
|
||||
padding: 0 14px;
|
||||
margin-bottom: 8px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.mb16 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.verify-white-tips {
|
||||
text-align: center;
|
||||
margin-top: 8px;
|
||||
font-size: 14px;
|
||||
color: #92949d;
|
||||
}
|
||||
.verify-white-title {
|
||||
font-size: 16px;
|
||||
color: #292a36;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.submit-btn {
|
||||
background: #faa600;
|
||||
border-radius: 2px;
|
||||
width: 255px;
|
||||
height: 32px;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import store from '../store/index'
|
||||
import { useSurveyStore } from '../stores/survey'
|
||||
import { computed } from 'vue'
|
||||
export const useProgressBar = () => {
|
||||
const surveyStore = useSurveyStore()
|
||||
const isVariableEmpty = (variable) => {
|
||||
if (variable === undefined || variable === null) {
|
||||
return true
|
||||
@ -22,7 +23,7 @@ export const useProgressBar = () => {
|
||||
fillCount: 0,
|
||||
topicCount: 0
|
||||
}
|
||||
const formValues = store.state.formValues
|
||||
const formValues = surveyStore.formValues
|
||||
for (let key in formValues) {
|
||||
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) => {
|
||||
const formValues = store.state.formValues
|
||||
const questionStore = useQuestionStore()
|
||||
const surveyStore = useSurveyStore()
|
||||
const formValues = surveyStore.formValues
|
||||
const questionVal = formValues[questionKey]
|
||||
let rangeConfig = store.state.questionData[questionKey].rangeConfig
|
||||
let rangeConfig = questionStore.questionData[questionKey].rangeConfig
|
||||
let othersValue = {}
|
||||
if (rangeConfig && Object.keys(rangeConfig).length > 0) {
|
||||
for (let key in rangeConfig) {
|
||||
@ -18,7 +22,8 @@ export const useShowInput = (questionKey) => {
|
||||
key: rangeKey,
|
||||
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) => {
|
||||
const formValues = store.state.formValues
|
||||
const questionStore = useQuestionStore()
|
||||
const surveyStore = useSurveyStore()
|
||||
const formValues = surveyStore.formValues
|
||||
const questionVal = formValues[questionKey]
|
||||
let othersValue = {}
|
||||
let options = store.state.questionData[questionKey].options.map((optionItem) => {
|
||||
let options = questionStore.questionData[questionKey].options.map((optionItem) => {
|
||||
if (optionItem.others) {
|
||||
const opKey = `${questionKey}_${optionItem.hash}`
|
||||
othersValue[opKey] = formValues[opKey]
|
||||
@ -13,7 +17,7 @@ export const useShowOthers = (questionKey) => {
|
||||
key: opKey,
|
||||
value: ''
|
||||
}
|
||||
store.commit('changeFormData', data)
|
||||
surveyStore.changeData(data)
|
||||
}
|
||||
return {
|
||||
...optionItem,
|
||||
|
@ -1,10 +1,12 @@
|
||||
import store from '../store/index'
|
||||
export const useVoteMap = (questionKey) => {
|
||||
let voteTotal = store.state.voteMap?.[questionKey]?.total || 0
|
||||
import { useQuestionStore } from '../stores/question'
|
||||
|
||||
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 voteCount = store.state.voteMap?.[questionKey]?.[optionHash] || 0
|
||||
const voteCount = questionStore.voteMap?.[questionKey]?.[optionHash] || 0
|
||||
|
||||
return {
|
||||
...option,
|
||||
|
@ -2,15 +2,16 @@ import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import EventBus from './utils/eventbus'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
const app = createApp(App)
|
||||
const pinia = createPinia()
|
||||
|
||||
const $bus = new EventBus()
|
||||
app.provide('$bus', $bus)
|
||||
// 挂载到this上
|
||||
app.config.globalProperties.$bus = $bus
|
||||
app.use(pinia)
|
||||
app.use(router)
|
||||
app.use(store)
|
||||
|
||||
app.mount('#app')
|
||||
|
@ -2,35 +2,41 @@
|
||||
<div class="result-page-wrap">
|
||||
<div class="result-page">
|
||||
<div class="page-content">
|
||||
<img class="img" :src="errorImageUrl" />
|
||||
<img class="img" :src="errorImage" />
|
||||
<div class="msg" v-html="errorMsg"></div>
|
||||
</div>
|
||||
<LogoIcon :logo-conf="logoConf" :readonly="true" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
// @ts-ignore
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
import communalLoader from '@materials/communals/communalLoader.js'
|
||||
import { useErrorInfo } from '../stores/errorInfo'
|
||||
import { useSurveyStore } from '../stores/survey'
|
||||
|
||||
const LogoIcon = communalLoader.loadComponent('LogoIcon')
|
||||
|
||||
const store = useStore()
|
||||
const surveyStore = useSurveyStore()
|
||||
const errorStore = useErrorInfo()
|
||||
const { errorInfo } = storeToRefs(errorStore)
|
||||
const imageMap = {
|
||||
overTime: '/imgs/icons/overtime.webp',
|
||||
default: '/imgs/icons/error.webp'
|
||||
}
|
||||
|
||||
const errorImageUrl = computed(() => {
|
||||
const errorType = store.state?.errorInfo?.errorType
|
||||
const imageMap = {
|
||||
overTime: '/imgs/icons/overtime.webp',
|
||||
default: '/imgs/icons/error.webp'
|
||||
}
|
||||
const errorImage = computed(() => {
|
||||
const errorType = errorInfo.value.errorType
|
||||
|
||||
return imageMap[errorType as 'overTime'] || imageMap.default
|
||||
return imageMap[errorType] || imageMap.default
|
||||
})
|
||||
|
||||
const errorMsg = computed(() => store.state?.errorInfo?.errorMsg || '提交失败')
|
||||
const logoConf = computed(() => store.state?.bottomConf || {})
|
||||
const errorMsg = computed(() => {
|
||||
return errorInfo.value.errorMsg || '提交失败'
|
||||
})
|
||||
const logoConf = computed(() => surveyStore.bottomConf || {})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.result-page-wrap {
|
||||
|
@ -3,17 +3,16 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { getPublishedSurveyInfo, getPreviewSchema } from '../api/survey'
|
||||
import useCommandComponent from '../hooks/useCommandComponent'
|
||||
import { useSurveyStore } from '../stores/survey'
|
||||
|
||||
import AlertDialog from '../components/AlertDialog.vue'
|
||||
import { initRuleEngine } from '@/render/hooks/useRuleEngine.js'
|
||||
|
||||
const store = useStore()
|
||||
const route = useRoute()
|
||||
const surveyStore = useSurveyStore()
|
||||
const loadData = (res: any, surveyPath: string) => {
|
||||
if (res.code === 200) {
|
||||
const data = res.data
|
||||
@ -30,8 +29,8 @@ const loadData = (res: any, surveyPath: string) => {
|
||||
|
||||
document.title = data.title
|
||||
|
||||
store.commit('setSurveyPath', surveyPath)
|
||||
store.dispatch('init', questionData)
|
||||
surveyStore.setSurveyPath(surveyPath)
|
||||
surveyStore.initSurvey(questionData)
|
||||
initRuleEngine(logicConf?.showLogicConf)
|
||||
} else {
|
||||
throw new Error(res.errmsg)
|
||||
@ -40,7 +39,7 @@ const loadData = (res: any, surveyPath: string) => {
|
||||
onMounted(() => {
|
||||
const surveyId = route.params.surveyId
|
||||
console.log({ surveyId })
|
||||
store.commit('setSurveyPath', surveyId)
|
||||
surveyStore.setSurveyPath(surveyId)
|
||||
getDetail(surveyId as string)
|
||||
})
|
||||
|
||||
@ -54,7 +53,7 @@ const getDetail = async (surveyPath: string) => {
|
||||
} else {
|
||||
const res: any = await getPublishedSurveyInfo({ surveyPath })
|
||||
loadData(res, surveyPath)
|
||||
store.dispatch('getEncryptInfo')
|
||||
surveyStore.getEncryptInfo()
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.log(error)
|
||||
|
@ -20,7 +20,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useRouter } from 'vue-router'
|
||||
// @ts-ignore
|
||||
import communalLoader from '@materials/communals/communalLoader.js'
|
||||
@ -29,6 +29,8 @@ import AlertDialog from '../components/AlertDialog.vue'
|
||||
import ConfirmDialog from '../components/ConfirmDialog.vue'
|
||||
import ProgressBar from '../components/ProgressBar.vue'
|
||||
|
||||
import { useSurveyStore } from '../stores/survey'
|
||||
import { useQuestionStore } from '../stores/question'
|
||||
import { submitForm } from '../api/survey'
|
||||
import encrypt from '../utils/encrypt'
|
||||
|
||||
@ -55,15 +57,13 @@ const boxRef = ref<HTMLElement>()
|
||||
const alert = useCommandComponent(AlertDialog)
|
||||
const confirm = useCommandComponent(ConfirmDialog)
|
||||
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const surveyStore = useSurveyStore()
|
||||
const questionStore = useQuestionStore()
|
||||
|
||||
const bannerConf = computed(() => store.state?.bannerConf || {})
|
||||
const renderData = computed(() => store.getters.renderData)
|
||||
const submitConf = computed(() => store.state?.submitConf || {})
|
||||
const logoConf = computed(() => store.state?.bottomConf || {})
|
||||
const surveyPath = computed(() => store.state?.surveyPath || '')
|
||||
const whiteData = computed(() => store.state?.whiteData || {})
|
||||
const renderData = computed(() => questionStore.renderData)
|
||||
const { bannerConf, submitConf, bottomConf: logoConf, whiteData } = storeToRefs(surveyStore)
|
||||
const surveyPath = computed(() => surveyStore.surveyPath || '')
|
||||
|
||||
const validate = (cbk: (v: boolean) => void) => {
|
||||
const index = 0
|
||||
@ -71,9 +71,9 @@ const validate = (cbk: (v: boolean) => void) => {
|
||||
}
|
||||
|
||||
const normalizationRequestBody = () => {
|
||||
const enterTime = store.state.enterTime
|
||||
const encryptInfo = store.state.encryptInfo
|
||||
const formValues = store.state.formValues
|
||||
const enterTime = surveyStore.enterTime
|
||||
const encryptInfo = surveyStore.encryptInfo as any
|
||||
const formValues = surveyStore.formValues
|
||||
|
||||
const result: any = {
|
||||
surveyPath: surveyPath.value,
|
||||
@ -84,7 +84,7 @@ const normalizationRequestBody = () => {
|
||||
}
|
||||
|
||||
if (encryptInfo?.encryptType) {
|
||||
result.encryptType = encryptInfo?.encryptType
|
||||
result.encryptType = encryptInfo.encryptType
|
||||
result.data = encrypt[result.encryptType as 'rsa']({
|
||||
data: result.data,
|
||||
secretKey: encryptInfo?.data?.secretKey
|
||||
@ -121,7 +121,7 @@ const submitSurver = async () => {
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
const confirmAgain = store.state.submitConf.confirmAgain
|
||||
const confirmAgain = (surveyStore.submitConf as any).confirmAgain
|
||||
const { again_text, is_again } = confirmAgain
|
||||
|
||||
if (is_again) {
|
||||
|
@ -11,16 +11,16 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useSurveyStore } from '../stores/survey'
|
||||
// @ts-ignore
|
||||
import communalLoader from '@materials/communals/communalLoader.js'
|
||||
|
||||
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 msgContent = store.state?.submitConf?.msgContent || {}
|
||||
const msgContent = (surveyStore?.submitConf as any)?.msgContent || {}
|
||||
return msgContent?.msg_200 || '提交成功'
|
||||
})
|
||||
</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',
|
||||
'qrcode',
|
||||
'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: [
|
||||
|
Loading…
Reference in New Issue
Block a user