Merge branch 'feature/pinia'
This commit is contained in:
commit
0b53b78cda
@ -172,7 +172,6 @@ export class WorkspaceController {
|
||||
pre[id] = cur;
|
||||
return pre;
|
||||
}, {});
|
||||
|
||||
const surveyTotalList = await Promise.all(
|
||||
workspaceIdList.map((item) => {
|
||||
return this.surveyMetaService.countSurveyMetaByWorkspaceId({
|
||||
|
120
web/components.d.ts
vendored
120
web/components.d.ts
vendored
@ -7,67 +7,67 @@ export {}
|
||||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
ElButton: typeof import('element-plus/es')['ElButton']
|
||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
||||
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
|
||||
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
|
||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||
ElForm: typeof import('element-plus/es')['ElForm']
|
||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||
ElInput: typeof import('element-plus/es')['ElInput']
|
||||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||
ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
|
||||
ElOption: typeof import('element-plus/es')['ElOption']
|
||||
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
|
||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||
ElRow: typeof import('element-plus/es')['ElRow']
|
||||
ElSegmented: typeof import('element-plus/es')['ElSegmented']
|
||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||
ElSelectV2: typeof import('element-plus/es')['ElSelectV2']
|
||||
ElSlider: typeof import('element-plus/es')['ElSlider']
|
||||
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
||||
ElTable: typeof import('element-plus/es')['ElTable']
|
||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
||||
ElTabs: typeof import('element-plus/es')['ElTabs']
|
||||
ElTag: typeof import('element-plus/es')['ElTag']
|
||||
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
|
||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||
IEpBottom: typeof import('~icons/ep/bottom')['default']
|
||||
IEpCheck: typeof import('~icons/ep/check')['default']
|
||||
IEpCirclePlus: typeof import('~icons/ep/circle-plus')['default']
|
||||
IEpClose: typeof import('~icons/ep/close')['default']
|
||||
IEpConnection: typeof import('~icons/ep/connection')['default']
|
||||
IEpCopyDocument: typeof import('~icons/ep/copy-document')['default']
|
||||
IEpDelete: typeof import('~icons/ep/delete')['default']
|
||||
IEpIphone: typeof import('~icons/ep/iphone')['default']
|
||||
IEpLoading: typeof import('~icons/ep/loading')['default']
|
||||
IEpMinus: typeof import('~icons/ep/minus')['default']
|
||||
IEpMonitor: typeof import('~icons/ep/monitor')['default']
|
||||
IEpMore: typeof import('~icons/ep/more')['default']
|
||||
IEpPlus: typeof import('~icons/ep/plus')['default']
|
||||
IEpQuestionFilled: typeof import('~icons/ep/question-filled')['default']
|
||||
IEpRank: typeof import('~icons/ep/rank')['default']
|
||||
IEpRemove: typeof import('~icons/ep/remove')['default']
|
||||
IEpSearch: typeof import('~icons/ep/search')['default']
|
||||
IEpSort: typeof import('~icons/ep/sort')['default']
|
||||
IEpSortDown: typeof import('~icons/ep/sort-down')['default']
|
||||
IEpSortUp: typeof import('~icons/ep/sort-up')['default']
|
||||
IEpTop: typeof import('~icons/ep/top')['default']
|
||||
IEpView: typeof import('~icons/ep/view')['default']
|
||||
IEpWarningFilled: typeof import('~icons/ep/warning-filled')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
ElButton: (typeof import('element-plus/es'))['ElButton']
|
||||
ElCheckbox: (typeof import('element-plus/es'))['ElCheckbox']
|
||||
ElCollapse: (typeof import('element-plus/es'))['ElCollapse']
|
||||
ElCollapseItem: (typeof import('element-plus/es'))['ElCollapseItem']
|
||||
ElColorPicker: (typeof import('element-plus/es'))['ElColorPicker']
|
||||
ElConfigProvider: (typeof import('element-plus/es'))['ElConfigProvider']
|
||||
ElDatePicker: (typeof import('element-plus/es'))['ElDatePicker']
|
||||
ElDialog: (typeof import('element-plus/es'))['ElDialog']
|
||||
ElForm: (typeof import('element-plus/es'))['ElForm']
|
||||
ElFormItem: (typeof import('element-plus/es'))['ElFormItem']
|
||||
ElInput: (typeof import('element-plus/es'))['ElInput']
|
||||
ElInputNumber: (typeof import('element-plus/es'))['ElInputNumber']
|
||||
ElMenu: (typeof import('element-plus/es'))['ElMenu']
|
||||
ElMenuItem: (typeof import('element-plus/es'))['ElMenuItem']
|
||||
ElMenuItemGroup: (typeof import('element-plus/es'))['ElMenuItemGroup']
|
||||
ElOption: (typeof import('element-plus/es'))['ElOption']
|
||||
ElPagination: (typeof import('element-plus/es'))['ElPagination']
|
||||
ElPopover: (typeof import('element-plus/es'))['ElPopover']
|
||||
ElRadio: (typeof import('element-plus/es'))['ElRadio']
|
||||
ElRadioButton: (typeof import('element-plus/es'))['ElRadioButton']
|
||||
ElRadioGroup: (typeof import('element-plus/es'))['ElRadioGroup']
|
||||
ElRow: (typeof import('element-plus/es'))['ElRow']
|
||||
ElSegmented: (typeof import('element-plus/es'))['ElSegmented']
|
||||
ElSelect: (typeof import('element-plus/es'))['ElSelect']
|
||||
ElSelectV2: (typeof import('element-plus/es'))['ElSelectV2']
|
||||
ElSlider: (typeof import('element-plus/es'))['ElSlider']
|
||||
ElSwitch: (typeof import('element-plus/es'))['ElSwitch']
|
||||
ElTable: (typeof import('element-plus/es'))['ElTable']
|
||||
ElTableColumn: (typeof import('element-plus/es'))['ElTableColumn']
|
||||
ElTabPane: (typeof import('element-plus/es'))['ElTabPane']
|
||||
ElTabs: (typeof import('element-plus/es'))['ElTabs']
|
||||
ElTag: (typeof import('element-plus/es'))['ElTag']
|
||||
ElTimePicker: (typeof import('element-plus/es'))['ElTimePicker']
|
||||
ElTooltip: (typeof import('element-plus/es'))['ElTooltip']
|
||||
IEpBottom: (typeof import('~icons/ep/bottom'))['default']
|
||||
IEpCheck: (typeof import('~icons/ep/check'))['default']
|
||||
IEpCirclePlus: (typeof import('~icons/ep/circle-plus'))['default']
|
||||
IEpClose: (typeof import('~icons/ep/close'))['default']
|
||||
IEpConnection: (typeof import('~icons/ep/connection'))['default']
|
||||
IEpCopyDocument: (typeof import('~icons/ep/copy-document'))['default']
|
||||
IEpDelete: (typeof import('~icons/ep/delete'))['default']
|
||||
IEpIphone: (typeof import('~icons/ep/iphone'))['default']
|
||||
IEpLoading: (typeof import('~icons/ep/loading'))['default']
|
||||
IEpMinus: (typeof import('~icons/ep/minus'))['default']
|
||||
IEpMonitor: (typeof import('~icons/ep/monitor'))['default']
|
||||
IEpMore: (typeof import('~icons/ep/more'))['default']
|
||||
IEpPlus: (typeof import('~icons/ep/plus'))['default']
|
||||
IEpQuestionFilled: (typeof import('~icons/ep/question-filled'))['default']
|
||||
IEpRank: (typeof import('~icons/ep/rank'))['default']
|
||||
IEpRemove: (typeof import('~icons/ep/remove'))['default']
|
||||
IEpSearch: (typeof import('~icons/ep/search'))['default']
|
||||
IEpSort: (typeof import('~icons/ep/sort'))['default']
|
||||
IEpSortDown: (typeof import('~icons/ep/sort-down'))['default']
|
||||
IEpSortUp: (typeof import('~icons/ep/sort-up'))['default']
|
||||
IEpTop: (typeof import('~icons/ep/top'))['default']
|
||||
IEpView: (typeof import('~icons/ep/view'))['default']
|
||||
IEpWarningFilled: (typeof import('~icons/ep/warning-filled'))['default']
|
||||
RouterLink: (typeof import('vue-router'))['RouterLink']
|
||||
RouterView: (typeof import('vue-router'))['RouterView']
|
||||
}
|
||||
export interface ComponentCustomProperties {
|
||||
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
|
||||
vLoading: (typeof import('element-plus/es'))['ElLoadingDirective']
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
"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",
|
||||
|
@ -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 = {}
|
||||
|
@ -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)
|
||||
|
@ -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) => {
|
||||
|
@ -25,8 +25,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 BackPanel from '../modules/generalModule/BackPanel.vue'
|
||||
import TitlePanel from '../modules/generalModule/TitlePanel.vue'
|
||||
@ -37,16 +36,11 @@ 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 title = computed(() => (editStore.schema?.metaData as any)?.title || '')
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import url('@/management/styles/edit-btn.scss');
|
||||
.view-icon {
|
||||
font-size: 20px;
|
||||
height: 29px;
|
||||
line-height: 29px;
|
||||
}
|
||||
.nav {
|
||||
width: 100%;
|
||||
height: 56px;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -26,8 +26,9 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { get as _get } from 'lodash-es'
|
||||
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 +45,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 +82,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'
|
||||
@ -15,7 +15,8 @@ import { showLogicEngine } from '@/management/hooks/useShowLogicEngine'
|
||||
import buildData from './buildData'
|
||||
|
||||
const isPublishing = ref<boolean>(false)
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const { schema, changeSchema, getSchemaFromRemote } = editStore
|
||||
const router = useRouter()
|
||||
|
||||
const updateLogicConf = () => {
|
||||
@ -27,7 +28,7 @@ const updateLogicConf = () => {
|
||||
showLogicEngine.value.validateSchema()
|
||||
const showLogicConf = showLogicEngine.value.toJson()
|
||||
// 更新逻辑配置
|
||||
store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
||||
changeSchema({ key: 'logicConf', value: { showLogicConf } })
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +47,7 @@ const handlePublish = async () => {
|
||||
return
|
||||
}
|
||||
|
||||
const saveData = buildData(store.state.edit.schema)
|
||||
const saveData = buildData(schema)
|
||||
if (!saveData.surveyId) {
|
||||
isPublishing.value = false
|
||||
ElMessage.error('未获取到问卷id')
|
||||
@ -64,7 +65,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,8 +15,8 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, nextTick, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
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'
|
||||
|
||||
@ -36,10 +36,12 @@ const saveText = computed(
|
||||
})[autoSaveStatus.value]
|
||||
)
|
||||
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const { schemaUpdateTime } = storeToRefs(editStore)
|
||||
const { schema, changeSchema } = editStore
|
||||
|
||||
const saveData = async () => {
|
||||
const saveData = buildData(store.state.edit.schema)
|
||||
const saveData = buildData(schema)
|
||||
|
||||
if (!saveData.surveyId) {
|
||||
ElMessage.error('未获取到问卷id')
|
||||
@ -59,7 +61,7 @@ const updateLogicConf = () => {
|
||||
showLogicEngine.value.validateSchema()
|
||||
const showLogicConf = showLogicEngine.value.toJson()
|
||||
// 更新逻辑配置
|
||||
store.dispatch('edit/changeSchema', { key: 'logicConf', value: { showLogicConf } })
|
||||
changeSchema({ key: 'logicConf', value: { showLogicConf } })
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,7 +130,6 @@ const handleSave = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const schemaUpdateTime = computed(() => _get(store.state, 'edit.schemaUpdateTime'))
|
||||
watch(schemaUpdateTime, () => {
|
||||
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) => {
|
||||
|
@ -38,7 +38,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, onMounted, shallowRef } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { cloneDeep as _cloneDeep, isArray as _isArray, get as _get } from 'lodash-es'
|
||||
|
||||
import baseConfig from './config/baseConfig'
|
||||
@ -49,6 +49,9 @@ import setterLoader from '@/materials/setters/setterLoader'
|
||||
const formConfigList = ref<Array<any>>([])
|
||||
const components = shallowRef<any>({})
|
||||
const registerTypes = ref<any>({})
|
||||
const editStore = useEditStore()
|
||||
const { schema, changeSchema } = editStore
|
||||
|
||||
const setterList = computed(() => {
|
||||
const list = _cloneDeep(formConfigList.value)
|
||||
|
||||
@ -61,12 +64,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
|
||||
@ -78,9 +81,8 @@ const setterList = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
const store = useStore()
|
||||
const handleFormChange = (data: any) => {
|
||||
store.dispatch('edit/changeSchema', {
|
||||
changeSchema({
|
||||
key: data.key,
|
||||
value: data.value
|
||||
})
|
||||
|
@ -17,10 +17,12 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useStore } from 'vuex'
|
||||
import { useEditStore } from '@/management/stores/edit'
|
||||
import { EDIT_STATUS_MAP } from '../enum'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
const { currentEditStatus } = storeToRefs(editStore)
|
||||
const statusList = [
|
||||
{
|
||||
type: EDIT_STATUS_MAP.SUCCESS,
|
||||
@ -35,10 +37,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
|
||||
})
|
||||
|
@ -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>
|
||||
|
@ -13,20 +13,21 @@
|
||||
:readonly="false"
|
||||
:is-selected="currentEditOne === 'submit'"
|
||||
/>
|
||||
<LogoIcon
|
||||
:logo-conf="bottomConf"
|
||||
:readonly="false"
|
||||
:is-selected="currentEditOne === 'logo'"
|
||||
/>
|
||||
</div>
|
||||
<LogoIcon
|
||||
:logo-conf="bottomConf"
|
||||
:readonly="false"
|
||||
:is-selected="currentEditOne === 'logo'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</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/config/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/settingModule/skin/CatalogPanel.vue'
|
||||
import PreviewPanel from '../../modules/settingModule/skin/PreviewPanel.vue'
|
||||
import SetterPanel from '../../modules/settingModule/skin/SetterPanel.vue'
|
||||
|
||||
const store = useStore()
|
||||
const editStore = useEditStore()
|
||||
|
||||
onMounted(() => {
|
||||
store.dispatch('getBannerData')
|
||||
editStore.fetchBannerData()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@ -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,11 +243,8 @@ const order = computed(() => {
|
||||
}, [])
|
||||
return JSON.stringify(formatOrder)
|
||||
})
|
||||
const workSpaceId = computed(() => {
|
||||
return store.state.list.workSpaceId
|
||||
})
|
||||
|
||||
const onRefresh = async () => {
|
||||
const onReflush = async () => {
|
||||
const filterString = JSON.stringify(
|
||||
filter.value.filter((item) => {
|
||||
return item.condition[0].value
|
||||
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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,8 +168,8 @@ const handleDelete = (id: string) => {
|
||||
}
|
||||
)
|
||||
.then(async () => {
|
||||
await store.dispatch('list/deleteSpace', id)
|
||||
await store.dispatch('list/getSpaceList')
|
||||
await workSpaceStore.deleteSpace(id)
|
||||
await workSpaceStore.getSpaceList()
|
||||
curPage.value = 1
|
||||
})
|
||||
.catch(() => {})
|
||||
@ -184,9 +185,10 @@ const handleClick = (key: string, data: any) => {
|
||||
|
||||
const onCloseModify = () => {
|
||||
showSpaceModify.value = false
|
||||
store.dispatch('list/getSpaceList')
|
||||
workSpaceStore.getSpaceList()
|
||||
curPage.value = 1
|
||||
}
|
||||
|
||||
defineExpose({ onCloseModify })
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@ -44,17 +44,15 @@
|
||||
|
||||
<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 MemberSelect from '@/management/components/CooperModify/MemberSelect.vue'
|
||||
import { type IMember, type IWorkspace, UserRole } from '@/management/utils/types/workSpace'
|
||||
import { useWorkSpaceStore } from '@/management/stores/workSpace'
|
||||
|
||||
const store = useStore()
|
||||
const workSpaceStore = useWorkSpaceStore()
|
||||
const emit = defineEmits(['on-close-codify', 'onFocus', 'change', 'blur'])
|
||||
const props = defineProps({
|
||||
type: String,
|
||||
@ -66,7 +64,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 +87,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 +144,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('您没有该问卷的相关协作权限')
|
||||
|
372
web/src/management/stores/edit.ts
Normal file
372
web/src/management/stores/edit.ts
Normal file
@ -0,0 +1,372 @@
|
||||
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/config/setterConfig/submitConfig'
|
||||
|
||||
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
|
||||
}
|
||||
})
|
55
web/src/management/stores/user.ts
Normal file
55
web/src/management/stores/user.ts
Normal file
@ -0,0 +1,55 @@
|
||||
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 }
|
||||
})
|
||||
|
147
web/src/management/stores/workSpace.ts
Normal file
147
web/src/management/stores/workSpace.ts
Normal file
@ -0,0 +1,147 @@
|
||||
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 surveyListStore = useSurveyListStore()
|
||||
|
||||
async function getSpaceList() {
|
||||
try {
|
||||
const res: any = await getSpaceListReq()
|
||||
|
||||
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,
|
||||
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,7 +11,7 @@ export interface MenuItem {
|
||||
}
|
||||
|
||||
export type IWorkspace = {
|
||||
id?: string
|
||||
_id?: string
|
||||
name: string
|
||||
description: string
|
||||
members: IMember[]
|
||||
@ -23,6 +23,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',
|
||||
|
@ -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,8 @@ watch(
|
||||
key: field,
|
||||
value: value
|
||||
}
|
||||
store.commit('changeFormData', data)
|
||||
// store.commit('changeFormData', data)
|
||||
surveyStore.changeData(data)
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -105,7 +109,7 @@ const handleChange = (data) => {
|
||||
emit('change', data)
|
||||
// 处理投票题
|
||||
if (props.moduleConfig.type === QUESTION_TYPE.VOTE) {
|
||||
store.dispatch('updateVoteData', data)
|
||||
questionStore.updateVoteData(data)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -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,14 +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 renderData = computed(() => questionStore.renderData)
|
||||
const { bannerConf, submitConf, bottomConf: logoConf } = storeToRefs(surveyStore)
|
||||
const surveyPath = computed(() => surveyStore.surveyPath || '')
|
||||
|
||||
const validate = (cbk: (v: boolean) => void) => {
|
||||
const index = 0
|
||||
@ -70,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,
|
||||
@ -82,7 +83,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
|
||||
@ -119,7 +120,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>
|
||||
|
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
|
||||
}
|
||||
})
|
166
web/src/render/stores/survey.js
Normal file
166
web/src/render/stores/survey.js
Normal file
@ -0,0 +1,166 @@
|
||||
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 router = useRouter()
|
||||
const questionStore = useQuestionStore()
|
||||
const { setErrorInfo } = useErrorInfo()
|
||||
|
||||
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'])
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
// 获取已投票数据
|
||||
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,
|
||||
|
||||
initSurvey,
|
||||
changeData,
|
||||
setSurveyPath,
|
||||
setEnterTime,
|
||||
getEncryptInfo
|
||||
}
|
||||
})
|
22
web/src/render/styles/default.scss
Normal file
22
web/src/render/styles/default.scss
Normal file
@ -0,0 +1,22 @@
|
||||
$primary-color: #faa600;
|
||||
$primary-color-light: hsl(48, 100%, 97%);
|
||||
|
||||
$title-color-deep: #292a36;
|
||||
$title-color: #4a4c5b;
|
||||
$font-color: #6e707c;
|
||||
$remark-color: #4a4c5b;
|
||||
$placeholder-color: #c8c9cd;
|
||||
$light-focus-color: #666666;
|
||||
|
||||
$disable-color: #f2f4f7;
|
||||
$border-color: #dee2e6;
|
||||
|
||||
$spliter-color: #f7f7f7;
|
||||
|
||||
$error-color: #ec4e29;
|
||||
|
||||
@import './variable';
|
||||
|
||||
$title-size: 0.32rem;
|
||||
$font-size: 0.28rem;
|
||||
$tip-size: 0.22rem;
|
@ -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