[重大更新] 整体主题样式重写 改为卡片式布局 样式更企业化

This commit is contained in:
疯狂的狮子Li
2026-03-17 12:35:56 +08:00
parent b83755e626
commit 833dfa67fc
70 changed files with 5250 additions and 1568 deletions
+36 -34
View File
@@ -1,51 +1,53 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="search">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="85px">
<el-form-item label="客户端key" prop="clientKey">
<el-input v-model="queryParams.clientKey" placeholder="请输入客户端key" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="客户端秘钥" prop="clientSecret">
<el-input v-model="queryParams.clientSecret" placeholder="请输入客户端秘钥" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="状态" clearable>
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<div class="p-2 page-shell system-client-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div><h3>筛选条件</h3></div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="85px" class="query-form">
<el-form-item label="客户端key" prop="clientKey">
<el-input v-model="queryParams.clientKey" placeholder="请输入客户端key" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="客户端秘钥" prop="clientSecret">
<el-input v-model="queryParams.clientSecret" placeholder="请输入客户端秘钥" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="状态" clearable>
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<h3>客户端列表</h3>
</div>
<div class="toolbar-actions">
<el-button v-hasPermi="['system:client:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:client:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">
修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:client:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:client:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table v-loading="loading" :data="clientList" border @selection-change="handleSelectionChange">
<el-table v-loading="loading" :data="clientList" border class="data-table" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="true" label="id" align="center" prop="id" />
<el-table-column label="客户端id" align="center" prop="clientId" />
+47 -21
View File
@@ -1,9 +1,16 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<div class="p-2 page-shell system-config-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div>
<span class="panel-kicker">Search Filters</span>
<h3>筛选条件</h3>
</div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="参数名称" prop="configName">
<el-input v-model="queryParams.configName" placeholder="请输入参数名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
@@ -33,34 +40,31 @@
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="hover">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<span class="panel-kicker">Config Dataset</span>
<h3>参数列表</h3>
<p> {{ total }} 条记录支持键值维护导出和缓存刷新</p>
</div>
<div class="toolbar-actions">
<el-button v-hasPermi="['system:config:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:config:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">
修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:config:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:config:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:config:remove']" type="danger" plain icon="Refresh" @click="handleRefreshCache">刷新缓存</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table v-loading="loading" border :data="configList" @selection-change="handleSelectionChange">
<el-table v-loading="loading" border class="data-table" :data="configList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="参数主键" align="center" prop="configId" />
<el-table-column label="参数名称" align="center" prop="configName" :show-overflow-tooltip="true" />
@@ -259,3 +263,25 @@ onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.page-shell {
display: flex;
flex-direction: column;
}
.data-table {
:deep(.el-button.is-link) {
width: 32px;
height: 32px;
border-radius: 10px;
background: rgba(53, 109, 255, 0.08);
}
}
@media (max-width: 900px) {
.toolbar-shell {
align-items: flex-start;
}
}
</style>
+47 -15
View File
@@ -1,9 +1,16 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<div class="p-2 page-shell system-dept-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div>
<span class="panel-kicker">Search Filters</span>
<h3>筛选条件</h3>
</div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="部门名称" prop="deptName">
<el-input v-model="queryParams.deptName" placeholder="请输入部门名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
@@ -22,24 +29,27 @@
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="hover">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10">
<el-col :span="1.5">
<el-button v-hasPermi="['system:dept:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增 </el-button>
</el-col>
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<span class="panel-kicker">Department Dataset</span>
<h3>部门列表</h3>
<p>支持树形层级维护负责人绑定和部门状态管理</p>
</div>
<div class="toolbar-actions">
<el-button v-hasPermi="['system:dept:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
<el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table
ref="deptTableRef"
v-loading="loading"
class="data-table"
:data="deptList"
row-key="deptId"
border
@@ -318,3 +328,25 @@ onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.page-shell {
display: flex;
flex-direction: column;
}
.data-table {
:deep(.el-button.is-link) {
width: 32px;
height: 32px;
border-radius: 10px;
background: rgba(53, 109, 255, 0.08);
}
}
@media (max-width: 900px) {
.toolbar-shell {
align-items: flex-start;
}
}
</style>
+71 -67
View File
@@ -1,35 +1,32 @@
<template>
<div class="p-2 dict-page">
<div class="p-2 page-shell dict-page">
<el-row :gutter="16" class="dict-grid">
<!-- 字典类型 -->
<el-col :xs="24" :lg="12">
<el-card shadow="hover" class="dict-card">
<el-card shadow="hover" class="dict-card table-panel">
<template #header>
<div class="dict-card__header">
<div class="dict-card__title">字典管理</div>
<right-toolbar v-model:show-search="showTypeSearch" @query-table="getTypeList" />
<div class="toolbar-shell dict-card__header">
<div class="table-heading">
<div class="panel-heading search-panel-toggle dict-title-toggle" @click.stop="showTypeSearch = !showTypeSearch">
<div>
<h3>字典管理</h3>
</div>
</div>
</div>
<div class="toolbar-actions">
<right-toolbar v-model:show-search="showTypeSearch" :search="false" @query-table="getTypeList" />
</div>
</div>
</template>
<div v-show="showTypeSearch" class="dict-form-scroll">
<el-form ref="typeQueryFormRef" :model="typeQueryParams" :inline="true">
<div class="dict-search" :class="{ 'is-collapsed': !showTypeSearch }">
<el-form ref="typeQueryFormRef" :model="typeQueryParams" :inline="true" class="query-form">
<el-form-item label="字典名称" prop="dictName">
<el-input v-model="typeQueryParams.dictName" placeholder="请输入字典名称" clearable @keyup.enter="handleTypeQuery" />
</el-form-item>
<el-form-item label="字典类型" prop="dictType">
<el-input v-model="typeQueryParams.dictType" placeholder="请输入字典类型" clearable @keyup.enter="handleTypeQuery" />
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleTypeQuery">搜索</el-button>
<el-button icon="Refresh" @click="handleTypeResetQuery">重置</el-button>
@@ -37,7 +34,7 @@
</el-form>
</div>
<div class="dict-actions">
<div class="toolbar-actions dict-actions">
<el-button v-hasPermi="['system:dict:add']" type="primary" plain icon="Plus" @click="handleTypeAdd">新增</el-button>
<el-button v-hasPermi="['system:dict:edit']" type="success" plain icon="Edit" :disabled="typeSingle" @click="handleTypeUpdate()"
>修改</el-button
@@ -54,6 +51,7 @@
ref="typeTableRef"
v-loading="typeLoading"
border
class="data-table"
:data="typeList"
highlight-current-row
@row-click="handleTypeRowClick"
@@ -98,19 +96,25 @@
<!-- 字典数据 -->
<el-col :xs="24" :lg="12">
<el-card shadow="hover" class="dict-card">
<el-card shadow="hover" class="dict-card table-panel">
<template #header>
<div class="dict-card__header">
<div class="dict-card__title">
字典数据
<span class="dict-card__subtitle">{{ currentDictLabel }}</span>
<div class="toolbar-shell dict-card__header">
<div class="table-heading">
<div class="panel-heading search-panel-toggle dict-title-toggle" @click.stop="showDataSearch = !showDataSearch">
<div>
<h3>字典数据</h3>
<p v-if="hasCurrentDict" class="dict-card__subtitle">{{ currentDictLabel }}</p>
</div>
</div>
</div>
<div class="toolbar-actions">
<right-toolbar v-model:show-search="showDataSearch" :search="false" @query-table="getDataList" />
</div>
<right-toolbar v-model:show-search="showDataSearch" @query-table="getDataList" />
</div>
</template>
<div v-show="showDataSearch" class="dict-form-scroll">
<el-form ref="dataQueryFormRef" :model="dataQueryParams" :inline="true">
<div class="dict-search" :class="{ 'is-collapsed': !showDataSearch }">
<el-form ref="dataQueryFormRef" :model="dataQueryParams" :inline="true" class="query-form">
<el-form-item label="字典标签" prop="dictLabel">
<el-input
v-model="dataQueryParams.dictLabel"
@@ -127,7 +131,7 @@
</el-form>
</div>
<div class="dict-actions">
<div class="toolbar-actions dict-actions">
<el-button v-hasPermi="['system:dict:add']" type="primary" plain icon="Plus" :disabled="!hasCurrentDict" @click="handleDataAdd"
>新增</el-button
>
@@ -155,10 +159,10 @@
</div>
<div class="dict-table-wrap">
<el-table v-loading="dataLoading" border :data="dataList" @selection-change="handleDataSelectionChange">
<el-table v-loading="dataLoading" border class="data-table" :data="dataList" @selection-change="handleDataSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="字典编码" align="center" prop="dictCode" />
<el-table-column label="字典标签" align="center" prop="dictLabel" width="80">
<el-table-column label="字典标签" align="center" prop="dictLabel" width="100">
<template #default="scope">
<span
v-if="
@@ -174,7 +178,7 @@
>
</template>
</el-table-column>
<el-table-column label="字典键值" align="center" prop="dictValue" width="80" />
<el-table-column label="字典键值" align="center" prop="dictValue" width="100" />
<el-table-column label="字典排序" align="center" prop="dictSort" width="80" />
<el-table-column label="备注" align="center" prop="remark" width="100" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
@@ -213,13 +217,15 @@
<el-input v-model="typeForm.dictName" placeholder="请输入字典名称" />
</el-form-item>
<el-form-item prop="dictType">
<template #label>
<span>
<el-tooltip content="数据存储中的Key值,如:sys_user_sex" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
字典类型
</span>
</template>
<el-input v-model="typeForm.dictType" placeholder="请输入字典类型" maxlength="100" />
<span slot="label">
<el-tooltip content="数据存储中的Key值,如:sys_user_sex" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
字典类型
</span>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="typeForm.remark" type="textarea" placeholder="请输入内容"></el-input>
@@ -291,7 +297,6 @@ const typeIds = ref<Array<number | string>>([]);
const typeSingle = ref(true);
const typeMultiple = ref(true);
const typeTotal = ref(0);
const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
const typeFormRef = ref<ElFormInstance>();
const typeQueryFormRef = ref<ElFormInstance>();
@@ -387,7 +392,7 @@ const { queryParams: dataQueryParams, form: dataForm, rules: dataRules } = toRef
const getTypeList = () => {
typeLoading.value = true;
listType(proxy?.addDateRange(typeQueryParams.value, dateRange.value)).then((res) => {
listType(typeQueryParams.value).then((res) => {
typeList.value = res.rows;
typeTotal.value = res.total;
typeLoading.value = false;
@@ -438,7 +443,6 @@ const handleTypeQuery = () => {
};
const handleTypeResetQuery = () => {
dateRange.value = ['', ''];
typeQueryFormRef.value?.resetFields();
handleTypeQuery();
};
@@ -614,54 +618,55 @@ onMounted(() => {
row-gap: 16px;
}
.dict-card__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
.dict-card {
height: 100%;
}
.dict-card__title {
display: inline-flex;
align-items: baseline;
gap: 8px;
font-weight: 600;
.dict-card__header {
gap: 12px;
}
.dict-title-toggle {
padding: 0 !important;
}
.dict-card__subtitle {
margin: 4px 0 0;
font-size: 12px;
color: var(--el-text-color-secondary);
}
.dict-form-scroll {
max-height: 200px;
overflow: auto;
.dict-search {
overflow: hidden;
max-height: 240px;
opacity: 1;
margin-bottom: 12px;
padding-right: 6px;
padding-bottom: 4px;
transition:
max-height 0.32s cubic-bezier(0.22, 1, 0.36, 1),
opacity 0.24s ease,
margin-bottom 0.24s ease;
}
.dict-form-scroll :deep(.el-form) {
display: flex;
flex-wrap: wrap;
column-gap: 12px;
row-gap: 10px;
.dict-search.is-collapsed {
max-height: 0;
opacity: 0;
margin-bottom: 0;
pointer-events: none;
}
.dict-form-scroll :deep(.el-form-item) {
margin: 0;
.dict-search :deep(.el-form-item) {
margin-bottom: 0;
}
.dict-actions {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 8px 0 12px;
margin: 0 0 12px;
padding-bottom: 0;
}
.dict-actions :deep(.el-button) {
height: 32px;
padding: 0 14px;
border-radius: 10px !important;
}
.dict-actions :deep(.el-button + .el-button) {
@@ -671,5 +676,4 @@ onMounted(() => {
.dict-table-wrap {
overflow-x: auto;
}
</style>
+46 -14
View File
@@ -1,9 +1,16 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<div class="p-2 page-shell system-menu-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div>
<span class="panel-kicker">Search Filters</span>
<h3>筛选条件</h3>
</div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="菜单名称" prop="menuName">
<el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
@@ -19,24 +26,27 @@
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="hover">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10">
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<span class="panel-kicker">Menu Dataset</span>
<h3>菜单列表</h3>
<p>支持树形加载图标选择级联删除和目录/菜单/按钮三级维护</p>
</div>
<div class="toolbar-actions">
<el-button v-hasPermi="['system:menu:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:menu:remove']" type="danger" plain icon="Delete" @click="handleCascadeDelete" :loading="deleteLoading">级联删除</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table
ref="menuTableRef"
v-loading="loading"
class="data-table"
:data="menuList"
row-key="menuId"
border
@@ -532,6 +542,28 @@ onMounted(() => {
});
</script>
<style lang="scss" scoped>
.page-shell {
display: flex;
flex-direction: column;
}
.data-table {
:deep(.el-button.is-link) {
width: 32px;
height: 32px;
border-radius: 10px;
background: rgba(53, 109, 255, 0.08);
}
}
@media (max-width: 900px) {
.toolbar-shell {
align-items: flex-start;
}
}
</style>
<style scoped lang="scss">
.tree-border {
height: 300px;
+49 -20
View File
@@ -1,9 +1,16 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<div class="p-2 page-shell system-notice-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div>
<span class="panel-kicker">Search Filters</span>
<h3>筛选条件</h3>
</div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="公告标题" prop="noticeTitle">
<el-input v-model="queryParams.noticeTitle" placeholder="请输入公告标题" clearable @keyup.enter="handleQuery" />
</el-form-item>
@@ -22,29 +29,29 @@
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="hover">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<span class="panel-kicker">Notice Dataset</span>
<h3>公告列表</h3>
<p> {{ total }} 条记录支持类型筛选内容编辑和状态管理</p>
</div>
<div class="toolbar-actions">
<el-button v-hasPermi="['system:notice:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:notice:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:notice:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">
修改
</el-button>
<el-button v-hasPermi="['system:notice:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
删除
</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table v-loading="loading" border :data="noticeList" @selection-change="handleSelectionChange">
<el-table v-loading="loading" border class="data-table" :data="noticeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="序号" align="center" prop="noticeId" width="100" />
<el-table-column label="公告标题" align="center" prop="noticeTitle" :show-overflow-tooltip="true" />
@@ -241,3 +248,25 @@ onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.page-shell {
display: flex;
flex-direction: column;
}
.data-table {
:deep(.el-button.is-link) {
width: 32px;
height: 32px;
border-radius: 10px;
background: rgba(53, 109, 255, 0.08);
}
}
@media (max-width: 900px) {
.toolbar-shell {
align-items: flex-start;
}
}
</style>
+49 -20
View File
@@ -1,9 +1,16 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<div class="p-2 page-shell system-oss-config-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div>
<span class="panel-kicker">Search Filters</span>
<h3>筛选条件</h3>
</div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="配置key" prop="configKey">
<el-input v-model="queryParams.configKey" placeholder="配置key" clearable @keyup.enter="handleQuery" />
</el-form-item>
@@ -23,29 +30,29 @@
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="hover">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<span class="panel-kicker">Storage Config</span>
<h3>OSS 配置</h3>
<p> {{ total }} 条记录支持默认桶切换权限策略维护和站点配置</p>
</div>
<div class="toolbar-actions">
<el-button v-hasPermi="['system:ossConfig:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:ossConfig:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:ossConfig:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">
修改
</el-button>
<el-button v-hasPermi="['system:ossConfig:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
删除
</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table v-loading="loading" border :data="ossConfigList" @selection-change="handleSelectionChange">
<el-table v-loading="loading" border class="data-table" :data="ossConfigList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="columns[0].visible" label="主建" align="center" prop="ossConfigId" />
<el-table-column v-if="columns[1].visible" label="配置key" align="center" prop="configKey" />
@@ -342,3 +349,25 @@ onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.page-shell {
display: flex;
flex-direction: column;
}
.data-table {
:deep(.el-button.is-link) {
width: 32px;
height: 32px;
border-radius: 10px;
background: rgba(53, 109, 255, 0.08);
}
}
@media (max-width: 900px) {
.toolbar-shell {
align-items: flex-start;
}
}
</style>
+49 -24
View File
@@ -1,9 +1,16 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<div class="p-2 page-shell system-oss-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div>
<span class="panel-kicker">Search Filters</span>
<h3>筛选条件</h3>
</div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="文件名" prop="fileName">
<el-input v-model="queryParams.fileName" placeholder="请输入文件名" clearable @keyup.enter="handleQuery" />
</el-form-item>
@@ -34,42 +41,40 @@
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="hover">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<span class="panel-kicker">Object Storage</span>
<h3>文件列表</h3>
<p> {{ total }} 条记录支持文件上传预览切换和 OSS 配置跳转</p>
</div>
<div class="toolbar-actions">
<el-button v-hasPermi="['system:oss:upload']" type="primary" plain icon="Upload" @click="handleFile">上传文件</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:oss:upload']" type="primary" plain icon="Upload" @click="handleImage">上传图片</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:oss:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['system:oss:edit']"
:type="previewListResource ? 'danger' : 'warning'"
plain
@click="handlePreviewListResource(!previewListResource)"
>预览开关 : {{ previewListResource ? '禁用' : '启用' }}</el-button
>
</el-col>
<el-col :span="1.5">
预览开关 : {{ previewListResource ? '禁用' : '启用' }}
</el-button>
<el-button v-hasPermi="['system:ossConfig:list']" type="info" plain icon="Operation" @click="handleOssConfig">配置管理</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table
v-if="showTable"
v-loading="loading"
:data="ossList"
class="data-table"
border
:header-cell-class-name="handleHeaderClass"
@selection-change="handleSelectionChange"
@@ -307,12 +312,10 @@ const handleDownload = (row: OssVO) => {
};
/** 预览开关按钮 */
const handlePreviewListResource = async (preview: boolean) => {
const text = preview ? '启用' : '停用';
try {
await proxy?.$modal.confirm('确认要"' + text + '""预览列表图片"配置吗?');
await proxy?.updateConfigByKey('sys.oss.previewListResource', preview);
await getList();
proxy?.$modal.msgSuccess(text + '成功');
proxy?.$modal.msgSuccess((preview ? '启用' : '停用') + '成功');
} catch {
return;
}
@@ -331,3 +334,25 @@ onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.page-shell {
display: flex;
flex-direction: column;
}
.data-table {
:deep(.el-button.is-link) {
width: 32px;
height: 32px;
border-radius: 10px;
background: rgba(53, 109, 255, 0.08);
}
}
@media (max-width: 900px) {
.toolbar-shell {
align-items: flex-start;
}
}
</style>
+76 -27
View File
@@ -1,13 +1,21 @@
<template>
<div class="p-2">
<el-row :gutter="20">
<div class="p-2 page-shell system-post-page">
<el-row :gutter="20" class="content-grid">
<!-- 部门树 -->
<el-col :lg="4" :xs="24" style="">
<el-card shadow="hover">
<el-col :lg="5" :xs="24">
<el-card shadow="hover" class="side-panel">
<template #header>
<div class="panel-heading">
<div>
<span class="panel-kicker">Department Filter</span>
<h3>部门结构</h3>
</div>
</div>
</template>
<el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
<el-tree
ref="deptTreeRef"
class="mt-2"
class="mt-2 dept-tree"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' } as any"
@@ -19,11 +27,18 @@
/>
</el-card>
</el-col>
<el-col :lg="20" :xs="24">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-col :lg="19" :xs="24" class="content-main">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div>
<span class="panel-kicker">Search Filters</span>
<h3>筛选条件</h3>
</div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="岗位编码" prop="postCode">
<el-input v-model="queryParams.postCode" placeholder="请输入岗位编码" clearable @keyup.enter="handleQuery" />
</el-form-item>
@@ -61,30 +76,28 @@
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="hover">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<span class="panel-kicker">Post Dataset</span>
<h3>岗位列表</h3>
<p> {{ total }} 条记录支持按部门筛选岗位维护和导出</p>
</div>
<div class="toolbar-actions">
<el-button v-hasPermi="['system:post:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:post:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:post:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">
修改
</el-button>
<el-button v-hasPermi="['system:post:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:post:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table v-loading="loading" border :data="postList" @selection-change="handleSelectionChange">
<el-table v-loading="loading" border class="data-table" :data="postList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="岗位编号" align="center" prop="postId" />
<el-table-column label="岗位编码" align="center" prop="postCode" />
@@ -359,3 +372,39 @@ onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.page-shell {
display: flex;
flex-direction: column;
}
.content-grid {
margin: 0 !important;
}
.content-main {
display: flex;
flex-direction: column;
gap: 12px;
}
.dept-tree {
padding-top: 6px;
}
.data-table {
:deep(.el-button.is-link) {
width: 32px;
height: 32px;
border-radius: 10px;
background: rgba(53, 109, 255, 0.08);
}
}
@media (max-width: 900px) {
.toolbar-shell {
align-items: flex-start;
}
}
</style>
+21 -17
View File
@@ -1,8 +1,13 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="search">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<div class="p-2 page-shell role-auth-user-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div><h3>筛选条件</h3></div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="用户名称" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
@@ -13,27 +18,26 @@
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10">
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<h3>已授权用户</h3>
</div>
<div class="toolbar-actions">
<el-button v-hasPermi="['system:role:add']" type="primary" plain icon="Plus" @click="openSelectUser">添加用户</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:remove']" type="danger" plain icon="CircleClose" :disabled="multiple" @click="cancelAuthUserAll">
批量取消授权
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Close" @click="handleClose">关闭</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" :search="true" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange">
<el-table v-loading="loading" border class="data-table" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
+47 -20
View File
@@ -1,9 +1,16 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<div class="page-shell system-role-page">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div>
<span class="panel-kicker">Search Filters</span>
<h3>筛选条件</h3>
</div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="queryParams.roleName" placeholder="请输入角色名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
@@ -34,28 +41,26 @@
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="hover">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10">
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<span class="panel-kicker">Role Dataset</span>
<h3>角色列表</h3>
<p> {{ total }} 条记录支持菜单权限数据权限和分配用户等完整配置流程</p>
</div>
<div class="toolbar-actions">
<el-button v-hasPermi="['system:role:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:edit']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:remove']" type="danger" plain :disabled="ids.length === 0" @click="handleDelete()">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:role:remove']" type="danger" plain :disabled="ids.length === 0" icon="Delete" @click="handleDelete()">删除</el-button>
<el-button v-hasPermi="['system:role:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
</el-col>
<right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table ref="roleTableRef" border v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
<el-table ref="roleTableRef" border class="data-table" v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column v-if="false" label="角色编号" prop="roleId" width="120" />
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
@@ -501,3 +506,25 @@ onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.page-shell {
display: flex;
flex-direction: column;
}
.data-table {
:deep(.el-button.is-link) {
width: 32px;
height: 32px;
border-radius: 10px;
background: rgba(53, 109, 255, 0.08);
}
}
@media (max-width: 900px) {
.toolbar-shell {
align-items: flex-start;
}
}
</style>
+52 -33
View File
@@ -1,38 +1,43 @@
<template>
<el-row>
<el-dialog v-model="visible" title="选择用户" width="800px" top="5vh" append-to-body>
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="用户名称" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row>
<el-table ref="tableRef" border :data="userList" height="260px" @row-click="clickRow" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ proxy.parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-if="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
</el-row>
<el-dialog v-model="visible" title="选择用户" width="800px" top="5vh" append-to-body class="select-user-dialog">
<div class="page-shell select-user-shell">
<el-card shadow="hover" class="search-panel select-user-card">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="用户名称" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card shadow="hover" class="table-panel select-user-card">
<el-table ref="tableRef" border class="data-table" :data="userList" height="260px" @row-click="clickRow" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="用户名称" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ proxy.parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-if="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
</el-card>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleSelectUser"> </el-button>
@@ -128,3 +133,17 @@ defineExpose({
show
});
</script>
<style lang="scss" scoped>
.select-user-shell {
gap: 12px;
}
.select-user-card :deep(.el-card__body) {
padding: 14px 16px !important;
}
.select-user-dialog :deep(.el-dialog__body) {
padding-top: 12px;
}
</style>
+69 -52
View File
@@ -1,57 +1,60 @@
<template>
<div class="p-2">
<div class="panel">
<h4 class="panel-title">基本信息</h4>
<el-form :model="form" :inline="true">
<el-row :gutter="10">
<el-col :span="2.5">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" disabled />
</el-form-item>
</el-col>
<el-col :span="2.5">
<el-form-item label="登录账号" prop="userName">
<el-input v-model="form.userName" disabled />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="panel">
<h4 class="panel-title">角色信息</h4>
<div>
<el-table
ref="tableRef"
v-loading="loading"
border
:row-key="getRowKey"
:data="roles.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
@row-click="clickRow"
@selection-change="handleSelectionChange"
>
<el-table-column label="序号" width="55" type="index" align="center">
<template #default="scope">
<span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column type="selection" :reserve-selection="true" :selectable="checkSelectable" width="55"></el-table-column>
<el-table-column label="角色编号" align="center" prop="roleId" />
<el-table-column label="角色名称" align="center" prop="roleName" />
<el-table-column label="权限字符" align="center" prop="roleKey" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ proxy.parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" v-model:page="pageNum" v-model:limit="pageSize" :total="total" />
<div style="text-align: center; margin-left: -120px; margin-top: 30px">
<el-button type="primary" @click="submitForm()">提交</el-button>
<el-button @click="close()">返回</el-button>
<div class="p-2 page-shell auth-role-page">
<el-card shadow="hover" class="search-panel auth-role-info">
<template #header>
<div class="panel-heading">
<div><h3>基本信息</h3></div>
</div>
<div></div>
</div>
</div>
</template>
<el-form :model="form" :inline="true" class="query-form auth-role-form">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" disabled />
</el-form-item>
<el-form-item label="登录账号" prop="userName">
<el-input v-model="form.userName" disabled />
</el-form-item>
</el-form>
</el-card>
<el-card shadow="hover" class="table-panel">
<template #header>
<div class="toolbar-shell">
<div class="table-heading">
<h3>角色信息</h3>
</div>
<div class="toolbar-actions">
<el-button type="primary" @click="submitForm()">提交</el-button>
<el-button @click="close()">返回</el-button>
</div>
</div>
</template>
<el-table
ref="tableRef"
v-loading="loading"
border
class="data-table"
:row-key="getRowKey"
:data="roles.slice((pageNum - 1) * pageSize, pageNum * pageSize)"
@row-click="clickRow"
@selection-change="handleSelectionChange"
>
<el-table-column label="序号" width="55" type="index" align="center">
<template #default="scope">
<span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column type="selection" :reserve-selection="true" :selectable="checkSelectable" width="55"></el-table-column>
<el-table-column label="角色编号" align="center" prop="roleId" />
<el-table-column label="角色名称" align="center" prop="roleName" />
<el-table-column label="权限字符" align="center" prop="roleKey" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ proxy.parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" v-model:page="pageNum" v-model:limit="pageSize" :total="total" />
</el-card>
</div>
</template>
@@ -144,3 +147,17 @@ onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.auth-role-form :deep(.el-form-item) {
margin-bottom: 0;
}
.auth-role-form :deep(.el-input) {
width: 220px;
}
.auth-role-info :deep(.el-card__body) {
padding-top: 14px !important;
}
</style>
+73 -24
View File
@@ -1,13 +1,21 @@
<template>
<div class="p-2">
<el-row :gutter="20">
<div class="page-shell system-user-page">
<el-row :gutter="20" class="content-grid">
<!-- 部门树 -->
<el-col :lg="4" :xs="24" style="">
<el-card shadow="hover">
<el-col :lg="5" :xs="24">
<el-card shadow="hover" class="side-panel">
<template #header>
<div class="panel-heading">
<div>
<span class="panel-kicker">Department Filter</span>
<h3>部门结构</h3>
</div>
</div>
</template>
<el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
<el-tree
ref="deptTreeRef"
class="mt-2"
class="mt-2 dept-tree"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' } as any"
@@ -19,11 +27,18 @@
/>
</el-card>
</el-col>
<el-col :lg="20" :xs="24">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-col :lg="19" :xs="24" class="content-main">
<div class="search-wrap">
<el-card shadow="hover" class="search-panel" :class="{ 'is-collapsed': !showSearch }">
<template #header>
<div class="panel-heading search-panel-toggle" @click.stop="showSearch = !showSearch">
<div>
<span class="panel-kicker">Search Filters</span>
<h3>筛选条件</h3>
</div>
</div>
</template>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" class="query-form">
<el-form-item label="用户名称" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
@@ -57,25 +72,23 @@
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="hover">
<el-card shadow="hover" class="table-panel">
<template #header>
<el-row :gutter="10">
<el-col :span="1.5">
<div class="toolbar-shell">
<div class="table-heading">
<span class="panel-kicker">User Dataset</span>
<h3>用户列表</h3>
<p> {{ total }} 条记录支持部门筛选状态切换导入导出和角色分配</p>
</div>
<div class="toolbar-actions">
<el-button v-has-permi="['system:user:add']" type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-has-permi="['system:user:edit']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()">
修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-has-permi="['system:user:remove']" type="danger" plain :disabled="multiple" icon="Delete" @click="handleDelete()">
删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-dropdown class="mt-[1px]">
<el-button plain type="info">
更多
@@ -90,12 +103,12 @@
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
<right-toolbar v-model:show-search="showSearch" :columns="columns" :search="true" @query-table="getList"></right-toolbar>
</el-row>
<right-toolbar v-model:show-search="showSearch" :columns="columns" :search="false" @query-table="getList"></right-toolbar>
</div>
</div>
</template>
<el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange">
<el-table v-loading="loading" border class="data-table" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column v-if="columns[0].visible" key="userId" label="用户编号" align="center" prop="userId" />
<el-table-column v-if="columns[1].visible" key="userName" label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" />
@@ -677,3 +690,39 @@ async function handleDeptChange(value: number | string) {
form.value.postIds = [];
}
</script>
<style lang="scss" scoped>
.page-shell {
display: flex;
flex-direction: column;
}
.content-grid {
margin: 0 !important;
}
.content-main {
display: flex;
flex-direction: column;
gap: 12px;
}
.dept-tree {
padding-top: 6px;
}
.data-table {
:deep(.el-button.is-link) {
width: 32px;
height: 32px;
border-radius: 10px;
background: rgba(53, 109, 255, 0.08);
}
}
@media (max-width: 900px) {
.toolbar-shell {
align-items: flex-start;
}
}
</style>
+130 -23
View File
@@ -1,54 +1,76 @@
<template>
<div class="p-2">
<el-row :gutter="20">
<div class="p-2 page-shell profile-page">
<el-row :gutter="20" class="profile-grid">
<el-col :span="6" :xs="24">
<el-card class="box-card">
<el-card shadow="hover" class="side-panel profile-summary-card">
<template #header>
<div class="clearfix">
<span>个人信息</span>
<div class="panel-heading">
<div><h3>个人信息</h3></div>
</div>
</template>
<div>
<div class="text-center">
<div class="profile-summary">
<div class="text-center profile-avatar">
<userAvatar />
</div>
<ul class="list-group list-group-striped">
<li class="list-group-item">
<svg-icon icon-class="user" />用户名称
<div class="pull-right">{{ state.user.userName }}</div>
<div class="profile-item-label">
<svg-icon icon-class="user" />
<span>用户名称</span>
</div>
<span class="profile-item-value">{{ state.user.userName || '-' }}</span>
</li>
<li class="list-group-item">
<svg-icon icon-class="phone" />手机号码
<div class="pull-right">{{ state.user.phonenumber }}</div>
<div class="profile-item-label">
<svg-icon icon-class="phone" />
<span>手机号码</span>
</div>
<span class="profile-item-value">{{ state.user.phonenumber || '-' }}</span>
</li>
<li class="list-group-item">
<svg-icon icon-class="email" />用户邮箱
<div class="pull-right">{{ state.user.email }}</div>
<div class="profile-item-label">
<svg-icon icon-class="email" />
<span>用户邮箱</span>
</div>
<span class="profile-item-value">{{ state.user.email || '-' }}</span>
</li>
<li class="list-group-item">
<svg-icon icon-class="tree" />所属部门
<div v-if="state.user.deptName" class="pull-right">{{ state.user.deptName }} / {{ state.postGroup }}</div>
<div class="profile-item-label">
<svg-icon icon-class="tree" />
<span>所属部门</span>
</div>
<span v-if="state.user.deptName" class="profile-item-value">{{ state.user.deptName }} / {{ state.postGroup }}</span>
<span v-else class="profile-item-value">-</span>
</li>
<li class="list-group-item">
<svg-icon icon-class="peoples" />所属角色
<div class="pull-right">{{ state.roleGroup }}</div>
<div class="profile-item-label">
<svg-icon icon-class="peoples" />
<span>所属角色</span>
</div>
<span class="profile-item-value">{{ state.roleGroup || '-' }}</span>
</li>
<li class="list-group-item">
<svg-icon icon-class="date" />创建日期
<div class="pull-right">{{ state.user.createTime }}</div>
<div class="profile-item-label">
<svg-icon icon-class="date" />
<span>创建日期</span>
</div>
<span class="profile-item-value">{{ state.user.createTime || '-' }}</span>
</li>
</ul>
</div>
</el-card>
</el-col>
<el-col :span="18" :xs="24">
<el-card>
<el-card shadow="hover" class="table-panel profile-main-card">
<template #header>
<div class="clearfix">
<span>基本资料</span>
<div class="toolbar-shell">
<div class="table-heading">
<h3>个人设置</h3>
<p>维护个人资料密码第三方应用和在线设备</p>
</div>
</div>
</template>
<el-tabs v-model="activeTab">
<el-tabs v-model="activeTab" class="profile-tabs">
<el-tab-pane label="基本资料" name="userinfo">
<userInfo :user="userForm" />
</el-tab-pane>
@@ -120,3 +142,88 @@ onMounted(() => {
getOnlines();
});
</script>
<style lang="scss" scoped>
.profile-grid {
row-gap: 12px;
}
.profile-summary-card,
.profile-main-card {
height: 100%;
}
.profile-summary {
display: flex;
flex-direction: column;
gap: 18px;
}
.profile-avatar {
margin-bottom: 4px;
}
.profile-item-label {
display: inline-flex;
align-items: center;
gap: 8px;
font-weight: 600;
}
.profile-item-value {
max-width: 58%;
text-align: right;
color: var(--el-text-color-secondary);
word-break: break-word;
}
.profile-summary :deep(.list-group-item) {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 12px 0;
}
.profile-tabs :deep(.el-tabs__header) {
margin-bottom: 18px;
}
.profile-tabs :deep(.el-tabs__nav-wrap::after),
.profile-tabs :deep(.el-tabs__active-bar) {
display: none;
}
.profile-tabs :deep(.el-tabs__nav) {
gap: 8px;
}
.profile-tabs :deep(.el-tabs__item) {
display: inline-flex;
align-items: center;
justify-content: center;
height: 36px;
min-width: 88px;
padding: 0 16px;
border-radius: 10px;
color: var(--el-text-color-regular);
}
.profile-tabs :deep(.el-tabs__item:nth-child(2)),
.profile-tabs :deep(.el-tabs__item.is-top:first-child),
.profile-tabs :deep(.el-tabs__item.is-top:last-child) {
padding-left: 16px;
padding-right: 16px;
}
.profile-tabs :deep(.el-tabs__item.is-active) {
background: rgba(53, 109, 255, 0.1);
color: var(--el-color-primary);
}
@media (max-width: 768px) {
.profile-item-value {
max-width: 50%;
}
}
</style>
@@ -1,6 +1,6 @@
<template>
<div>
<el-table :data="devices" border style="width: 100%; height: 100%; font-size: 14px">
<div class="profile-table-wrap">
<el-table :data="devices" border class="data-table profile-device-table">
<el-table-column label="设备类型" align="center">
<template #default="scope">
<dict-tag :options="sys_device_type" :value="scope.row.deviceType" />
@@ -52,6 +52,12 @@ const handldDelOnline = (row: any) => {
proxy?.$modal.msgError(res.msg);
}
})
.catch(() => {});
.catch(() => {});
};
</script>
<style lang="scss" scoped>
.profile-table-wrap {
width: 100%;
}
</style>
+22 -3
View File
@@ -1,5 +1,5 @@
<template>
<el-form ref="pwdRef" :model="user" :rules="rules" label-width="80px">
<el-form ref="pwdRef" :model="user" :rules="rules" label-width="80px" class="profile-form">
<el-form-item label="旧密码" prop="oldPassword">
<el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password />
</el-form-item>
@@ -9,9 +9,9 @@
<el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password />
</el-form-item>
<el-form-item>
<el-form-item class="profile-form__actions">
<el-button type="primary" @click="submit">保存</el-button>
<el-button type="danger" @click="close">关闭</el-button>
<el-button @click="close">关闭</el-button>
</el-form-item>
</el-form>
</template>
@@ -71,3 +71,22 @@ const close = () => {
proxy?.$tab.closePage();
};
</script>
<style lang="scss" scoped>
.profile-form {
max-width: 520px;
}
.profile-form :deep(.el-input__wrapper) {
border-radius: 12px;
}
.profile-form :deep(.el-button) {
border-radius: 10px;
}
.profile-form__actions :deep(.el-form-item__content) {
display: flex;
gap: 8px;
}
</style>
+87 -35
View File
@@ -1,6 +1,6 @@
<template>
<div>
<el-table :data="auths" border style="width: 100%; height: 100%; font-size: 14px">
<div class="profile-auth">
<el-table :data="auths" border class="data-table profile-auth-table">
<el-table-column label="序号" width="50" type="index" />
<el-table-column label="绑定账号平台" width="140" align="center" prop="source" show-overflow-tooltip />
<el-table-column label="头像" width="120" align="center" prop="avatar">
@@ -12,43 +12,48 @@
<el-table-column label="绑定时间" width="180" align="center" prop="createTime" />
<el-table-column label="操作" width="80" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button size="small" type="text" @click="unlockAuth(scope.row)">解绑</el-button>
<el-tooltip content="解绑" placement="top">
<el-button link type="primary" icon="CircleClose" @click="unlockAuth(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<div id="git-user-binding">
<h4 class="provider-desc">你可以绑定以下第三方帐号</h4>
<div id="authlist" class="user-bind">
<div class="provider-section">
<div class="provider-heading">
<h4 class="provider-desc">可绑定的第三方应用</h4>
<p>点击下方平台完成账号绑定</p>
</div>
<div class="user-bind">
<a class="third-app" href="#" title="使用 微信 账号授权登录" @click="authUrl('wechat')">
<div class="git-other-login-icon">
<div class="third-app__icon">
<svg-icon icon-class="wechat" />
</div>
<span class="app-name">WeiXin</span>
<span class="app-name">微信</span>
</a>
<a class="third-app" href="#" title="使用 MaxKey 账号授权登录" @click="authUrl('maxkey')">
<div class="git-other-login-icon">
<div class="third-app__icon">
<svg-icon icon-class="maxkey" />
</div>
<span class="app-name">MaxKey</span>
</a>
<a class="third-app" href="#" title="使用 TopIam 账号授权登录" @click="authUrl('topiam')">
<div class="git-other-login-icon">
<div class="third-app__icon">
<svg-icon icon-class="topiam" />
</div>
<span class="app-name">TopIam</span>
</a>
<a class="third-app" href="#" title="使用 Gitee 账号授权登录" @click="authUrl('gitee')">
<div class="git-other-login-icon">
<div class="third-app__icon">
<svg-icon icon-class="gitee" />
</div>
<span class="app-name">Gitee</span>
</a>
<a class="third-app" href="#" title="使用 GitHub 账号授权登录" @click="authUrl('github')">
<div class="git-other-login-icon">
<div class="third-app__icon">
<svg-icon icon-class="github" />
</div>
<span class="app-name">Github</span>
<span class="app-name">GitHub</span>
</a>
</div>
</div>
@@ -94,44 +99,77 @@ const authUrl = (source: string) => {
</script>
<style lang="scss" scoped>
.user-bind .third-app {
display: -webkit-box;
display: -ms-flexbox;
.profile-auth {
display: flex;
flex-direction: column;
gap: 18px;
}
.profile-auth-table {
width: 100%;
}
.provider-section {
display: flex;
flex-direction: column;
gap: 14px;
}
.provider-heading p {
margin: 6px 0 0;
color: var(--el-text-color-secondary);
}
.user-bind .third-app {
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
min-width: 80px;
float: left;
justify-content: center;
gap: 8px;
min-height: 84px;
padding: 12px 10px;
border: 1px solid var(--app-surface-border);
border-radius: 12px;
background: rgba(248, 250, 252, 0.82);
transition:
transform 0.2s ease,
border-color 0.2s ease,
box-shadow 0.2s ease;
}
.user-bind {
font-size: 1rem;
text-align: start;
height: 50px;
margin-top: 10px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(96px, 108px));
gap: 10px;
justify-content: start;
}
.git-other-login-icon > img {
height: 32px;
.third-app:hover {
transform: translateY(-1px);
border-color: rgba(53, 109, 255, 0.3);
box-shadow: var(--app-shadow-sm);
}
.third-app__icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
border-radius: 10px;
background: rgba(53, 109, 255, 0.08);
font-size: 18px;
}
a {
text-decoration: none;
cursor: pointer;
color: #005980;
color: inherit;
}
.provider-desc {
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Liberation Sans',
'PingFang SC', 'Microsoft YaHei', 'Hiragino Sans GB', 'Wenquanyi Micro Hei', 'WenQuanYi Zen Hei', 'ST Heiti', SimHei, SimSun,
'WenQuanYi Zen Hei Sharp', sans-serif;
font-size: 1.071rem;
margin: 0;
font-size: 16px;
}
td > img {
@@ -141,4 +179,18 @@ td > img {
border-radius: 50%;
margin-right: 5px;
}
.app-name {
font-weight: 600;
font-size: 13px;
line-height: 1.2;
text-align: center;
word-break: break-word;
}
:global(html.dark) {
.user-bind .third-app {
background: rgba(15, 23, 42, 0.64);
}
}
</style>
+26 -1
View File
@@ -159,7 +159,18 @@ const closeDialog = () => {
.user-info-head {
position: relative;
display: inline-block;
width: 120px;
height: 120px;
cursor: pointer;
}
.user-info-head :deep(.img-circle) {
width: 120px;
height: 120px;
object-fit: cover;
border-radius: 50%;
border: 4px solid rgba(255, 255, 255, 0.92);
box-shadow: var(--app-shadow-sm);
}
.user-info-head:hover:after {
@@ -176,7 +187,21 @@ const closeDialog = () => {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
cursor: pointer;
line-height: 110px;
line-height: 120px;
border-radius: 50%;
}
.avatar-upload-preview {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
border-radius: 18px;
background: rgba(248, 250, 252, 0.9);
}
.avatar-upload-preview img {
max-width: 100%;
}
</style>
+26 -3
View File
@@ -1,5 +1,5 @@
<template>
<el-form ref="userRef" :model="userForm" :rules="rules" label-width="80px">
<el-form ref="userRef" :model="userForm" :rules="rules" label-width="80px" class="profile-form">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="userForm.nickName" maxlength="30" />
</el-form-item>
@@ -15,9 +15,9 @@
<el-radio value="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-form-item class="profile-form__actions">
<el-button type="primary" @click="submit">保存</el-button>
<el-button type="danger" @click="close">关闭</el-button>
<el-button @click="close">关闭</el-button>
</el-form-item>
</el-form>
</template>
@@ -67,3 +67,26 @@ const close = () => {
proxy?.$tab.closePage();
};
</script>
<style lang="scss" scoped>
.profile-form {
max-width: 520px;
}
.profile-form :deep(.el-input__wrapper) {
border-radius: 12px;
}
.profile-form :deep(.el-radio-group) {
gap: 16px;
}
.profile-form :deep(.el-button) {
border-radius: 10px;
}
.profile-form__actions :deep(.el-form-item__content) {
display: flex;
gap: 8px;
}
</style>