|
@@ -1,278 +1,143 @@
|
|
|
<template>
|
|
|
- <el-container>
|
|
|
- <el-aside width="200px" v-loading="showGroupLoading">
|
|
|
+ <div class="flex-column-page-wrap pageWrap">
|
|
|
+ <el-card class="box-card">
|
|
|
<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-aside width="200px">
|
|
|
+ <el-container>
|
|
|
+ <el-header>
|
|
|
+ <el-input v-model="groupFilterText" placeholder="输入关键字进行过滤" clearable />
|
|
|
+ </el-header>
|
|
|
+ <el-main class="nopadding">
|
|
|
+ <el-tree ref="treeRef" class="filter-tree" :data="data" :props="defaultProps" default-expand-all :filter-node-method="filterNode" />
|
|
|
+ </el-main>
|
|
|
+ </el-container>
|
|
|
+ </el-aside>
|
|
|
+ <el-divider direction="vertical" style="height: 100vh" />
|
|
|
+ <el-container>
|
|
|
+ <el-header>
|
|
|
+ <div class="flex flex-pack-justify">
|
|
|
+ <div class="left-panel">
|
|
|
+ <el-button type="primary" :icon="Plus"><Plus /></el-button>
|
|
|
+ <el-button type="danger" plain :icon="Delete"></el-button>
|
|
|
+ <el-button type="primary" plain>分配角色</el-button>
|
|
|
+ <el-button type="primary" plain>密码重置</el-button>
|
|
|
+ </div>
|
|
|
+ <div class="right-panel">
|
|
|
+ <div class="right-panel-search flex">
|
|
|
+ <el-input placeholder="登录账号 / 姓名" clearable></el-input>
|
|
|
+ <el-button type="primary" :icon="Search"></el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-header>
|
|
|
+ <el-main class="nopadding"> </el-main>
|
|
|
+ </el-container>
|
|
|
</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>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref, watch } from 'vue'
|
|
|
+import { ElTree } from 'element-plus'
|
|
|
+import { Plus, Delete, Search } from '@element-plus/icons-vue'
|
|
|
|
|
|
- <save-dialog v-if="dialog.save" ref="saveDialog" @success="handleSuccess" @closed="dialog.save = false"></save-dialog>
|
|
|
+interface Tree {
|
|
|
+ [key: string]: any
|
|
|
+}
|
|
|
|
|
|
- <assign-role-dialog
|
|
|
- v-if="dialog.assignRole"
|
|
|
- ref="assignRoleDialog"
|
|
|
- @success="handleSuccess"
|
|
|
- @closed="dialog.assignRole = false"
|
|
|
- ></assign-role-dialog>
|
|
|
-</template>
|
|
|
+const groupFilterText = ref('')
|
|
|
+const treeRef = ref<InstanceType<typeof ElTree>>()
|
|
|
|
|
|
-<!--样式问题先不调整-->
|
|
|
-<!--<link rel="stylesheet" href="src/style/style.scss">-->
|
|
|
+const defaultProps = {
|
|
|
+ children: 'children',
|
|
|
+ label: 'label'
|
|
|
+}
|
|
|
|
|
|
-<script lang="js">
|
|
|
-import saveDialog from './save'
|
|
|
-import assignRoleDialog from './assign-role'
|
|
|
+watch(groupFilterText, val => {
|
|
|
+ treeRef.value!.filter(val)
|
|
|
+})
|
|
|
|
|
|
-export default {
|
|
|
- name: 'user',
|
|
|
- components: {
|
|
|
- saveDialog,
|
|
|
- assignRoleDialog
|
|
|
+const filterNode = (value: string, data: Tree) => {
|
|
|
+ if (!value) return true
|
|
|
+ return data.label.includes(value)
|
|
|
+}
|
|
|
+
|
|
|
+const data: Tree[] = [
|
|
|
+ {
|
|
|
+ id: 1,
|
|
|
+ label: 'Level one 1',
|
|
|
+ children: [
|
|
|
+ {
|
|
|
+ id: 4,
|
|
|
+ label: 'Level two 1-1',
|
|
|
+ children: [
|
|
|
+ {
|
|
|
+ id: 9,
|
|
|
+ label: 'Level three 1-1-1'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 10,
|
|
|
+ label: 'Level three 1-1-2'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ]
|
|
|
},
|
|
|
- data() {
|
|
|
- return {
|
|
|
- dialog: {
|
|
|
- save: false,
|
|
|
- assignRole: false
|
|
|
+ {
|
|
|
+ id: 2,
|
|
|
+ label: 'Level one 2',
|
|
|
+ children: [
|
|
|
+ {
|
|
|
+ id: 5,
|
|
|
+ label: 'Level two 2-1'
|
|
|
},
|
|
|
- showGroupLoading: false,
|
|
|
- groupFilterText: '',
|
|
|
- group: [],
|
|
|
- apiObj: this.$API.user.page,
|
|
|
- selection: [],
|
|
|
- search: {
|
|
|
- name: null
|
|
|
+ {
|
|
|
+ id: 6,
|
|
|
+ label: 'Level two 2-2'
|
|
|
}
|
|
|
- }
|
|
|
- },
|
|
|
- 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)
|
|
|
- })
|
|
|
+ {
|
|
|
+ id: 3,
|
|
|
+ label: 'Level one 3',
|
|
|
+ children: [
|
|
|
+ {
|
|
|
+ id: 7,
|
|
|
+ label: 'Level two 3-1'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 8,
|
|
|
+ label: 'Level two 3-2'
|
|
|
}
|
|
|
- }
|
|
|
+ ]
|
|
|
}
|
|
|
-}
|
|
|
+]
|
|
|
</script>
|
|
|
+<style scoped lang="scss">
|
|
|
+.box-card {
|
|
|
+ // 单独自己写的
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
|
|
|
-<style></style>
|
|
|
+// todo 样式问题 应该要提成公用
|
|
|
+.pageWrap {
|
|
|
+ //padding-top: 12px;
|
|
|
+ padding: 12px 12px 0 12px;
|
|
|
+ overflow: auto;
|
|
|
+ background-color: #f5f6f7;
|
|
|
+}
|
|
|
+
|
|
|
+// 其他样式
|
|
|
+.local_table {
|
|
|
+ //padding: 0 12px;
|
|
|
+ box-shadow: 0 0 6px 4px rgb(145 159 175 / 6%);
|
|
|
+ border-top: 1px solid #eaedf0;
|
|
|
+ border-radius: 6px 6px 0 0;
|
|
|
+ background-color: #fff;
|
|
|
+ //padding: 12px 12px 0 12px;
|
|
|
+ &.tabs_content-wrap {
|
|
|
+ border-top: 0;
|
|
|
+ border-radius: 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|