-
-
问卷列表
-
-
- 创建问卷
-
+
+
+
+
+
{{ spaceType === SpaceType.Group ? '团队空间' : '问卷' }}列表
+
+
+
+ 创建团队空间
+
+
+
+ 创建问卷
+
+
+
+
+
-
+
-
@@ -47,7 +161,8 @@ export default {
.question-list-root {
height: 100%;
background-color: #f6f7f9;
- .login-status {
+
+ .top-nav {
background: #fff;
color: #4a4c5b;
padding: 0 20px;
@@ -55,10 +170,25 @@ export default {
display: flex;
justify-content: space-between;
align-items: center;
- .logo-img {
- width: 90px;
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.04);
+ .left {
+ display: flex;
+ align-items: center;
+ width: calc(100% - 200px);
+ .logo-img {
+ width: 90px;
+ height: fit-content;
+ padding-right: 20px;
+ }
+ .el-menu {
+ width: 100%;
+ height: 56px;
+ border: none !important;
+ :deep(.el-menu-item, .is-active) {
+ border: none !important;
+ }
+ }
}
-
.login-info {
display: flex;
align-items: center;
@@ -78,28 +208,46 @@ export default {
color: #faa600;
}
}
-
- .list-content {
+ .content-wrap {
+ position: relative;
height: calc(100% - 56px);
- padding: 20px;
+ }
+ .list-content {
+ position: relative;
+ height: 100%;
+ width: 100%;
+ padding: 32px 32px 32px 232px;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ overflow: scroll;
.top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
+ .operation {
+ flex: 0 1 auto;
+ display: flex;
+ }
h2 {
font-size: 18px;
}
.create-btn {
+ background: #4a4c5b;
+ }
+ .space-btn {
+ background: $primary-color;
+ }
+ .btn {
width: 132px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
- background: #4a4c5b;
+
color: #fff;
.icon-chuangjian {
diff --git a/web/src/management/router/index.ts b/web/src/management/router/index.ts
index 919cb688..e6a2652e 100644
--- a/web/src/management/router/index.ts
+++ b/web/src/management/router/index.ts
@@ -1,6 +1,9 @@
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
import { useStore } from 'vuex'
+import { SurveyPermissions } from '@/management/utils/types/workSpace'
+import { ElMessage } from 'element-plus'
+import 'element-plus/theme-chalk/src/message.scss'
const routes: RouteRecordRaw[] = [
{
@@ -19,7 +22,8 @@ const routes: RouteRecordRaw[] = [
{
path: '/survey/:id/edit',
meta: {
- needLogin: true
+ needLogin: true,
+ premissions: [SurveyPermissions.SurveyManage]
},
name: 'QuestionEdit',
component: () => import('../pages/edit/index.vue'),
@@ -89,7 +93,8 @@ const routes: RouteRecordRaw[] = [
path: '/survey/:id/analysis',
name: 'analysisPage',
meta: {
- needLogin: true
+ needLogin: true,
+ premissions: [SurveyPermissions.DataManage]
},
component: () => import('../pages/analysis/AnalysisPage.vue')
},
@@ -97,7 +102,8 @@ const routes: RouteRecordRaw[] = [
path: '/survey/:id/publish',
name: 'publish',
meta: {
- needLogin: true
+ needLogin: true,
+ premissions: [SurveyPermissions.SurveyManage]
},
component: () => import('../pages/publish/PublishPage.vue')
},
@@ -125,7 +131,7 @@ const router = createRouter({
routes
})
-router.beforeEach((to, from, next) => {
+router.beforeEach(async (to, from, next) => {
const store = useStore()
if (!store.state.user?.initialized) {
store?.dispatch('user/init')
@@ -135,7 +141,24 @@ router.beforeEach((to, from, next) => {
}
if (to.meta.needLogin) {
if (store?.state?.user?.hasLogined) {
- next()
+ if (to.meta.premissions) {
+ const params = to.params
+ await store.dispatch('fetchCooperPermissions', params.id)
+ if (
+ (to.meta.premissions as []).some((permission) =>
+ store.state?.cooperPermissions?.includes(permission)
+ )
+ ) {
+ next()
+ } else {
+ ElMessage.warning('您没有该问卷的相关协作权限')
+ next({
+ name: 'survey'
+ })
+ }
+ } else {
+ next()
+ }
} else {
next({
name: 'login',
@@ -149,4 +172,17 @@ router.beforeEach((to, from, next) => {
}
})
+// router.afterEach(async (to, from) => {
+// const store = useStore()
+// if (to.meta.premissions) {
+// const params = to.params
+// await store.dispatch('fetchCooperPermissions', params.id)
+// if (!(to.meta.premissions as []).some((permission) => store.state?.cooperPermissions?.includes(permission))) {
+// ElMessage.warning('您没有该问卷的相关协作权限')
+// router.push({
+// name: 'survey'
+// })
+// }
+// }
+// })
export default router
diff --git a/web/src/management/store/actions.js b/web/src/management/store/actions.js
index 91071b4c..7652fb26 100644
--- a/web/src/management/store/actions.js
+++ b/web/src/management/store/actions.js
@@ -1,4 +1,6 @@
import { getBannerData } from '@/management/api/skin.js'
+import { getCollaboratorPermissions } from '@/management/api/space.ts'
+import { CODE_MAP } from '../api/base'
export default {
async getBannerData({ state, commit }) {
@@ -9,5 +11,12 @@ export default {
if (res.code === 200) {
commit('setBannerList', res.data)
}
+ },
+ async fetchCooperPermissions({ commit }, id) {
+ const res = await getCollaboratorPermissions(id)
+ console.log(res.data)
+ if (res.code === CODE_MAP.SUCCESS) {
+ commit('setCooperPermissions', res.data.permissions)
+ }
}
}
diff --git a/web/src/management/store/index.js b/web/src/management/store/index.js
index 69d22b47..c0ca999b 100644
--- a/web/src/management/store/index.js
+++ b/web/src/management/store/index.js
@@ -1,7 +1,7 @@
import { createStore } from 'vuex'
import edit from './edit'
import user from './user'
-
+import list from './list'
import actions from './actions'
import mutations from './mutations'
import state from './state'
@@ -13,6 +13,7 @@ export default createStore({
actions,
modules: {
edit,
- user
+ user,
+ list
}
})
diff --git a/web/src/management/store/list/index.js b/web/src/management/store/list/index.js
new file mode 100644
index 00000000..e347bebd
--- /dev/null
+++ b/web/src/management/store/list/index.js
@@ -0,0 +1,258 @@
+import {
+ createSpace,
+ getSpaceList,
+ getSpaceDetail,
+ updateSpace,
+ deleteSpace
+} from '@/management/api/space'
+import { CODE_MAP } from '@/management/api/base'
+import { ElMessage } from 'element-plus'
+import 'element-plus/theme-chalk/src/message.scss'
+import { getSurveyList as surveyList } from '@/management/api/survey'
+import { set } from 'lodash-es'
+import { SpaceType } from '@/management/utils/types/workSpace'
+
+export default {
+ namespaced: true,
+ state: {
+ // 空间管理
+ spaceMenus: [
+ {
+ icon: 'icon-wodekongjian',
+ name: '我的空间',
+ id: SpaceType.Personal
+ },
+ {
+ icon: 'icon-tuanduikongjian',
+ name: '团队空间',
+ id: SpaceType.Group,
+ children: [
+ // {
+ // name: '小桔问卷调研团队',
+ // id: 'xxxx',
+ // }
+ ]
+ }
+ ],
+ spaceType: SpaceType.Personal,
+ workSpaceId: '',
+ spaceDetail: null,
+ teamSpaceList: [],
+ // 列表管理
+ surveyList: [],
+ surveyTotal: 0,
+ searchVal: '',
+ selectValueMap: {
+ surveyType: '',
+ 'curStatus.status': ''
+ },
+ buttonValueMap: {
+ 'curStatus.date': '',
+ createDate: -1
+ }
+ },
+ getters: {
+ listFliter(state) {
+ return [
+ {
+ comparator: '',
+ condition: [
+ {
+ field: 'title',
+ value: state.searchVal,
+ comparator: '$regex'
+ }
+ ]
+ },
+ {
+ comparator: '',
+ condition: [
+ {
+ field: 'curStatus.status',
+ value: state.selectValueMap['curStatus.status']
+ }
+ ]
+ },
+ {
+ comparator: '',
+ condition: [
+ {
+ field: 'surveyType',
+ value: state.selectValueMap.surveyType
+ }
+ ]
+ }
+ ]
+ },
+ listOrder(state) {
+ const { buttonValueMap } = state
+ return Object.entries(buttonValueMap)
+ .filter(([, effectValue]) => effectValue)
+ .reduce((prev, item) => {
+ const [effectKey, effectValue] = item
+ prev.push({ field: effectKey, value: effectValue })
+ return prev
+ }, [])
+ }
+ },
+ mutations: {
+ updateSpaceMenus(state, teamSpace) {
+ // 更新空间列表下的团队空间
+ set(state, 'spaceMenus[1].children', teamSpace)
+ },
+ changeSpaceType(state, spaceType) {
+ state.spaceType = spaceType
+ },
+ changeWorkSpace(state, workSpaceId) {
+ // 切换空间清除筛选条件
+ this.commit('list/reserSelectValueMap')
+ this.commit('list/reserButtonValueMap')
+ this.commit('list/setSearchVal', '')
+ state.workSpaceId = workSpaceId
+ },
+ setSpaceDetail(state, data) {
+ state.spaceDetail = data
+ },
+ setTeamSpaceList(state, data) {
+ state.teamSpaceList = data
+ },
+ setSurveyList(state, list) {
+ state.surveyList = list
+ },
+ setSurveyTotal(state, total) {
+ state.surveyTotal = total
+ },
+ setSearchVal(state, data) {
+ state.searchVal = data
+ },
+ reserSelectValueMap(state) {
+ state.selectValueMap = {
+ surveyType: '',
+ 'curStatus.status': ''
+ }
+ },
+ changeSelectValueMap(state, { key, value }) {
+ state.selectValueMap[key] = value
+ },
+ reserButtonValueMap(state) {
+ state.buttonValueMap = {
+ 'curStatus.date': '',
+ createDate: -1
+ }
+ },
+ changeButtonValueMap(state, { key, value }) {
+ state.buttonValueMap[key] = value
+ }
+ },
+ actions: {
+ async getSpaceList({ commit }) {
+ try {
+ const res = await getSpaceList()
+
+ if (res.code === CODE_MAP.SUCCESS) {
+ const { list } = res.data
+ const teamSpace = list.map((item) => {
+ return {
+ id: item._id,
+ name: item.name
+ }
+ })
+ commit('setTeamSpaceList', list)
+ commit('updateSpaceMenus', teamSpace)
+ } else {
+ ElMessage.error('getSpaceList' + res.errmsg)
+ }
+ } catch (err) {
+ ElMessage.error('getSpaceList' + err)
+ }
+ },
+ async addSpace({}, params) {
+ const res = await createSpace({
+ name: params.name,
+ description: params.description,
+ members: params.members
+ })
+
+ if (res.code === CODE_MAP.SUCCESS) {
+ ElMessage.success('添加成功')
+ } else {
+ ElMessage.error('createSpace code err' + res.errmsg)
+ }
+ },
+ async getSpaceDetail({ state, commit }, id) {
+ try {
+ const workspaceId = id || state.workSpaceId
+ const res = await getSpaceDetail(workspaceId)
+ if (res.code === CODE_MAP.SUCCESS) {
+ commit('setSpaceDetail', res.data)
+ } else {
+ ElMessage.error('getSpaceList' + res.errmsg)
+ }
+ } catch (err) {
+ ElMessage.error('getSpaceList' + err)
+ }
+ },
+ async updateSpace({}, params) {
+ const res = await updateSpace({
+ workspaceId: params._id,
+ name: params.name,
+ description: params.description,
+ members: params.members
+ })
+
+ if (res.code === CODE_MAP.SUCCESS) {
+ ElMessage.success('更新成功')
+ } else {
+ ElMessage.error(res.errmsg)
+ }
+ },
+ async deleteSpace({}, workspaceId) {
+ try {
+ const res = await deleteSpace(workspaceId)
+
+ if (res.code === CODE_MAP.SUCCESS) {
+ ElMessage.success('删除成功')
+ } else {
+ ElMessage.error(res.errmsg)
+ }
+ } catch (err) {
+ ElMessage.error(err)
+ }
+ },
+ async getSurveyList({ state, getters, commit }, payload) {
+ const filterString = JSON.stringify(
+ getters.listFliter.filter((item) => {
+ return item.condition[0].value
+ })
+ )
+ const orderString = JSON.stringify(getters.listOrder)
+ try {
+ let params = {
+ curPage: payload?.curPage || 1,
+ pageSize: payload?.pageSize || 10, // 默认一页10条
+ filter: filterString,
+ order: orderString,
+ workspaceId: state.workSpaceId
+ }
+ // if(payload?.order) {
+ // params.order = payload.order
+ // }
+ // if(payload.filter) {
+ // params.filter = payload.filter
+ // }
+ // if(payload?.workspaceId) {
+ // params.workspaceId = payload.workspaceId
+ // }
+ const res = await surveyList(params)
+ if (res.code === CODE_MAP.SUCCESS) {
+ commit('setSurveyList', res.data.data)
+ commit('setSurveyTotal', res.data.count)
+ } else {
+ ElMessage.error(res.errmsg)
+ }
+ } catch (error) {
+ ElMessage.error('getSurveyList status' + error)
+ }
+ }
+ }
+}
diff --git a/web/src/management/store/mutations.js b/web/src/management/store/mutations.js
index 4995fdc0..0bf45451 100644
--- a/web/src/management/store/mutations.js
+++ b/web/src/management/store/mutations.js
@@ -1,5 +1,8 @@
export default {
setBannerList(state, data) {
state.bannerList = data
+ },
+ setCooperPermissions(state, data) {
+ state.cooperPermissions = data
}
}
diff --git a/web/src/management/store/state.js b/web/src/management/store/state.js
index 54246623..8ef14c4d 100644
--- a/web/src/management/store/state.js
+++ b/web/src/management/store/state.js
@@ -1,3 +1,5 @@
+import { SurveyPermissions } from '@/management/utils/types/workSpace'
export default {
- bannerList: []
+ bannerList: [],
+ cooperPermissions: Object.values(SurveyPermissions)
}
diff --git a/web/src/management/styles/icon.scss b/web/src/management/styles/icon.scss
index dcef1b00..c1cae880 100644
--- a/web/src/management/styles/icon.scss
+++ b/web/src/management/styles/icon.scss
@@ -1,9 +1,9 @@
@font-face {
font-family: 'iconfont'; /* Project id 4263849 */
src:
- url('//at.alicdn.com/t/c/font_4263849_xndlbqcha3l.woff2?t=1711101684869') format('woff2'),
- url('//at.alicdn.com/t/c/font_4263849_xndlbqcha3l.woff?t=1711101684869') format('woff'),
- url('//at.alicdn.com/t/c/font_4263849_xndlbqcha3l.ttf?t=1711101684869') format('truetype');
+ url('//at.alicdn.com/t/c/font_4263849_xfsn9z31epc.woff2?t=1716556097756') format('woff2'),
+ url('//at.alicdn.com/t/c/font_4263849_xfsn9z31epc.woff?t=1716556097756') format('woff'),
+ url('//at.alicdn.com/t/c/font_4263849_xfsn9z31epc.ttf?t=1716556097756') format('truetype');
}
.iconfont {
@@ -131,3 +131,9 @@
.icon-NPSpingfen::before {
content: '\e6e7';
}
+.icon-wodekongjian::before {
+ content: '\e6ee';
+}
+.icon-tuanduikongjian::before {
+ content: '\e6ec';
+}
diff --git a/web/src/management/utils/constant.js b/web/src/management/utils/constant.js
index b3d7ab2c..f48115f0 100644
--- a/web/src/management/utils/constant.js
+++ b/web/src/management/utils/constant.js
@@ -1,8 +1,10 @@
// 问卷操作枚举
export const QOP_MAP = {
+ ADD: 'add',
COPY: 'copy',
EDIT: 'edit'
}
+
export const qAbleList = ['radio', 'checkbox', 'binary-choice', 'vote']
export const operatorOptions = [
{
diff --git a/web/src/management/utils/types/workSpace.ts b/web/src/management/utils/types/workSpace.ts
new file mode 100644
index 00000000..e6ca90d7
--- /dev/null
+++ b/web/src/management/utils/types/workSpace.ts
@@ -0,0 +1,59 @@
+export interface ListItem {
+ value: string
+ label: string
+}
+
+export interface MenuItem {
+ id: string
+ name: string
+ icon?: string
+ children?: MenuItem[]
+}
+
+export type IWorkspace = {
+ id?: string
+ name: string
+ description: string
+ members: IMember[]
+}
+export type IMember = {
+ userId: string
+ username: string
+ role: any
+ _id?: string
+}
+
+export enum SpaceType {
+ Personal = 'personal',
+ Group = 'group',
+ Teamwork = 'teamwork'
+}
+export enum UserRole {
+ Admin = 'admin',
+ Member = 'user'
+}
+
+// 定义角色标签映射对象
+export const roleLabels: Record
= {
+ [UserRole.Admin]: '管理员',
+ [UserRole.Member]: '成员'
+}
+
+export interface ICollaborator {
+ _id?: string
+ userId: string
+ username: string
+ permissions: Array
+}
+
+export enum SurveyPermissions {
+ SurveyManage = 'SURVEY_CONF_MANAGE',
+ DataManage = 'SURVEY_RESPONSE_MANAGE',
+ CollaboratorManage = 'SURVEY_COOPERATION_MANAGE'
+}
+// 定义协作者权限标签映射对象
+export const surveyPermissionsLabels: Record = {
+ [SurveyPermissions.SurveyManage]: '问卷管理',
+ [SurveyPermissions.DataManage]: '数据管理',
+ [SurveyPermissions.CollaboratorManage]: '协作管理'
+}
diff --git a/web/src/materials/communals/widgets/HeaderContent/Components/HeaderVideo.jsx b/web/src/materials/communals/widgets/HeaderContent/Components/HeaderVideo.jsx
index 98cfdc87..bbf90356 100644
--- a/web/src/materials/communals/widgets/HeaderContent/Components/HeaderVideo.jsx
+++ b/web/src/materials/communals/widgets/HeaderContent/Components/HeaderVideo.jsx
@@ -45,7 +45,7 @@ export default defineComponent({
return (