فهرست منبع

feat: 把爱组搭的user页面搬过来 init等待联调接口

luoyali 1 سال پیش
والد
کامیت
1c9768d3bd
6فایلهای تغییر یافته به همراه596 افزوده شده و 0 حذف شده
  1. 1 0
      src/api/index.ts
  2. 76 0
      src/api/system/user.ts
  3. 14 0
      src/router/index.ts
  4. 68 0
      src/views/setting/user/assign-role.vue
  5. 278 0
      src/views/setting/user/index.vue
  6. 159 0
      src/views/setting/user/save.vue

+ 1 - 0
src/api/index.ts

@@ -0,0 +1 @@
+// 自动import导入所有 api下面的文件夹中

+ 76 - 0
src/api/system/user.ts

@@ -0,0 +1,76 @@
+import request from '@/utils/request'
+import { AxiosPromise } from 'axios'
+
+// apiUrl
+const api = {
+	page: '/sys/user/page',
+	create: '/sys/user/create',
+	update: '/sys/user/update',
+	delete: '/sys/user/delete',
+	resetPassword: '/sys/user/reset-password',
+	assignRoles: '/sys/user/assign-roles',
+	roleIds: '/sys/user/role-ids'
+}
+
+/**
+ * 用户管理 - 列表
+ */
+export function userPageApi(data: any): AxiosPromise {
+	return request({
+		url: api.page,
+		method: 'post',
+		data
+	})
+}
+
+/**
+ * 用户管理 - 新增编辑保存
+ */
+export function userAddOrEditSaveApi(data: any): AxiosPromise {
+	return request({
+		url: data.id ? api.update : api.create,
+		method: 'post',
+		data
+	})
+}
+
+/**
+ * 用户管理 - 删除
+ */
+export function userDeleteApi(data: any): AxiosPromise {
+	return request({
+		url: api.delete,
+		method: 'post',
+		data
+	})
+}
+
+/**
+ * 用户管理 - 重置密码
+ */
+export function userResetPasswordApi(data: any): AxiosPromise {
+	return request({
+		url: api.resetPassword,
+		method: 'post',
+		data
+	})
+}
+/**
+ * 用户管理 - 重置密码
+ */
+export function userAssignRolesApi(data: any): AxiosPromise {
+	return request({
+		url: api.assignRoles,
+		method: 'post',
+		data
+	})
+}
+/**
+ * 用户管理 - 重置密码
+ */
+export function userRoleIdsApi(data: any): AxiosPromise {
+	return request({
+		url: `${api.roleIds}?id=${data.id}`,
+		method: 'post'
+	})
+}

+ 14 - 0
src/router/index.ts

@@ -146,6 +146,20 @@ export const constantRoutes: Array<AppRouteRecordRaw> = [
 		]
 	},
 	// 仅用于研发测试 END
+	{
+		path: '/setting',
+		component: Layout,
+		meta: { title: 'Setting', icon: 'guide' },
+		redirect: '/setting/user',
+		children: [
+			{
+				path: 'user',
+				component: () => import('@/views/setting/user/index.vue'),
+				name: 'user',
+				meta: { title: '用户管理', icon: '' }
+			}
+		]
+	},
 	// 外部链接
 	{
 		path: '/external-link',

+ 68 - 0
src/views/setting/user/assign-role.vue

@@ -0,0 +1,68 @@
+<template>
+	<el-dialog title="分配角色" v-model="visible" :width="550" destroy-on-close @closed="$emit('closed')">
+		<el-select v-model="roleIds" style="width: 500px;" multiple filterable
+				   placeholder="请选择分配角色">
+			<el-option
+				v-for="item in options"
+				:key="item.id"
+				:label="item.name"
+				:value="item.id"
+			>
+				<span style="float: left">{{ item.name }}</span>
+				<span style="float: right;color: var(--el-text-color-secondary); font-size: 13px;">{{
+						item.alias
+					}}</span>
+			</el-option>
+		</el-select>
+		<template #footer>
+			<el-button @click="visible=false">取 消</el-button>
+			<el-button type="primary" :loading="isSaveing" @click="submit()">保 存</el-button>
+		</template>
+	</el-dialog>
+</template>
+
+<script>
+export default {
+	emits: ['success', 'closed'],
+	data() {
+		return {
+			visible: false,
+			isSaveing: false,
+			options: [],
+			roleIds: [],
+			userIds: []
+		}
+	},
+	mounted() {
+		this.loadRoles();
+	},
+	methods: {
+		async open(userIds) {
+			this.visible = true;
+			this.userIds = userIds;
+			if (userIds.length == 1) {
+				let res = await this.$API.user.roleIds(userIds[0]);
+				this.roleIds = res.data;
+			}
+		},
+		async submit() {
+			this.isSaveing = true;
+			let res = await this.$API.user.assignRoles({
+				userIds: this.userIds,
+				roleIds: this.roleIds
+			});
+			if (res.data) {
+				this.isSaveing = false;
+				this.visible = false;
+				this.$message.success("分配成功")
+			} else {
+				this.$message.error("分配失败")
+			}
+		},
+		async loadRoles() {
+			let res = await this.$API.role.listAll();
+			this.options = res.data;
+		}
+	}
+}
+</script>

+ 278 - 0
src/views/setting/user/index.vue

@@ -0,0 +1,278 @@
+<template>
+	<el-container>
+		<el-aside width="200px" v-loading="showGroupLoading">
+			<el-container>
+				<el-header>
+					<el-input placeholder="输入关键字进行过滤" v-model="groupFilterText" clearable></el-input>
+				</el-header>
+				<el-main class="nopadding">
+					<el-tree
+						ref="group"
+						class="menu"
+						node-key="id"
+						:data="group"
+						:current-node-key="''"
+						:highlight-current="true"
+						:expand-on-click-node="false"
+						:filter-node-method="groupFilterNode"
+						@node-click="roleClick"
+					></el-tree>
+				</el-main>
+			</el-container>
+		</el-aside>
+		<el-container>
+			<el-header>
+				<div class="left-panel">
+					<el-button type="primary" icon="el-icon-plus" @click="add"></el-button>
+					<el-button type="danger" plain icon="el-icon-delete" :disabled="selection.length == 0" @click="batch_del"></el-button>
+					<el-button type="primary" plain :disabled="selection.length == 0" @click="assignRole">分配角色</el-button>
+					<el-button type="primary" plain :disabled="selection.length == 0" @click="resetPwd">密码重置</el-button>
+				</div>
+				<div class="right-panel">
+					<div class="right-panel-search">
+						<el-input v-model="search.name" placeholder="登录账号 / 姓名" clearable></el-input>
+						<el-button type="primary" icon="el-icon-search" @click="upSearch"></el-button>
+					</div>
+				</div>
+			</el-header>
+			<el-main class="nopadding">
+				<scTable ref="table" :apiObj="apiObj" @selection-change="selectionChange" stripe remoteSort remoteFilter highlight-current-row>
+					<el-table-column fixed="left" type="selection" width="50"></el-table-column>
+					<el-table-column
+						label="头像"
+						fixed="left"
+						width="80"
+						column-key="filterAvatar"
+						:filters="[
+							{ text: '已上传', value: '1' },
+							{ text: '未上传', value: '0' }
+						]"
+					>
+						<template #default="scope">
+							<el-avatar :src="scope.row.avatar" size="small"></el-avatar>
+						</template>
+					</el-table-column>
+					<el-table-column
+						label="登录账号"
+						fixed="left"
+						width="100"
+						column-key="filterUserName"
+						:filters="[
+							{ text: '系统账号', value: '1' },
+							{ text: '普通账号', value: '0' }
+						]"
+					>
+						<template #default="scope">
+							<el-button type="text" size="small" @click="table_show(scope.row, scope.$index)">
+								{{ scope.row.username }}
+							</el-button>
+						</template>
+					</el-table-column>
+					<el-table-column label="状态" fixed="left" width="50">
+						<template #default="scope">
+							<sc-status-indicator pulse type="success" v-if="scope.row.status == 1"></sc-status-indicator>
+							<sc-status-indicator pulse type="danger" v-else></sc-status-indicator>
+						</template>
+					</el-table-column>
+					<el-table-column label="昵称" prop="nickName" width="100"></el-table-column>
+					<el-table-column label="姓名" prop="realName" width="100"></el-table-column>
+					<el-table-column label="性别" prop="sex" width="80" sortable="custom"></el-table-column>
+					<el-table-column label="修改人" prop="updateBy" width="100"></el-table-column>
+					<el-table-column label="修改时间" prop="updateTime" width="126"></el-table-column>
+					<el-table-column label="创建人" prop="createBy" width="100"></el-table-column>
+					<el-table-column label="创建时间" prop="createTime" width="126"></el-table-column>
+					<el-table-column label="操作" fixed="right" align="center" width="100">
+						<template #default="scope">
+							<el-tooltip content="编辑" placement="bottom" effect="light">
+								<el-icon class="ibt0" @click="table_edit(scope.row, scope.$index)">
+									<sc-icon-edit />
+								</el-icon>
+							</el-tooltip>
+							<el-divider direction="vertical"></el-divider>
+							<el-popconfirm title="确定删除吗?" @confirm="table_del(scope.row)">
+								<template #reference>
+									<el-icon class="ibt0">
+										<sc-icon-delete />
+									</el-icon>
+								</template>
+							</el-popconfirm>
+						</template>
+					</el-table-column>
+				</scTable>
+			</el-main>
+		</el-container>
+	</el-container>
+
+	<save-dialog v-if="dialog.save" ref="saveDialog" @success="handleSuccess" @closed="dialog.save = false"></save-dialog>
+
+	<assign-role-dialog
+		v-if="dialog.assignRole"
+		ref="assignRoleDialog"
+		@success="handleSuccess"
+		@closed="dialog.assignRole = false"
+	></assign-role-dialog>
+</template>
+
+<!--样式问题先不调整-->
+<!--<link rel="stylesheet" href="src/style/style.scss">-->
+
+<script lang="js">
+import saveDialog from './save'
+import assignRoleDialog from './assign-role'
+
+export default {
+	name: 'user',
+	components: {
+		saveDialog,
+		assignRoleDialog
+	},
+	data() {
+		return {
+			dialog: {
+				save: false,
+				assignRole: false
+			},
+			showGroupLoading: false,
+			groupFilterText: '',
+			group: [],
+			apiObj: this.$API.user.page,
+			selection: [],
+			search: {
+				name: null
+			}
+		}
+	},
+	watch: {
+		groupFilterText(val) {
+			this.$refs.group.filter(val);
+		}
+	},
+	mounted() {
+		this.getGroup()
+	},
+	methods: {
+		//添加
+		add() {
+			this.dialog.save = true
+			this.$nextTick(() => {
+				this.$refs.saveDialog.open()
+			})
+		},
+		//编辑
+		table_edit(row) {
+			this.dialog.save = true
+			this.$nextTick(() => {
+				this.$refs.saveDialog.open('edit').setData(row)
+			})
+		},
+		//查看
+		table_show(row) {
+			this.dialog.save = true
+			this.$nextTick(() => {
+				this.$refs.saveDialog.open('show').setData(row)
+			})
+		},
+		//删除
+		async delete(ids) {
+			let res = await this.$API.user.delete(ids);
+			if (res.code == 200) {
+				this.$refs.table.refresh()
+				this.$message.success("删除成功")
+			} else {
+				this.$alert(res.message, "提示", {type: 'error'})
+			}
+		},
+		//删除
+		table_del(row) {
+			this.delete([row.id])
+		},
+		//批量删除
+		batch_del() {
+			this.$confirm(`确定删除选中的 ${this.selection.length} 项吗?`, '提示', {
+				type: 'warning'
+			}).then(() => {
+				const loading = this.$loading();
+				this.delete(this.selectUserIds())
+				loading.close();
+			})
+		},
+		// 当前已选择ID数组
+		selectUserIds() {
+			let ids = [];
+			this.selection.forEach(item => {
+				ids.push(item.id)
+			})
+			return ids;
+		},
+		// 分配角色
+		assignRole() {
+			this.dialog.assignRole = true;
+			this.$nextTick(() => {
+				this.$refs.assignRoleDialog.open(this.selectUserIds())
+			})
+		},
+		async resetPassword(data) {
+			let res = await this.$API.user.resetPassword({ids: this.selectUserIds(), password: data});
+			if (res.code == 200) {
+				this.$message.success("密码重置成功")
+			} else {
+				this.$alert(res.message, "提示", {type: 'error'})
+			}
+		},
+		// 重置密码
+		resetPwd() {
+			this.$prompt('请输入新的密码', '密码重置', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				inputPattern: /^(?![A-z0-9]+$)(?=.[^%&',;=?$\x22])(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{6,20}$/,
+				inputErrorMessage: '登录密码必须为6-20位大小写字母数字特殊字符组合',
+			})
+			.then(({ value }) => {
+				this.resetPassword(value)
+			})
+		},
+		//表格选择后回调事件
+		selectionChange(selection) {
+			this.selection = selection;
+		},
+		//加载树数据
+		async getGroup() {
+			this.showGroupLoading = true;
+			let res = await this.$API.role.listTree();
+			this.showGroupLoading = false;
+			res.data.unshift({id: '', label: '所有'});
+			this.group = res.data;
+		},
+		//树过滤
+		groupFilterNode(value, data) {
+			if (!value) return true;
+			return data.label.indexOf(value) !== -1;
+		},
+		//树点击事件
+		roleClick(data) {
+			this.$refs.table.reload({
+				data: {
+					roleId: data.id ? data.id : null
+				}
+			})
+		},
+		//搜索
+		upSearch() {
+			this.$refs.table.upData(this.search)
+		},
+		//本地更新数据
+		handleSuccess(data, mode) {
+			if (mode == 'add') {
+				data.id = new Date().getTime()
+				this.$refs.table.tableData.unshift(data)
+			} else if (mode == 'edit') {
+				this.$refs.table.tableData.filter(item => item.id === data.id).forEach(item => {
+					Object.assign(item, data)
+				})
+			}
+		}
+	}
+}
+</script>
+
+<style></style>

+ 159 - 0
src/views/setting/user/save.vue

@@ -0,0 +1,159 @@
+<template>
+	<el-dialog :title="titleMap[mode]" v-model="visible" :width="500" destroy-on-close @closed="$emit('closed')">
+		<el-form :model="form" :rules="rules" :disabled="mode=='show'" ref="dialogForm" label-width="100px"
+				 label-position="left">
+			<!--			<el-form-item label="头像" prop="avatar">-->
+			<!--				<sc-upload v-model="form.avatar" title="上传头像"></sc-upload>-->
+			<!--			</el-form-item>-->
+			<el-form-item label="登录账号" prop="username">
+				<el-input v-model="form.username" placeholder="用于登录系统" clearable></el-input>
+			</el-form-item>
+			<template v-if="mode=='add'">
+				<el-form-item label="登录密码" prop="password">
+					<el-input type="password" v-model="form.password" clearable show-password></el-input>
+				</el-form-item>
+				<el-form-item label="确认密码" prop="password2">
+					<el-input type="password" v-model="form.password2" clearable show-password></el-input>
+				</el-form-item>
+			</template>
+			<el-form-item label="昵称" prop="nickName">
+				<el-input v-model="form.nickName" placeholder="用于登录系统" clearable></el-input>
+			</el-form-item>
+			<el-form-item label="姓名" prop="realName">
+				<el-input v-model="form.realName" placeholder="请输入完整的真实姓名" clearable></el-input>
+			</el-form-item>
+			<el-form-item label="性别" prop="sex">
+				<el-radio-group v-model="form.sex">
+					<el-radio label="男">男</el-radio>
+					<el-radio label="女">女</el-radio>
+				</el-radio-group>
+			</el-form-item>
+			<el-form-item label="状态" prop="status">
+				<el-switch v-model="form.status" :active-value="1" :inactive-value="0"></el-switch>
+			</el-form-item>
+			<el-form-item label="所属角色" prop="roleIds">
+				<el-select v-model="form.roleIds" placeholder="请选择分配角色" multiple clearable style="width: 100%;">
+					<el-option v-for="item in roles" :key="item.id" :label="item.name" :value="item.id">
+						<span style="float: left">{{ item.name }}</span>
+						<span
+							style="float: right;color: var(--el-text-color-secondary); font-size: 13px;">{{ item.alias }}</span>
+					</el-option>
+				</el-select>
+			</el-form-item>
+		</el-form>
+		<template #footer>
+			<el-button @click="visible=false">取 消</el-button>
+			<el-button v-if="mode!='show'" type="primary" :loading="isSaveing" @click="submit()">保 存</el-button>
+		</template>
+	</el-dialog>
+</template>
+
+<script>
+export default {
+	emits: ['success', 'closed'],
+	data() {
+		return {
+			mode: "add",
+			titleMap: {
+				add: '新增用户',
+				edit: '编辑用户',
+				show: '查看'
+			},
+			visible: false,
+			isSaveing: false,
+			//表单数据
+			form: {
+				id: "",
+				username: "",
+				password: "",
+				nickName: "",
+				avatar: "",
+				realName: "",
+				group: "",
+				sex: "男",
+				status: 1,
+				roleIds: []
+			},
+			//验证规则
+			rules: {
+				avatar: [
+					{required: true, message: '请上传头像'}
+				],
+				username: [
+					{required: true, message: '请输入登录账号'}
+				],
+				password: [
+					{required: true, message: '请输入登录密码'},
+					{
+						validator: (rule, value, callback) => {
+							if (this.form.password2 !== '') {
+								this.$refs.dialogForm.validateField('password2');
+							}
+							callback();
+						}
+					}
+				],
+				password2: [
+					{required: true, message: '请再次输入密码'},
+					{
+						validator: (rule, value, callback) => {
+							if (value !== this.form.password) {
+								callback(new Error('两次输入密码不一致!'));
+							} else {
+								callback();
+							}
+						}
+					}
+				],
+				group: [
+					{required: true, message: '请选择所属角色'}
+				]
+			},
+			//所需数据选项
+			roles: []
+		}
+	},
+	mounted() {
+		this.loadRoles()
+	},
+	methods: {
+		open(mode = 'add') {
+			this.mode = mode;
+			this.visible = true;
+			return this
+		},
+		async loadRoles() {
+			let res = await this.$API.role.listAll();
+			this.roles = res.data;
+		},
+		//表单提交方法
+		submit() {
+			this.$refs.dialogForm.validate(async (valid) => {
+				if (valid) {
+					this.isSaveing = true;
+					var res = await this.$API.user.save(this.form);
+					this.isSaveing = false;
+					if (res.code == 200) {
+						this.$emit('success', this.form, this.mode)
+						this.visible = false;
+						this.$message.success("操作成功")
+					} else {
+						this.$alert(res.message, "提示", {type: 'error'})
+					}
+				} else {
+					return false;
+				}
+			})
+		},
+		//表单注入数据
+		async setData(data) {
+			this.form = data
+			let res = await this.$API.user.roleIds(data.id);
+			this.form.roleIds = res.data;
+		}
+	}
+}
+</script>
+
+<style>
+</style>