提交 7f122024 authored 作者: lihuihui's avatar lihuihui

用户管理,角色管理,项目管理(未完成)开发

上级 6db3c1da
...@@ -29,3 +29,8 @@ export function uploadFile(data: Record<string, any>) { ...@@ -29,3 +29,8 @@ export function uploadFile(data: Record<string, any>) {
}) })
.then(() => data) .then(() => data)
} }
// 获取项目公共map
export function getProjectMap() {
return httpRequest.get('/api/zws/v1/backend/project/conditions')
}
\ No newline at end of file
import { getProjectMap } from '@/api/base'
// 赛项信息
interface ProjectType {
id: number
name: string
}
interface ProjectStatus {
id: number
name: string
}
const projectTypeMap = ref<ProjectType[]>([])
const projectStatusMap = ref<ProjectStatus[]>([])
export function useGetProjectMap() {
getProjectMap().then((res: any) => {
projectTypeMap.value = res.data.project_type_map.map((item: any) => {
item.id = item.id + ''
return item
})
projectStatusMap.value = res.data.project_status_map.map((item: any) => {
item.id = item.id + ''
return item
})
})
return { projectTypeMap, projectStatusMap }
}
<script setup lang="ts"></script> <script setup lang="ts">
const emit = defineEmits<{
(e: 'update:modelValue', visible: boolean): void
}>()
const options = [
{
value: 'Option1',
label: 'O1'
},
{
value: 'Option2',
label: 'Option2'
},
{
value: 'Option3',
label: 'Option3'
},
{
value: 'Option4',
label: 'Option4'
},
{
value: 'Option5',
label: 'Option5'
}
]
const formInline = reactive({
tag: ''
})
</script>
<template> <template>
<el-dialog title="选择标签" width="400px" :close-on-click-modal="false"></el-dialog> <el-dialog title="选择标签" width="400px" :close-on-click-modal="false">
<el-form style="display: block; width: 80%; margin: 0 auto" :model="formInline" class="demo-form-inline">
<el-form-item label="渠道标签">
<el-select style="width: 200px" v-model="formInline.tag" multiple placeholder="Select">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<!-- <el-form-item>
<el-button type="primary" @click="onSubmit">Query</el-button>
</el-form-item> -->
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="emit('update:modelValue', false)">取消</el-button>
<el-button type="primary"> 确定 </el-button>
</span>
</template>
</el-dialog>
</template> </template>
<script setup lang="ts"></script> <script setup lang="ts"></script>
<template> <template>
<el-dialog title="生成二维码"> <el-dialog title="生成二维码" width="400px">
<el-form> <el-form style="display:block;width: 80%; margin: 0 auto">
<el-form-item label="选择项目"> <el-form-item label="选择项目">
<el-select></el-select> <el-select></el-select>
</el-form-item> </el-form-item>
......
...@@ -13,9 +13,45 @@ const listOptions = $computed(() => { ...@@ -13,9 +13,45 @@ const listOptions = $computed(() => {
{ type: 'input', prop: 'code', placeholder: '渠道名称' }, { type: 'input', prop: 'code', placeholder: '渠道名称' },
{ type: 'input', prop: 'code', placeholder: '公司字号' }, { type: 'input', prop: 'code', placeholder: '公司字号' },
{ type: 'select', prop: 'code', placeholder: '渠道标签' }, { type: 'select', prop: 'code', placeholder: '渠道标签' },
{ type: 'select', prop: 'code', placeholder: '呼叫状态' }, {
{ type: 'select', prop: 'code', placeholder: '回抽状态' }, type: 'select',
{ type: 'select', prop: 'code', placeholder: '渠道质量' } prop: 'code',
placeholder: '咨询状态框',
options: [
{ value: '1', label: '隐藏' },
{ value: '2', label: '显示' }
]
},
{
type: 'select',
prop: 'code',
placeholder: '回抽状态',
options: [
{ value: '1', label: '开启' },
{ value: '2', label: '关闭' }
]
},
{
type: 'select',
prop: 'code',
placeholder: '分配状态',
options: [
{ value: '1', label: '开启' },
{ value: '2', label: '关闭' }
]
},
{
type: 'select',
prop: 'code',
placeholder: '渠道质量',
options: (function () {
const options = []
for (let i = 0; i < 11; i++) {
options.push({ value: i, label: i })
}
return options
})()
}
], ],
data: [ data: [
{ id: 1, code: 123 }, { id: 1, code: 123 },
......
import httpRequest from '@/utils/axios' import httpRequest from '@/utils/axios'
// 获取封面列表 // 获取列表
export function getCoverList(params?: { type?: string; page?: number; ['per-page']?: number }) { export function getProjectList(params?: { project_id?: string; project_type?: string; project_status?: string; title?: string; page?: number;['per-page']?: number }) {
return httpRequest.get('/api/resource/v1/backend/cover/list', { params }) return httpRequest.get('/api/zws/v1/backend/project/list', { params })
}
// 搜索用户
export function searchUser(params: { q: string; }) {
return httpRequest.get('/api/zws/v1/backend/common/search-user', { params })
}
// 获取角色
export function getProjectRoles() {
return httpRequest.get('/api/zws/v1/backend/common/project-roles')
}
// 创建项目
export function createProject(data?: { title?: string; alias?: string; project_type: string; project_status: string; project_uri?: string; landing_page_uri?: string; members: string }) {
return httpRequest.post('/api/zws/v1/backend/project/create', data)
}
// 详情
export function getProjectDetail(params?: { id?: string | string[] }) {
return httpRequest.get('/api/zws/v1/backend/project/view', { params })
}
// 获取成员列表
export function getProjectUserList(params?: { id?: string | string[] }) {
return httpRequest.get('/api/zws/v1/backend/project/member', { params })
}
// 更新项目
export function updateProject(data?: { id: string | string[]; title?: string; alias?: string; project_type: string; project_status: string; project_uri?: string; landing_page_uri?: string; }) {
return httpRequest.post('/api/zws/v1/backend/project/update', data)
} }
<script setup lang="ts">
import { searchUser, getProjectRoles } from '../api'
import { ElMessage } from 'element-plus'
const emit = defineEmits(['update:modelValue', 'changeUser'])
// 用户搜索
interface UserInfo {
id: string
nickname: string
mobile: string
}
let userValue = $ref('')
const loading = ref(false)
let userListOption = $ref<UserInfo[]>()
const remoteMethod = (q: string) => {
if (q) {
loading.value = true
searchUser({ q: q }).then((res: { data: UserInfo[] }) => {
loading.value = false
userListOption = res.data
})
}
}
// 获取角色
interface ProjectRole {
id: string
name: string
}
let roleValue = $ref([])
let projectRoleOption = $ref<ProjectRole[]>()
getProjectRoles().then((res: { data: ProjectRole[] }) => {
projectRoleOption = res.data
})
// 选择完成
const submit = function () {
if (Object.keys(roleValue).length && userValue) {
console.log(projectRoleOption, 'projectRoleOptionprojectRoleOption', roleValue)
const data = {
userInfo: userListOption.find(item => item.id === userValue),
role: projectRoleOption.reduce((a: any, b) => {
if (roleValue.find((item: any) => item === b.id)) {
a.push(b)
}
return a
}, [])
}
emit('changeUser', data)
emit('update:modelValue', false)
userValue = ''
roleValue = []
} else {
ElMessage('请选择')
}
}
</script>
<template>
<el-dialog title="添加项目成员" width="400px" :close-on-click-modal="false">
<el-form style="display: block; width: 80%; margin: 0 auto" class="demo-form-inline">
<el-form-item label="选择成员">
<el-select
v-model="userValue"
filterable
remote
reserve-keyword
placeholder="请输入"
:remote-method="remoteMethod"
:loading="loading"
>
<el-option
v-for="item in userListOption"
:key="item.id"
:label="item.mobile ? `${item.nickname}(${item.mobile}})` : item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="选择角色" v-show="userValue">
<el-select v-model="roleValue" multiple placeholder="请选择">
<el-option v-for="item in projectRoleOption" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="emit('update:modelValue', false)">取消</el-button>
<el-button type="primary" @click="submit"> 确定 </el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts"></script> <script setup lang="ts">
import { useGetProjectMap } from '@/composables/useGetProjectMap'
import type { FormRules } from 'element-plus'
import { getProjectDetail } from '../api'
const route = useRoute()
const { projectTypeMap, projectStatusMap } = useGetProjectMap()
const ruleFormRef = ref()
interface Props {
isAdd?: boolean
isUpdate?: boolean
isView?: boolean
}
const prop = defineProps<{ status?: Props }>()
interface ProjectInfoBase {
title: string
alias: string
project_type: string
project_status: string
project_uri: string
landing_page_uri: string
}
let form = reactive<ProjectInfoBase>({
title: '',
alias: '',
project_type: '',
project_status: '',
project_uri: '',
landing_page_uri: ''
})
onMounted(() => {
if (prop.status?.isView || prop.status?.isUpdate) {
getProjectDetail({ id: route.params.id }).then((res: { data: ProjectInfoBase }) => {
form = Object.assign(form, res.data)
})
}
})
const rules = reactive<FormRules>({
project_type: [{ required: true, message: '请选择类型' }],
project_status: [{ required: true, message: '请选择状态' }]
})
const submit = () => {
return ruleFormRef.value.validate()
}
defineExpose({
form,
submit
})
</script>
<template> <template>
<el-card shadow="never" header="基本信息"></el-card> <el-card shadow="never" header="基本信息">
<el-form ref="ruleFormRef" :disabled="status?.isView" :model="form" :rules="rules" label-width="140px">
<el-form-item label="项目名称">
<el-input v-model="form.title" />
</el-form-item>
<el-form-item label="项目别名">
<el-input v-model="form.alias" />
</el-form-item>
<el-form-item label="项目类型" prop="project_type">
<el-select v-model="form.project_type" placeholder="请选择">
<el-option v-for="item in projectTypeMap" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="project_status">
<el-select v-model="form.project_status" placeholder="请选择">
<el-option v-for="item in projectStatusMap" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="项目站首页(原项目页)">
<el-input v-model="form.project_uri" />
</el-form-item>
<el-form-item label="移动端落地页(原着陆页地址)">
<el-input v-model="form.landing_page_uri" />
</el-form-item>
</el-form>
</el-card>
</template> </template>
<script setup lang="ts"></script> <script setup lang="ts">
import AppList from '@/components/base/AppList.vue'
import { getProjectUserList } from '../api'
const AddMember = defineAsyncComponent(() => import('../components/AddMember.vue'))
const route = useRoute()
interface Props {
isAdd?: boolean
isUpdate?: boolean
isView?: boolean
}
const prop = defineProps<{ status?: Props }>()
interface User {
nickname: string
mobile: string
email: string
role: string[]
}
let userList = $ref<User[]>([])
const listOptions = $computed(() => {
return {
columns: [
{
label: '姓名',
prop: 'nickname',
computed(row: any) {
let name = ''
if (row.row?.name) {
name = row.row.name
} else {
name = row.row.nickname
}
return name
}
},
{ label: '手机号', prop: 'mobile' },
{ label: '邮箱', prop: 'email' },
{
label: '角色',
prop: 'role',
computed(row: any) {
if (row.row?.role_name) {
return row.row?.role_name
} else {
return row.row.role.reduce((a: any, b: any) => a.push(b.name) && a, []).toString()
}
}
},
{ label: '加入日期', prop: 'updated_time' },
{ label: '操作', prop: 'name', slots: 'table-x', width: 100 }
],
data: userList
}
})
const labelVisible = $ref(false)
// 选择人员
const changeUser = function (e: any) {
const info = Object.assign(e.userInfo, { role: e.role })
userList.push(info)
}
// 删除人员
const deleteUser = function (row: any) {
const index = userList.findIndex((item: any) => item.id === row.id)
userList.splice(index, 1)
}
// 新建时重构接口需要的数据
const data = function () {
if (!prop.status?.isUpdate) {
return JSON.stringify(
userList.reduce((a: any, b: any) => {
a.push({
user_id: b.id,
roles: b.role.reduce((roleA: any, roleB: any) => roleA.push(roleB.id) && roleA, []).toString()
})
return a
}, [])
)
}
}
// 详情
onMounted(() => {
if (prop.status?.isView || prop.status?.isUpdate) {
getProjectUserList({ id: route.params.id }).then((res: { data: { list: User[] } }) => {
userList = res.data.list
})
}
})
defineExpose({
data
})
</script>
<template> <template>
<el-card shadow="never" header="成员信息"></el-card> <el-card shadow="never" header="成员信息">
<AppList v-bind="listOptions" ref="appList">
<template #header-buttons>
<el-button type="primary" v-if="!prop.status?.isView" @click="labelVisible = true">添加成员</el-button>
</template>
<template #table-x="{ row }">
<el-button text type="primary" @click="deleteUser(row)" :disabled="prop.status?.isView">删除</el-button>
</template>
</AppList>
</el-card>
<AddMember v-model="labelVisible" @changeUser="changeUser"></AddMember>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import AppList from '@/components/base/AppList.vue' import AppList from '@/components/base/AppList.vue'
import { getProjectList } from '../api'
const AddMember = defineAsyncComponent(() => import('../components/AddMember.vue'))
const appList = $ref<InstanceType<typeof AppList> | null>(null) const appList = $ref<InstanceType<typeof AppList> | null>(null)
const listOptions = $computed(() => { const listOptions = $computed(() => {
return { return {
remote: {
httpRequest: getProjectList,
params: {
project_id: '',
project_type: '',
project_status: '',
title: ''
}
},
filters: [ filters: [
{ type: 'input', prop: 'code', placeholder: '项目编号' }, { type: 'input', prop: 'project_id', placeholder: '项目编号' },
{ type: 'input', prop: 'code', placeholder: '项目名称' }, { type: 'input', prop: 'title', placeholder: '项目名称' },
{ type: 'select', prop: 'code', placeholder: '项目类型' }, { type: 'input', prop: 'project_uri', placeholder: '项目页' },
{ type: 'select', prop: 'code', placeholder: '状态' } { type: 'select', prop: 'project_type_name', placeholder: '项目类型' },
], { type: 'select', prop: 'project_status_name', placeholder: '状态' },
data: [ { type: 'select', prop: 'updated_time', placeholder: '更新时间' }
{ id: 1, code: 123 },
{ id: 2, code: 456 }
] ]
} }
}) })
const columns = $computed(() => { const columns = $computed(() => {
const columns: Record<string, any>[] = [ const columns: Record<string, any>[] = [
{ label: '项目编号', prop: 'name' }, { label: '项目编号', prop: 'project_id' },
{ label: '项目名称', prop: 'name' }, { label: '项目名称', prop: 'title' },
{ label: '项目网址', prop: 'name' }, { label: '项目网址', prop: 'project_uri' },
{ label: '项目类型', prop: 'name' }, { label: '项目类型', prop: 'project_type_name' },
{ label: '状态', prop: 'name' }, { label: '状态', prop: 'project_status_name' },
{ label: '更新时间', prop: 'name' }, { label: '更新时间', prop: 'updated_time' },
{ label: '操作', prop: 'name', slots: 'table-x', width: 240 } { label: '操作', prop: 'name', slots: 'table-x', width: 240 }
] ]
if (selectionVisible) columns.unshift({ type: 'selection' }) if (selectionVisible) columns.unshift({ type: 'selection' })
...@@ -43,6 +53,8 @@ let multipleSelection = $ref([]) ...@@ -43,6 +53,8 @@ let multipleSelection = $ref([])
function handleSelectionChange(value: any) { function handleSelectionChange(value: any) {
multipleSelection = value multipleSelection = value
} }
const labelVisible = $ref(false)
</script> </script>
<template> <template>
...@@ -52,7 +64,9 @@ function handleSelectionChange(value: any) { ...@@ -52,7 +64,9 @@ function handleSelectionChange(value: any) {
<el-button type="primary"><router-link :to="{ name: 'projectCreate' }">创建项目</router-link></el-button> <el-button type="primary"><router-link :to="{ name: 'projectCreate' }">创建项目</router-link></el-button>
<el-button type="primary" @click="toggleSelection" v-if="!selectionVisible">添加成员</el-button> <el-button type="primary" @click="toggleSelection" v-if="!selectionVisible">添加成员</el-button>
<template v-else> <template v-else>
<el-button type="primary" :disabled="!multipleSelection.length">选择成员</el-button> <el-button type="primary" :disabled="!multipleSelection.length" @click="labelVisible = true"
>选择成员</el-button
>
<el-button type="primary" @click="toggleSelection">取消</el-button> <el-button type="primary" @click="toggleSelection">取消</el-button>
</template> </template>
</template> </template>
...@@ -67,5 +81,6 @@ function handleSelectionChange(value: any) { ...@@ -67,5 +81,6 @@ function handleSelectionChange(value: any) {
<el-button text style="--el-button-text-color: #d9001b">删除</el-button> <el-button text style="--el-button-text-color: #d9001b">删除</el-button>
</template> </template>
</AppList> </AppList>
<AddMember v-model="labelVisible"></AddMember>
</AppCard> </AppCard>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import InfoBase from '../components/InfoBase.vue' import InfoBase from '../components/InfoBase.vue'
import InfoUsers from '../components/InfoUsers.vue' import InfoUsers from '../components/InfoUsers.vue'
import { createProject, updateProject } from '../api'
const router = useRouter()
const route = useRoute()
interface Props { interface Props {
isAdd?: boolean isAdd?: boolean
...@@ -12,11 +16,42 @@ const props = defineProps<Props>() ...@@ -12,11 +16,42 @@ const props = defineProps<Props>()
const title = $computed(() => { const title = $computed(() => {
return (props.isAdd && '创建项目') || (props.isUpdate && '编辑项目') || (props.isView && '查看项目') || '' return (props.isAdd && '创建项目') || (props.isUpdate && '编辑项目') || (props.isView && '查看项目') || ''
}) })
interface InfoBaseFrom {
form: {
title: string
alias: string
project_type: string
project_status: string
project_uri: string
landing_page_uri: string
}
submit: any
}
const infoBase = $ref<InfoBaseFrom>()
const infoUsers = $ref<{ data: any }>()
const onSubmit = function () {
infoBase.submit().then(() => {
const params = Object.assign(infoBase.form, { members: infoUsers.data() })
if (props.isAdd) {
createProject(params).then((res: any) => {
router.go(-1)
})
} else {
updateProject(Object.assign(params, { id: route.params.id })).then((res: any) => {
router.go(-1)
})
}
})
}
</script> </script>
<template> <template>
<AppCard :title="title"> <AppCard :title="title">
<InfoBase style="margin: 20px 0"></InfoBase> <InfoBase :status="props" ref="infoBase" style="margin: 20px 0"></InfoBase>
<InfoUsers></InfoUsers> <InfoUsers :status="props" ref="infoUsers"></InfoUsers>
<el-button v-if="!props?.isView" @click="onSubmit" style="margin: 20px auto; display: block" type="primary"
>提交</el-button
>
</AppCard> </AppCard>
</template> </template>
import httpRequest from '@/utils/axios' import httpRequest from '@/utils/axios'
// 获取封面列表 // 获取角色列表
export function getCoverList(params?: { type?: string; page?: number; ['per-page']?: number }) { export function getManagementList(params?: { user_name?: string; mobile?: string; email?: string; role_name?: string; page?: number;['per-page']?: number }) {
return httpRequest.get('/api/resource/v1/backend/cover/list', { params }) return httpRequest.get('/api/zws/v1/backend/management/role/list', { params })
}
// 获取角色详情
export function getManagementDetail(params?: { role_id?: string; page?: number;['per-page']?: number }) {
return httpRequest.get('/api/zws/v1/backend/management/role/view', { params })
} }
<script setup lang="ts">
import type { Info } from '../types'
const emit = defineEmits<{
(e: 'update:modelValue', visible: boolean): void
}>()
const prop = defineProps<{
data: Info
}>()
</script>
<template>
<el-dialog class="dialogClass" title="用户信息" width="500px" :close-on-click-modal="false">
<div class="info">
<div class="item">
<div class="label">姓名:</div>
<div class="value">{{ prop.data.user_name }}</div>
</div>
<div class="item">
<div class="label">用户手机:</div>
<div class="value">{{ prop.data.mobile }}</div>
</div>
<div class="item">
<div class="label">用户邮箱:</div>
<div class="value">{{ prop.data.email }}</div>
</div>
<div class="item">
<div class="label">角色类型:</div>
<div class="value" v-if="Array.isArray(prop.data.levels)">
<el-tag class="ml-2" v-for="(item, index) in prop.data.levels" :key="index">{{ item }}</el-tag>
</div>
<div class="value" v-else>{{ prop.data.levels }}</div>
</div>
<div class="item">
<div class="label">角色名称:</div>
<div class="value">
<el-tag>{{ prop.data.name }}</el-tag>
</div>
</div>
<div class="item">
<div class="label">应用项目:</div>
<div class="value" v-if="Array.isArray(prop.data.projects)">
<el-tag class="ml-2" v-for="(item, index) in prop.data.projects" :key="index">{{ item }}</el-tag>
</div>
<div class="value" v-else>{{ prop.data.projects }}</div>
</div>
<div class="item">
<div class="label">应用渠道:</div>
<div class="value" v-if="Array.isArray(prop.data.channels)">
<el-tag class="ml-2" v-for="(item, index) in prop.data.channels" :key="index">{{ item }}</el-tag>
</div>
<div class="value" v-else>{{ prop.data.channels }}</div>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="emit('update:modelValue', false)">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
<style lang="scss">
.dialogClass {
.el-dialog__body {
padding: 10px 20px 20px;
}
.info {
.item {
display: flex;
.label {
width: 110px;
display: inline-flex;
justify-content: flex-end;
align-items: flex-start;
flex: 0 0 auto;
font-size: 14px;
color: #969696;
height: 32px;
line-height: 32px;
box-sizing: border-box;
text-align: right;
}
.value {
font-size: 14px;
line-height: 32px;
.el-tag {
margin-top: 5px;
}
.ml-2 {
margin-right: 10px;
}
}
}
}
}
</style>
...@@ -5,6 +5,9 @@ export const routes: Array<RouteRecordRaw> = [ ...@@ -5,6 +5,9 @@ export const routes: Array<RouteRecordRaw> = [
{ {
path: '/base/roles', path: '/base/roles',
component: AppLayout, component: AppLayout,
children: [{ path: '', component: () => import('./views/Index.vue') }] children: [
{ path: '', component: () => import('./views/Index.vue') },
{ path: 'detail/:id', component: () => import('./views/Details.vue') }
]
} }
] ]
export interface Info {
user_name: string
mobile: string
email: string
name: string
levels: string | string[]
projects: string | string[]
channels: string | string[]
}
\ No newline at end of file
<script setup lang="ts">
import AppList from '@/components/base/AppList.vue'
import { getManagementDetail } from '../api'
import type { Info } from '../types'
const route = useRoute()
const UserInfo = defineAsyncComponent(() => import('../components/UserInfo.vue'))
const appList = $ref<InstanceType<typeof AppList> | null>(null)
let userInfoData: any = $ref()
const listOptions = $computed(() => {
return {
remote: {
httpRequest: getManagementDetail,
params: {
role_id: route.params.id
},
callback: (res: any) => {
userInfoData = res
return { list: res.members }
}
},
columns: [
{ label: '姓名', prop: 'user_name' },
{ label: '手机号', prop: 'mobile' },
{ label: '邮箱', prop: 'email' },
{ label: '加入日期', prop: 'join_time' },
{ label: '操作', slots: 'table-x', width: 100 }
]
}
})
// 查看
let labelVisible = $ref(false)
const currentRow = ref<Info>()
function handleView(row: Info) {
row.name = userInfoData.name
row.levels = userInfoData.levels
currentRow.value = row
labelVisible = true
}
</script>
<template>
<AppCard title="用户信息">
<AppList v-bind="listOptions" ref="appList">
<template #table-x="{ row }: { row: Info }">
<el-button text type="primary" @click="handleView(row)">查看详情</el-button>
</template>
</AppList>
<UserInfo v-if="labelVisible && currentRow" v-model="labelVisible" :data="currentRow"></UserInfo>
</AppCard>
</template>
<script setup lang="ts"> <script setup lang="ts">
import AppList from '@/components/base/AppList.vue' import AppList from '@/components/base/AppList.vue'
import { getManagementList } from '../api'
const router = useRouter()
const appList = $ref<InstanceType<typeof AppList> | null>(null) const appList = $ref<InstanceType<typeof AppList> | null>(null)
const listOptions = $computed(() => { const listOptions = $computed(() => {
return { return {
remote: {
httpRequest: getManagementList,
params: {
user_name: '',
mobile: '',
email: '',
role_name: ''
}
},
filters: [ filters: [
{ type: 'input', prop: 'code', placeholder: '请输入用户姓名' }, { type: 'input', prop: 'user_name', placeholder: '请输入用户姓名' },
{ type: 'input', prop: 'code', placeholder: '请输入用户手机号' }, { type: 'input', prop: 'mobile', placeholder: '请输入用户手机号' },
{ type: 'input', prop: 'code', placeholder: '请输入角色名称' } { type: 'input', prop: 'email', placeholder: '请输入角色邮箱' },
{ type: 'input', prop: 'role_name', placeholder: '请输入角色名称' }
], ],
columns: [ columns: [
{ label: '名称', prop: 'name' }, { label: '名称', prop: 'name' },
{ label: '描述', prop: 'name' }, { label: '描述', prop: 'desc' },
{ label: '用户数量', prop: 'name' }, { label: '包含用户数量', prop: 'user_count' },
{ label: '角色类型', prop: 'name' }, { label: '角色类型', prop: 'levels' },
{ label: '更新时间', prop: 'name' }, { label: '更新时间', prop: 'updated_at' },
{ label: '操作', prop: 'name', slots: 'table-x', width: 100 } { label: '操作', prop: 'name', slots: 'table-x', width: 100 }
], ],
data: [ data: [
...@@ -26,9 +39,10 @@ const listOptions = $computed(() => { ...@@ -26,9 +39,10 @@ const listOptions = $computed(() => {
}) })
// 查看 // 查看
let currentRow = $ref()
function handleView(row: any) { function handleView(row: any) {
currentRow = row router.push({
path: `/base/roles/detail/${row.id}`
})
} }
</script> </script>
...@@ -36,7 +50,7 @@ function handleView(row: any) { ...@@ -36,7 +50,7 @@ function handleView(row: any) {
<AppCard title="角色管理"> <AppCard title="角色管理">
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<template #table-x="{ row }"> <template #table-x="{ row }">
<el-button text type="primary" @click="handleView(row)">查看</el-button> <el-button text type="primary" @click="handleView(row)">查看成员</el-button>
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
......
import httpRequest from '@/utils/axios' import httpRequest from '@/utils/axios'
// 获取封面列表 // 获取列表
export function getCoverList(params?: { type?: string; page?: number; ['per-page']?: number }) { export function getMemberList(params?: { user_name?: string; mobile?: string; email?: string; role_name?: string; page?: number;['per-page']?: number }) {
return httpRequest.get('/api/resource/v1/backend/cover/list', { params }) return httpRequest.get('/api/zws/v1/backend/management/member/list', { params })
}
// 获取角色详情
export function getMemberDetail(params?: { user_id?: string; page?: number;['per-page']?: number }) {
return httpRequest.get('/api/zws/v1/backend/management/member/view', { params })
} }
\ No newline at end of file
<script setup lang="ts">
import { getMemberDetail } from '../api'
const emit = defineEmits<{
(e: 'update:modelValue', visible: boolean): void
}>()
const prop = defineProps({
id: String
})
interface Channels {
channel_id: string
title: string
roles: string[]
}
interface Info {
user_id: string
user_name: string
mobile: string
email: string
projects: [
{
title: string
project_id: string
roles: string[]
channels: Channels[]
}
]
}
let userInfo = $ref<Info>()
getMemberDetail({ user_id: prop.id }).then((res: any) => {
userInfo = res.data
console.log(userInfo, 'userInfouserInfo')
})
const projectValue = $ref()
const channelValue = $ref()
let projectRole = $ref<string[]>()
let channelRole = $ref<string[]>()
let channelsOption = $ref<Channels[]>()
// 项目渠道联动
const projectChange = function () {
const findData = userInfo.projects.find(item => item.project_id === projectValue)
if (findData) {
channelsOption = findData.channels
projectRole = findData.roles
}
}
// 选择渠道
const channelChange = function () {
const findData = channelsOption.find(item => item.channel_id === channelValue)
if (findData) {
channelRole = findData.roles
}
}
</script>
<template>
<el-dialog v-if="userInfo" class="user-dialog-class" title="用户信息" width="600px" :close-on-click-modal="false">
<div class="info">
<div class="item">
<div class="label">姓名:</div>
<div class="value">{{ userInfo.user_name }}</div>
</div>
<div class="item">
<div class="label">用户手机:</div>
<div class="value">{{ userInfo.mobile }}</div>
</div>
<div class="item">
<div class="label">用户邮箱:</div>
<div class="value">{{ userInfo.email }}</div>
</div>
</div>
<el-card class="box-card">
<div class="info block">
<div class="item">
<div class="label">选择项目:</div>
<div class="value">
<el-select @change="projectChange" v-model="projectValue" class="m-2" placeholder="选择项目" size="small">
<el-option
v-for="item in userInfo.projects"
:key="item.project_id"
:label="item.title"
:value="item.project_id"
/>
</el-select>
</div>
</div>
<div class="item">
<div class="label">角色权限:</div>
<div v-for="(item, index) in projectRole" :key="index" class="value" style="margin-right: 10px">
<el-tag>{{ item }}</el-tag>
</div>
</div>
<div class="item mt-20">
<div class="label">选择渠道:</div>
<div class="value">
<el-select @change="channelChange" v-model="channelValue" class="m-2" placeholder="选择渠道" size="small">
<el-option
v-for="item in channelsOption"
:key="item.channel_id"
:label="item.title"
:value="item.channel_id"
/>
</el-select>
</div>
</div>
<div class="item">
<div class="label">角色权限:</div>
<div v-for="(item, index) in channelRole" :key="index" class="value" style="margin-right: 10px">
<el-tag>{{ item }}</el-tag>
</div>
</div>
</div>
</el-card>
<template #footer>
<span class="dialog-footer">
<el-button @click="emit('update:modelValue', false)">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
<style lang="scss">
.user-dialog-class {
.el-dialog__header {
border-bottom: 1px solid #ccc;
margin-right: 0;
padding-bottom: 20px;
}
.el-dialog__body {
padding: 10px 20px 20px;
}
.info {
display: flex;
justify-content: space-between;
&.block {
display: block;
}
.item {
display: flex;
&.mt-20 {
margin-top: 20px;
}
.label {
display: inline-flex;
justify-content: flex-end;
align-items: flex-start;
flex: 0 0 auto;
font-size: 14px;
color: #969696;
height: 32px;
line-height: 32px;
box-sizing: border-box;
text-align: right;
}
.value {
font-size: 14px;
line-height: 32px;
.el-tag {
margin-top: 5px;
}
.ml-2 {
margin-right: 10px;
}
}
}
}
}
.box-card {
margin-top: 15px;
}
</style>
<script setup lang="ts"> <script setup lang="ts">
import AppList from '@/components/base/AppList.vue' import AppList from '@/components/base/AppList.vue'
import { getMemberList } from '../api'
const UserInfo = defineAsyncComponent(() => import('../components/UserInfo.vue'))
const appList = $ref<InstanceType<typeof AppList> | null>(null) const appList = $ref<InstanceType<typeof AppList> | null>(null)
const listOptions = $computed(() => { const listOptions = $computed(() => {
return { return {
remote: {
httpRequest: getMemberList,
params: {
user_name: '',
mobile: '',
email: '',
role_name: ''
}
},
filters: [ filters: [
{ type: 'input', prop: 'code', placeholder: '请输入用户姓名' }, { type: 'input', prop: 'user_name', placeholder: '请输入用户姓名' },
{ type: 'input', prop: 'code', placeholder: '请输入用户手机号' }, { type: 'input', prop: 'mobile', placeholder: '请输入用户手机号' },
{ type: 'input', prop: 'code', placeholder: '请输入用户邮箱' }, { type: 'input', prop: 'email', placeholder: '请输入角色邮箱' },
{ type: 'input', prop: 'code', placeholder: '请输入角色名称' } { type: 'input', prop: 'role_name', placeholder: '请输入角色名称' }
], ],
columns: [ columns: [
{ label: '姓名', prop: 'name' }, { label: '用户姓名', prop: 'user_name' },
{ label: '手机', prop: 'name' }, { label: '用户手机', prop: 'mobile' },
{ label: '邮箱', prop: 'name' }, { label: '用户邮箱', prop: 'email' },
{ label: '角色数量', prop: 'name' }, { label: '角色数量', prop: 'roles_count' },
{ label: '操作', prop: 'name', slots: 'table-x', width: 100 } { label: '操作', prop: 'name', slots: 'table-x', width: 100 }
],
data: [
{ id: 1, code: 123 },
{ id: 2, code: 456 }
] ]
} }
}) })
// 查看 // 查看
let currentRow = $ref() let labelVisible = $ref(false)
let currentRowId = $ref('')
function handleView(row: any) { function handleView(row: any) {
currentRow = row currentRowId = row.user_id
labelVisible = true
} }
</script> </script>
<template> <template>
<AppCard title="用户管理"> <AppCard title="用户管理">
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<UserInfo v-if="currentRowId && labelVisible" v-model="labelVisible" :id="currentRowId"></UserInfo>
<template #table-x="{ row }"> <template #table-x="{ row }">
<el-button text type="primary" @click="handleView(row)">查看</el-button> <el-button text type="primary" @click="handleView(row)">查看</el-button>
</template> </template>
......
...@@ -24,6 +24,12 @@ export default defineConfig(({ mode }) => ({ ...@@ -24,6 +24,12 @@ export default defineConfig(({ mode }) => ({
cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem')) cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem'))
}, },
proxy: { proxy: {
'/api/zws': {
target: 'http://localhost-new-zws-backend.ezijing.com',
// target: 'http://localhost-activity-backend.ezijing.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/api\/zws/, '')
},
'/api': 'https://saas-lab.ezijing.com' '/api': 'https://saas-lab.ezijing.com'
} }
}, },
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论