|
@@ -5,46 +5,96 @@
|
|
|
<el-aside width="200px">
|
|
|
<el-container>
|
|
|
<el-header>
|
|
|
- <el-input v-model="groupFilterText" placeholder="输入关键字进行过滤" clearable />
|
|
|
+ <el-input v-model="groupFilterText" placeholder="输入关键字进行过滤" clearable style="margin-top: 10px" />
|
|
|
</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-tree
|
|
|
+ ref="treeRef"
|
|
|
+ class="menu-tree"
|
|
|
+ :data="treeData"
|
|
|
+ node-key="id"
|
|
|
+ :current-node-key="''"
|
|
|
+ :highlight-current="true"
|
|
|
+ :expand-on-click-node="false"
|
|
|
+ @node-click="roleClick"
|
|
|
+ :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-main class="nopadding">
|
|
|
+ <!-- 公用搜索组件 -->
|
|
|
+ <LeSearchForm ref="searchForm" v-model:searchData="searchData" :forms="forms" :loading="tableOpts.options.loading"> </LeSearchForm>
|
|
|
+
|
|
|
+ <!-- LeTable 组件使用 -->
|
|
|
+ <LeTable
|
|
|
+ ref="tableRef"
|
|
|
+ v-model:searchParams="tableOpts.searchParams"
|
|
|
+ v-bind="tableOpts"
|
|
|
+ :columns="activeColumns"
|
|
|
+ v-model:curRow="tableOpts.curRow"
|
|
|
+ v-model:checked-options="checkedColumns"
|
|
|
+ >
|
|
|
+ <template #toolLeft>
|
|
|
+ <el-button type="primary">
|
|
|
+ <el-icon class="btn-icon">
|
|
|
+ <Plus />
|
|
|
+ </el-icon>
|
|
|
+ </el-button>
|
|
|
+ <el-button type="danger">
|
|
|
+ <el-icon class="btn-icon">
|
|
|
+ <Delete />
|
|
|
+ </el-icon>
|
|
|
+ </el-button>
|
|
|
+ <el-button plain> 分配角色 </el-button>
|
|
|
+ <el-button plain> 密码重置 </el-button>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #filterAvatarSlot="scope">
|
|
|
+ <el-avatar :src="scope.row.avatar" size="small"></el-avatar>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #statusSlot="scope">
|
|
|
+ <status-indicator pulse type="success" v-if="scope.row.status === 1"></status-indicator>
|
|
|
+ <status-indicator pulse type="danger" v-else></status-indicator>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #actionSlot="">
|
|
|
+ <el-tooltip content="编辑" placement="bottom" effect="light">
|
|
|
+ <el-icon class="ibt0">
|
|
|
+ <Edit />
|
|
|
+ </el-icon>
|
|
|
+ </el-tooltip>
|
|
|
+ <el-divider direction="vertical"></el-divider>
|
|
|
+ <el-popconfirm title="确定删除吗?">
|
|
|
+ <template #reference>
|
|
|
+ <el-icon class="ibt0">
|
|
|
+ <Delete />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ </el-popconfirm>
|
|
|
+ </template>
|
|
|
+ </LeTable>
|
|
|
+ </el-main>
|
|
|
</el-container>
|
|
|
</el-container>
|
|
|
</el-card>
|
|
|
</div>
|
|
|
</template>
|
|
|
-<script lang="ts" setup>
|
|
|
-import { ref, watch } from 'vue'
|
|
|
+<script lang="tsx" setup>
|
|
|
+import role from '@/api/system/role'
|
|
|
+import user from '@/api/system/user'
|
|
|
+import { nextTick, ref, watch } from 'vue'
|
|
|
import { ElTree } from 'element-plus'
|
|
|
-import { Plus, Delete, Search } from '@element-plus/icons-vue'
|
|
|
-
|
|
|
-interface Tree {
|
|
|
- [key: string]: any
|
|
|
-}
|
|
|
-
|
|
|
+import { useTablePage } from '@/hooks/useTablePage'
|
|
|
+import { Plus, Delete } from '@element-plus/icons-vue'
|
|
|
+import StatusIndicator from '@/components/StatusIndicator'
|
|
|
+const showGroupLoading = ref(false)
|
|
|
const groupFilterText = ref('')
|
|
|
const treeRef = ref<InstanceType<typeof ElTree>>()
|
|
|
|
|
@@ -53,91 +103,177 @@ const defaultProps = {
|
|
|
label: 'label'
|
|
|
}
|
|
|
|
|
|
-watch(groupFilterText, val => {
|
|
|
- treeRef.value!.filter(val)
|
|
|
-})
|
|
|
-
|
|
|
const filterNode = (value: string, data: Tree) => {
|
|
|
if (!value) return true
|
|
|
return data.label.includes(value)
|
|
|
}
|
|
|
|
|
|
-const data: Tree[] = [
|
|
|
+const treeData = ref([])
|
|
|
+
|
|
|
+// 获取左侧菜单数据
|
|
|
+const getGroup = async () => {
|
|
|
+ showGroupLoading.value = true
|
|
|
+ let data = await role.roleListTreeApi()
|
|
|
+ showGroupLoading.value = false
|
|
|
+ data.unshift({ id: '', label: '所有' })
|
|
|
+ treeData.value = data // console.log('获取左侧菜单数据')
|
|
|
+}
|
|
|
+
|
|
|
+// 左侧菜单点击
|
|
|
+const roleClick = data => {
|
|
|
+ console.log(data.id, 'data.id')
|
|
|
+ // 刷新右侧的表格
|
|
|
+}
|
|
|
+
|
|
|
+// 搜索条件
|
|
|
+const forms = ref([
|
|
|
+ {
|
|
|
+ prop: 'name',
|
|
|
+ label: '账号/姓名:',
|
|
|
+ itemType: 'input',
|
|
|
+ placeholder: '请输入登录账号 / 姓名'
|
|
|
+ }
|
|
|
+])
|
|
|
+
|
|
|
+// table列表数据请求
|
|
|
+const queryList = async () => {
|
|
|
+ const { options, searchParams } = tableOpts
|
|
|
+ options.loading = true
|
|
|
+ console.log('搜索参数: ', JSON.stringify(tableOpts.searchParams))
|
|
|
+ try {
|
|
|
+ const { records: list, total } = await user.userPageApi(searchParams)
|
|
|
+ tableOpts.total = total
|
|
|
+ tableOpts.list = list
|
|
|
+ } catch {
|
|
|
+ console.log('获取列表数据失败')
|
|
|
+ tableOpts.total = 0
|
|
|
+ tableOpts.list = []
|
|
|
+ options.loading = false // 更改加载中的 loading值
|
|
|
+ } finally {
|
|
|
+ options.loading = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// table 参数
|
|
|
+const columns = [
|
|
|
+ {
|
|
|
+ prop: 'filterAvatar',
|
|
|
+ label: '头像',
|
|
|
+ minWidth: 80,
|
|
|
+ slots: {
|
|
|
+ default: 'filterAvatarSlot'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'username',
|
|
|
+ label: '登录账号',
|
|
|
+ minWidth: 100
|
|
|
+ },
|
|
|
{
|
|
|
- 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'
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
- ]
|
|
|
+ prop: 'status',
|
|
|
+ label: '状态',
|
|
|
+ minWidth: 50,
|
|
|
+ slots: {
|
|
|
+ default: 'statusSlot'
|
|
|
+ }
|
|
|
},
|
|
|
{
|
|
|
- id: 2,
|
|
|
- label: 'Level one 2',
|
|
|
- children: [
|
|
|
- {
|
|
|
- id: 5,
|
|
|
- label: 'Level two 2-1'
|
|
|
- },
|
|
|
- {
|
|
|
- id: 6,
|
|
|
- label: 'Level two 2-2'
|
|
|
- }
|
|
|
- ]
|
|
|
+ prop: 'nickName',
|
|
|
+ label: '昵称',
|
|
|
+ minWidth: 100
|
|
|
},
|
|
|
{
|
|
|
- id: 3,
|
|
|
- label: 'Level one 3',
|
|
|
- children: [
|
|
|
- {
|
|
|
- id: 7,
|
|
|
- label: 'Level two 3-1'
|
|
|
- },
|
|
|
- {
|
|
|
- id: 8,
|
|
|
- label: 'Level two 3-2'
|
|
|
- }
|
|
|
- ]
|
|
|
+ prop: 'realName',
|
|
|
+ label: '姓名',
|
|
|
+ minWidth: 100
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'sex',
|
|
|
+ label: '性别',
|
|
|
+ minWidth: 80
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'updateBy',
|
|
|
+ label: '修改人',
|
|
|
+ minWidth: 100
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'updateTime',
|
|
|
+ label: '修改时间',
|
|
|
+ minWidth: 126
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'createBy',
|
|
|
+ label: '创建人',
|
|
|
+ minWidth: 100
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'createTime',
|
|
|
+ label: '创建时间',
|
|
|
+ minWidth: 126
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'action',
|
|
|
+ label: '操作',
|
|
|
+ width: 100,
|
|
|
+ fixed: 'right',
|
|
|
+ slots: {
|
|
|
+ default: 'actionSlot'
|
|
|
+ }
|
|
|
}
|
|
|
]
|
|
|
+
|
|
|
+const { searchData, tableOpts, checkedColumns, activeColumns } = useTablePage(
|
|
|
+ {
|
|
|
+ options: {
|
|
|
+ showIndex: false
|
|
|
+ },
|
|
|
+ searchParams: {
|
|
|
+ page: 1,
|
|
|
+ size: 10
|
|
|
+ },
|
|
|
+ // 需要展示的列
|
|
|
+ columns,
|
|
|
+ // 控制列配置
|
|
|
+ columnsConfig: {
|
|
|
+ columns
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ queryList,
|
|
|
+ fetchImmediate: false
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+nextTick(() => {
|
|
|
+ getGroup()
|
|
|
+ queryList()
|
|
|
+})
|
|
|
+
|
|
|
+watch(groupFilterText, val => {
|
|
|
+ treeRef.value!.filter(val)
|
|
|
+})
|
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
|
-.box-card {
|
|
|
- // 单独自己写的
|
|
|
+// 单独自己写的
|
|
|
+:deep(.box-card) {
|
|
|
height: 100%;
|
|
|
+ .el-card__body {
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-// todo 样式问题 应该要提成公用
|
|
|
-.pageWrap {
|
|
|
- //padding-top: 12px;
|
|
|
- padding: 12px 12px 0 12px;
|
|
|
- overflow: auto;
|
|
|
- background-color: #f5f6f7;
|
|
|
+// 角色的树结构样式
|
|
|
+:deep(.menu-tree) {
|
|
|
+ .el-tree-node__content {
|
|
|
+ height: 36px;
|
|
|
+ }
|
|
|
+ .el-tree-node__content .el-tree-node__label .icon {
|
|
|
+ margin-right: 5px;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-// 其他样式
|
|
|
-.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;
|
|
|
- }
|
|
|
+.nopadding {
|
|
|
+ padding: 0px;
|
|
|
}
|
|
|
</style>
|