refactor: 移除ant-design-vue和tailwindcss依赖并优化样式

style: 统一使用css替换scss并调整组件样式
style: 优化组件布局和属性顺序
chore: 更新.gitignore和.eslintrc配置
This commit is contained in:
张翔
2026-03-13 09:55:05 +08:00
parent 9f8bf041c3
commit 2555bf5f55
17 changed files with 901 additions and 1313 deletions
-678
View File
@@ -19,11 +19,6 @@
--el-color-info-light-9: #a6a9ad;
--el-color-info-light-3: #c8c9cc;
--el-color-info-dark-2: #73767a;
--border-radius-base: 8px;
--border-radius-large: 12px;
--border-radius-small: 4px;
--border-radius-circle: 50%;
}
* {
@@ -37,676 +32,3 @@ body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.el-card {
border-radius: var(--border-radius-base) !important;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}
.el-card:hover {
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.12);
transform: translateY(-2px);
}
.el-button {
border-radius: var(--border-radius-base) !important;
transition: all 0.3s ease;
}
.el-button--primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none;
}
.el-button--primary:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}
.el-input__wrapper {
border-radius: var(--border-radius-base) !important;
transition: all 0.3s ease;
}
.el-input__wrapper:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.el-select .el-input__wrapper {
border-radius: var(--border-radius-base) !important;
}
.el-table {
border-radius: var(--border-radius-base) !important;
overflow: hidden;
}
.el-table th {
background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%);
font-weight: 600;
}
.el-table tr {
transition: all 0.3s ease;
}
.el-table tr:hover {
background-color: #f0f9ff !important;
}
.el-table .el-table__cell {
border-radius: var(--border-radius-small);
}
.el-pagination {
border-radius: var(--border-radius-base) !important;
}
.el-pagination .el-pager li {
border-radius: var(--border-radius-small) !important;
transition: all 0.3s ease;
}
.el-pagination .el-pager li:hover {
transform: scale(1.1);
}
.el-dialog {
border-radius: var(--border-radius-large) !important;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}
.el-dialog__header {
border-radius: var(--border-radius-large) var(--border-radius-large) 0 0 !important;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.el-dialog__body {
padding: 24px;
}
.el-form-item__label {
font-weight: 500;
color: #606266;
}
.el-form-item {
margin-bottom: 20px;
}
.el-menu {
border-radius: var(--border-radius-base) !important;
border: none;
}
.el-menu-item {
border-radius: var(--border-radius-small) !important;
margin: 4px 8px;
transition: all 0.3s ease;
}
.el-menu-item:hover {
background: linear-gradient(135deg, #667eea20 0%, #764ba220 100%);
transform: translateX(4px);
}
.el-menu-item.is-active {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.el-statistic {
border-radius: var(--border-radius-base) !important;
transition: all 0.3s ease;
}
.el-statistic:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}
.el-timeline-item__tail {
border-radius: var(--border-radius-small);
}
.el-timeline-item__node {
border-radius: var(--border-radius-circle) !important;
}
.el-tag {
border-radius: var(--border-radius-small) !important;
padding: 4px 12px;
font-weight: 500;
}
.el-tag--success {
background: linear-gradient(135deg, #67c23a 0%, #5daf34 100%);
border: none;
}
.el-tag--warning {
background: linear-gradient(135deg, #e6a23c 0%, #d93026 100%);
border: none;
}
.el-tag--info {
background: linear-gradient(135deg, #909399 0%, #73767a 100%);
border: none;
}
.el-descriptions {
border-radius: var(--border-radius-base) !important;
}
.el-descriptions__label {
font-weight: 600;
background: #f5f7fa;
}
.el-message-box {
border-radius: var(--border-radius-large) !important;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}
.el-notification {
border-radius: var(--border-radius-base) !important;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.el-drawer {
border-radius: var(--border-radius-large) var(--border-radius-large) 0 0 !important;
}
.el-switch {
border-radius: var(--border-radius-circle) !important;
}
.el-checkbox {
border-radius: var(--border-radius-small) !important;
}
.el-radio {
border-radius: var(--border-radius-small) !important;
}
.el-upload {
border-radius: var(--border-radius-base) !important;
}
.el-upload-dragger {
border-radius: var(--border-radius-base) !important;
border: 2px dashed #dcdfe6;
transition: all 0.3s ease;
}
.el-upload-dragger:hover {
border-color: #667eea;
background: #f0f9ff;
}
.el-progress-bar__inner {
border-radius: var(--border-radius-small) !important;
}
.el-progress-bar {
border-radius: var(--border-radius-base) !important;
}
.el-rate__icon {
border-radius: var(--border-radius-small) !important;
}
.el-slider__runway {
border-radius: var(--border-radius-base) !important;
}
.el-slider__button {
border-radius: var(--border-radius-circle) !important;
}
.el-avatar {
border-radius: var(--border-radius-circle) !important;
}
.el-badge__content {
border-radius: var(--border-radius-circle) !important;
}
.el-breadcrumb {
border-radius: var(--border-radius-base) !important;
padding: 8px 16px;
}
.el-breadcrumb__item {
transition: all 0.3s ease;
}
.el-breadcrumb__item:hover {
color: #667eea;
}
.el-divider {
border-radius: var(--border-radius-small) !important;
}
.el-empty {
border-radius: var(--border-radius-base) !important;
}
.el-result {
border-radius: var(--border-radius-base) !important;
}
.el-alert {
border-radius: var(--border-radius-base) !important;
border: none;
}
.el-alert--success {
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
}
.el-alert--warning {
background: linear-gradient(135deg, #fdf6ec 0%, #fef0f0 100%);
}
.el-alert--error {
background: linear-gradient(135deg, #fef0f0 0%, #fde2e2 100%);
}
.el-alert--info {
background: linear-gradient(135deg, #f4f4f5 0%, #e9e9eb 100%);
}
.el-tabs__item {
border-radius: var(--border-radius-base) var(--border-radius-base) 0 0 !important;
transition: all 0.3s ease;
}
.el-tabs__item:hover {
color: #667eea;
}
.el-tabs__item.is-active {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.el-collapse {
border-radius: var(--border-radius-base) !important;
}
.el-collapse-item__header {
border-radius: var(--border-radius-base) !important;
transition: all 0.3s ease;
}
.el-collapse-item__header:hover {
background: #f5f7fa;
}
.el-popover {
border-radius: var(--border-radius-base) !important;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.el-tooltip__popper {
border-radius: var(--border-radius-base) !important;
}
.el-dropdown-menu {
border-radius: var(--border-radius-base) !important;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.el-dropdown-menu__item {
border-radius: var(--border-radius-small) !important;
transition: all 0.3s ease;
}
.el-dropdown-menu__item:hover {
background: linear-gradient(135deg, #667eea20 0%, #764ba220 100%);
transform: translateX(4px);
}
.el-tree-node__content {
border-radius: var(--border-radius-small) !important;
transition: all 0.3s ease;
}
.el-tree-node__content:hover {
background: #f0f9ff;
}
.el-transfer-panel {
border-radius: var(--border-radius-base) !important;
}
.el-cascader-panel {
border-radius: var(--border-radius-base) !important;
}
.el-color-picker__panel {
border-radius: var(--border-radius-base) !important;
}
.el-date-picker {
border-radius: var(--border-radius-base) !important;
}
.el-picker-panel {
border-radius: var(--border-radius-base) !important;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.el-calendar {
border-radius: var(--border-radius-base) !important;
}
.el-image {
border-radius: var(--border-radius-base) !important;
}
.el-skeleton {
border-radius: var(--border-radius-base) !important;
}
.el-backtop {
border-radius: var(--border-radius-circle) !important;
}
.el-affix {
border-radius: var(--border-radius-base) !important;
}
.el-space {
border-radius: var(--border-radius-base) !important;
}
.el-tour {
border-radius: var(--border-radius-base) !important;
}
.el-segmented {
border-radius: var(--border-radius-base) !important;
}
.el-timeline {
border-radius: var(--border-radius-base) !important;
}
.el-timeline-item {
border-radius: var(--border-radius-base) !important;
}
.el-scrollbar {
border-radius: var(--border-radius-base) !important;
}
.el-main {
border-radius: var(--border-radius-base) !important;
}
.el-header {
border-radius: var(--border-radius-base) !important;
}
.el-footer {
border-radius: var(--border-radius-base) !important;
}
.el-aside {
border-radius: var(--border-radius-base) !important;
}
.el-container {
border-radius: var(--border-radius-base) !important;
}
.el-row {
border-radius: var(--border-radius-base) !important;
}
.el-col {
border-radius: var(--border-radius-base) !important;
}
.el-form {
border-radius: var(--border-radius-base) !important;
}
.el-input-number {
border-radius: var(--border-radius-base) !important;
}
.el-select-dropdown {
border-radius: var(--border-radius-base) !important;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.el-option {
border-radius: var(--border-radius-small) !important;
transition: all 0.3s ease;
}
.el-option:hover {
background: #f0f9ff;
}
.el-option-group {
border-radius: var(--border-radius-base) !important;
}
.el-option-group__title {
border-radius: var(--border-radius-base) var(--border-radius-base) 0 0 !important;
}
.el-checkbox-group {
border-radius: var(--border-radius-base) !important;
}
.el-checkbox-button {
border-radius: var(--border-radius-base) !important;
}
.el-radio-group {
border-radius: var(--border-radius-base) !important;
}
.el-radio-button {
border-radius: var(--border-radius-base) !important;
}
.el-check-tag {
border-radius: var(--border-radius-small) !important;
}
.el-select-v2 {
border-radius: var(--border-radius-base) !important;
}
.el-select-dropdown-v2 {
border-radius: var(--border-radius-base) !important;
}
.el-select-dropdown-v2__item {
border-radius: var(--border-radius-small) !important;
}
.el-select-dropdown-v2__item:hover {
background: #f0f9ff;
}
.el-table-v2 {
border-radius: var(--border-radius-base) !important;
}
.el-table-column {
border-radius: var(--border-radius-base) !important;
}
.el-table-v2__row {
transition: all 0.3s ease;
}
.el-table-v2__row:hover {
background: #f0f9ff !important;
}
.el-page-header {
border-radius: var(--border-radius-base) !important;
}
.el-overlay {
border-radius: var(--border-radius-base) !important;
}
.el-notification__group {
border-radius: var(--border-radius-base) !important;
}
.el-notification__icon {
border-radius: var(--border-radius-circle) !important;
}
.el-notification__content {
border-radius: var(--border-radius-base) !important;
}
.el-notification__closeBtn {
border-radius: var(--border-radius-circle) !important;
}
.el-message {
border-radius: var(--border-radius-base) !important;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.el-message__icon {
border-radius: var(--border-radius-circle) !important;
}
.el-message__content {
border-radius: var(--border-radius-base) !important;
}
.el-message-box__btns {
border-radius: var(--border-radius-base) !important;
}
.el-menu-item-group {
border-radius: var(--border-radius-base) !important;
}
.el-menu-item-group__title {
border-radius: var(--border-radius-base) var(--border-radius-base) 0 0 !important;
}
.el-mention {
border-radius: var(--border-radius-base) !important;
}
.el-loading-spinner {
border-radius: var(--border-radius-circle) !important;
}
.el-link {
border-radius: var(--border-radius-small) !important;
}
.el-input-tag {
border-radius: var(--border-radius-small) !important;
}
.el-infinite-scroll {
border-radius: var(--border-radius-base) !important;
}
.el-image-viewer {
border-radius: var(--border-radius-base) !important;
}
.el-icon {
border-radius: var(--border-radius-small) !important;
}
.el-result__icon {
border-radius: var(--border-radius-circle) !important;
}
.el-result__title {
border-radius: var(--border-radius-base) !important;
}
.el-result__subtitle {
border-radius: var(--border-radius-base) !important;
}
.el-result__extra {
border-radius: var(--border-radius-base) !important;
}
.el-result__content {
border-radius: var(--border-radius-base) !important;
}
.el-descriptions-item {
border-radius: var(--border-radius-base) !important;
}
.el-descriptions-item__label {
border-radius: var(--border-radius-base) var(--border-radius-base) 0 0 !important;
}
.el-descriptions-item__content {
border-radius: var(--border-radius-base) !important;
}
.el-descriptions-item__cell {
border-radius: var(--border-radius-base) !important;
}
.el-date-picker__header {
border-radius: var(--border-radius-base) var(--border-radius-base) 0 0 !important;
}
.el-date-picker__header-label {
border-radius: var(--border-radius-small) !important;
}
.el-date-picker__time-header {
border-radius: var(--border-radius-base) var(--border-radius-base) 0 0 !important;
}
.el-date-picker__time-picker-option {
border-radius: var(--border-radius-small) !important;
}
.el-date-picker__time-picker-option:hover {
background: #f0f9ff;
}
.el-date-picker__time-picker-option.is-selected {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.el-date-picker__time-picker-option.is-disabled {
background: #f5f7fa;
color: #c0c4cc;
}
.el-date-picker__time-picker-option.is-disabled:hover {
background: #f5f7fa;
}
.el-date-picker__time-picker-option.is-disabled.is-selected {
background: #f5f7fa;
color: #c0c4cc;
}
.el-date-picker__time-picker-option.is-disabled.is-selected:hover {
background: #f5f7fa;
}
@@ -1,6 +1,9 @@
<template>
<el-container class="default-layout">
<el-aside :width="collapsed ? '64px' : '200px'" class="aside">
<el-aside
:width="collapsed ? '64px' : '200px'"
class="aside"
>
<div class="logo">
<span v-if="!collapsed">Novalon</span>
<span v-else>N</span>
@@ -9,8 +12,8 @@
:default-active="activeMenu"
class="menu"
:collapse="collapsed"
background-color="#304156"
text-color="#bfcbd9"
background-color="#f5f7fa"
text-color="#606266"
active-text-color="#409eff"
router
>
@@ -23,55 +26,85 @@
<el-icon><Setting /></el-icon>
<span>系统管理</span>
</template>
<el-menu-item index="/users">用户管理</el-menu-item>
<el-menu-item index="/roles">角色管理</el-menu-item>
<el-menu-item index="/menus">菜单管理</el-menu-item>
<el-menu-item index="/users">
用户管理
</el-menu-item>
<el-menu-item index="/roles">
角色管理
</el-menu-item>
<el-menu-item index="/menus">
菜单管理
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="config">
<template #title>
<el-icon><Tools /></el-icon>
<span>系统配置</span>
</template>
<el-menu-item index="/dict">字典管理</el-menu-item>
<el-menu-item index="/sysconfig">参数配置</el-menu-item>
<el-menu-item index="/dict">
字典管理
</el-menu-item>
<el-menu-item index="/sysconfig">
参数配置
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="audit">
<template #title>
<el-icon><Document /></el-icon>
<span>审计中心</span>
</template>
<el-menu-item index="/loginlog">登录日志</el-menu-item>
<el-menu-item index="/oplog">操作日志</el-menu-item>
<el-menu-item index="/loginlog">
登录日志
</el-menu-item>
<el-menu-item index="/oplog">
操作日志
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="notify">
<template #title>
<el-icon><Bell /></el-icon>
<span>通知中心</span>
</template>
<el-menu-item index="/notice">通知公告</el-menu-item>
<el-menu-item index="/notice">
通知公告
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="file">
<template #title>
<el-icon><Folder /></el-icon>
<span>文件管理</span>
</template>
<el-menu-item index="/files">文件列表</el-menu-item>
<el-menu-item index="/files">
文件列表
</el-menu-item>
</el-sub-menu>
</el-menu>
</el-aside>
<el-container>
<el-header class="header">
<el-icon class="trigger" @click="collapsed = !collapsed">
<el-icon
class="trigger"
@click="collapsed = !collapsed"
>
<Fold v-if="!collapsed" />
<Expand v-else />
</el-icon>
<div class="header-right">
<el-dropdown @command="handleCommand">
<el-avatar :size="32">{{ username }}</el-avatar>
<el-avatar :size="32">
{{ username }}
</el-avatar>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="profile">个人中心</el-dropdown-item>
<el-dropdown-item command="logout" divided>退出登录</el-dropdown-item>
<el-dropdown-item command="profile">
个人中心
</el-dropdown-item>
<el-dropdown-item
command="logout"
divided
>
退出登录
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
@@ -114,13 +147,13 @@ onMounted(() => {
})
</script>
<style scoped lang="scss">
<style scoped lang="css">
.default-layout {
min-height: 100vh;
}
.aside {
background-color: #304156;
background-color: #f5f7fa;
transition: width 0.3s;
overflow: hidden;
}
@@ -130,7 +163,7 @@ onMounted(() => {
display: flex;
align-items: center;
justify-content: center;
color: #fff;
color: #303133;
font-size: 20px;
font-weight: bold;
}
+50 -12
View File
@@ -16,17 +16,51 @@
<el-icon><Search /></el-icon>
</template>
</el-input>
<el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button
type="primary"
@click="handleSearch"
>
搜索
</el-button>
</div>
</div>
</template>
<el-table :data="dataSource" v-loading="loading" style="width: 100%" @sort-change="handleSortChange">
<el-table-column prop="id" label="ID" sortable="custom" />
<el-table-column prop="username" label="用户名" sortable="custom" />
<el-table-column prop="ip" label="IP地址" sortable="custom" />
<el-table-column prop="location" label="登录地点" sortable="custom" />
<el-table-column prop="browser" label="浏览器" sortable="custom" />
<el-table-column prop="os" label="操作系统" sortable="custom" />
<el-table
v-loading="loading"
:data="dataSource"
style="width: 100%"
@sort-change="handleSortChange"
>
<el-table-column
prop="id"
label="ID"
sortable="custom"
/>
<el-table-column
prop="username"
label="用户名"
sortable="custom"
/>
<el-table-column
prop="ip"
label="IP地址"
sortable="custom"
/>
<el-table-column
prop="location"
label="登录地点"
sortable="custom"
/>
<el-table-column
prop="browser"
label="浏览器"
sortable="custom"
/>
<el-table-column
prop="os"
label="操作系统"
sortable="custom"
/>
<el-table-column label="状态">
<template #default="{ row }">
<el-tag :type="row.status === '0' ? 'success' : 'danger'">
@@ -34,17 +68,21 @@
</el-tag>
</template>
</el-table-column>
<el-table-column prop="loginTime" label="登录时间" sortable="custom" />
<el-table-column
prop="loginTime"
label="登录时间"
sortable="custom"
/>
</el-table>
<el-pagination
v-model:current-page="pagination.current"
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 50, 100]"
:total="pagination.total"
@current-change="handleTableChange"
@size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper"
style="margin-top: 16px; justify-content: flex-end"
@current-change="handleTableChange"
@size-change="handleSizeChange"
/>
</el-card>
</div>
@@ -111,7 +149,7 @@ const handleSortChange = ({ prop, order }: any) => {
onMounted(() => fetchData())
</script>
<style scoped lang="scss">
<style scoped lang="css">
.login-log {
.card-header {
display: flex;
@@ -16,16 +16,46 @@
<el-icon><Search /></el-icon>
</template>
</el-input>
<el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button
type="primary"
@click="handleSearch"
>
搜索
</el-button>
</div>
</div>
</template>
<el-table :data="dataSource" v-loading="loading" style="width: 100%" @sort-change="handleSortChange">
<el-table-column prop="id" label="ID" sortable="custom" />
<el-table-column prop="username" label="操作人" sortable="custom" />
<el-table-column prop="operation" label="操作模块" sortable="custom" />
<el-table-column prop="method" label="请求方法" sortable="custom" />
<el-table-column prop="params" label="请求参数" :show-overflow-tooltip="true" />
<el-table
v-loading="loading"
:data="dataSource"
style="width: 100%"
@sort-change="handleSortChange"
>
<el-table-column
prop="id"
label="ID"
sortable="custom"
/>
<el-table-column
prop="username"
label="操作人"
sortable="custom"
/>
<el-table-column
prop="operation"
label="操作模块"
sortable="custom"
/>
<el-table-column
prop="method"
label="请求方法"
sortable="custom"
/>
<el-table-column
prop="params"
label="请求参数"
:show-overflow-tooltip="true"
/>
<el-table-column label="状态">
<template #default="{ row }">
<el-tag :type="row.status === '0' ? 'success' : 'danger'">
@@ -33,18 +63,26 @@
</el-tag>
</template>
</el-table-column>
<el-table-column prop="duration" label="耗时(ms)" sortable="custom" />
<el-table-column prop="createdAt" label="操作时间" sortable="custom" />
<el-table-column
prop="duration"
label="耗时(ms)"
sortable="custom"
/>
<el-table-column
prop="createdAt"
label="操作时间"
sortable="custom"
/>
</el-table>
<el-pagination
v-model:current-page="pagination.current"
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 50, 100]"
:total="pagination.total"
@current-change="handleTableChange"
@size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper"
style="margin-top: 16px; justify-content: flex-end"
@current-change="handleTableChange"
@size-change="handleSizeChange"
/>
</el-card>
</div>
@@ -111,7 +149,7 @@ const handleSortChange = ({ prop, order }: any) => {
onMounted(() => fetchData())
</script>
<style scoped lang="scss">
<style scoped lang="css">
.operation-log {
.card-header {
display: flex;
@@ -4,14 +4,35 @@
<template #header>
<div class="card-title">
<span>参数配置</span>
<el-button type="primary" @click="handleAdd">新增配置</el-button>
<el-button
type="primary"
@click="handleAdd"
>
新增配置
</el-button>
</div>
</template>
<el-table :data="dataSource" v-loading="loading" style="width: 100%">
<el-table-column prop="id" label="ID" />
<el-table-column prop="configName" label="参数名称" />
<el-table-column prop="configKey" label="参数键名" />
<el-table-column prop="configValue" label="参数值" />
<el-table
v-loading="loading"
:data="dataSource"
style="width: 100%"
>
<el-table-column
prop="id"
label="ID"
/>
<el-table-column
prop="configName"
label="参数名称"
/>
<el-table-column
prop="configKey"
label="参数键名"
/>
<el-table-column
prop="configValue"
label="参数值"
/>
<el-table-column label="类型">
<template #default="{ row }">
<el-tag :type="row.configType === 'Y' ? '' : 'info'">
@@ -19,17 +40,41 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="150">
<el-table-column
label="操作"
width="150"
>
<template #default="{ row }">
<el-button type="primary" link size="small" @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" link size="small" @click="handleDelete(row)">删除</el-button>
<el-button
type="primary"
link
size="small"
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
type="danger"
link
size="small"
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog v-model="modalVisible" :title="modalTitle" width="500px">
<el-form :model="formState" label-width="80px">
<el-dialog
v-model="modalVisible"
:title="modalTitle"
width="500px"
>
<el-form
:model="formState"
label-width="80px"
>
<el-form-item label="参数名称">
<el-input v-model="formState.configName" />
</el-form-item>
@@ -41,8 +86,15 @@
</el-form-item>
</el-form>
<template #footer>
<el-button @click="modalVisible = false">取消</el-button>
<el-button type="primary" @click="handleModalOk">确定</el-button>
<el-button @click="modalVisible = false">
取消
</el-button>
<el-button
type="primary"
@click="handleModalOk"
>
确定
</el-button>
</template>
</el-dialog>
</div>
@@ -91,7 +143,9 @@ const handleDelete = async (row: any) => {
await request.delete(`/config/${row.id}`)
ElMessage.success('删除成功')
fetchData()
} catch {}
} catch (error) {
console.error('删除配置失败:', error)
}
}
const handleModalOk = async () => {
@@ -112,7 +166,7 @@ const handleModalOk = async () => {
onMounted(() => fetchData())
</script>
<style scoped lang="scss">
<style scoped lang="css">
.config-management .card-title {
display: flex;
justify-content: space-between;
@@ -4,13 +4,31 @@
<template #header>
<div class="card-title">
<span>字典管理</span>
<el-button type="primary" @click="handleAdd">新增字典</el-button>
<el-button
type="primary"
@click="handleAdd"
>
新增字典
</el-button>
</div>
</template>
<el-table :data="dataSource" v-loading="loading" style="width: 100%">
<el-table-column prop="id" label="ID" />
<el-table-column prop="dictName" label="字典名称" />
<el-table-column prop="dictType" label="字典类型" />
<el-table
v-loading="loading"
:data="dataSource"
style="width: 100%"
>
<el-table-column
prop="id"
label="ID"
/>
<el-table-column
prop="dictName"
label="字典名称"
/>
<el-table-column
prop="dictType"
label="字典类型"
/>
<el-table-column label="状态">
<template #default="{ row }">
<el-tag :type="row.status === '0' ? 'success' : 'danger'">
@@ -18,18 +36,45 @@
</el-tag>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" />
<el-table-column label="操作" width="200">
<el-table-column
prop="remark"
label="备注"
/>
<el-table-column
label="操作"
width="200"
>
<template #default="{ row }">
<el-button type="primary" link size="small" @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" link size="small" @click="handleDelete(row)">删除</el-button>
<el-button
type="primary"
link
size="small"
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
type="danger"
link
size="small"
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog v-model="modalVisible" :title="modalTitle" width="500px">
<el-form :model="formState" label-width="80px">
<el-dialog
v-model="modalVisible"
:title="modalTitle"
width="500px"
>
<el-form
:model="formState"
label-width="80px"
>
<el-form-item label="字典名称">
<el-input v-model="formState.dictName" />
</el-form-item>
@@ -38,17 +83,33 @@
</el-form-item>
<el-form-item label="状态">
<el-select v-model="formState.status">
<el-option value="0" label="正常" />
<el-option value="1" label="停用" />
<el-option
value="0"
label="正常"
/>
<el-option
value="1"
label="停用"
/>
</el-select>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="formState.remark" type="textarea" />
<el-input
v-model="formState.remark"
type="textarea"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="modalVisible = false">取消</el-button>
<el-button type="primary" @click="handleModalOk">确定</el-button>
<el-button @click="modalVisible = false">
取消
</el-button>
<el-button
type="primary"
@click="handleModalOk"
>
确定
</el-button>
</template>
</el-dialog>
</div>
@@ -94,10 +155,12 @@ const handleDelete = async (row: any) => {
cancelButtonText: '取消',
type: 'warning'
})
await request.delete(`/dict/types/${row.id}`)
await request.delete(`/dict/${row.id}`)
ElMessage.success('删除成功')
fetchData()
} catch {}
} catch (error) {
console.error('删除字典失败:', error)
}
}
const handleModalOk = async () => {
@@ -118,7 +181,7 @@ const handleModalOk = async () => {
onMounted(() => fetchData())
</script>
<style scoped lang="scss">
<style scoped lang="css">
.dict-management .card-title {
display: flex;
justify-content: space-between;
@@ -4,17 +4,33 @@
<template #header>
<div class="card-title">
<span>文件管理</span>
<el-upload :before-upload="handleUpload" :show-file-list="false">
<el-upload
:before-upload="handleUpload"
:show-file-list="false"
>
<el-button type="primary">
<el-icon><Upload /></el-icon> 上传文件
</el-button>
</el-upload>
</div>
</template>
<el-table :data="dataSource" v-loading="loading" style="width: 100%">
<el-table-column prop="id" label="ID" />
<el-table-column prop="fileName" label="文件名" />
<el-table-column prop="fileSize" label="文件大小" />
<el-table
v-loading="loading"
:data="dataSource"
style="width: 100%"
>
<el-table-column
prop="id"
label="ID"
/>
<el-table-column
prop="fileName"
label="文件名"
/>
<el-table-column
prop="fileSize"
label="文件大小"
/>
<el-table-column label="文件类型">
<template #default="{ row }">
<el-tag :type="getFileTypeTag(row.fileType)">
@@ -22,12 +38,35 @@
</el-tag>
</template>
</el-table-column>
<el-table-column prop="storageType" label="存储方式" />
<el-table-column prop="createdAt" label="上传时间" />
<el-table-column label="操作" width="150">
<el-table-column
prop="storageType"
label="存储方式"
/>
<el-table-column
prop="createdAt"
label="上传时间"
/>
<el-table-column
label="操作"
width="150"
>
<template #default="{ row }">
<el-button type="primary" link size="small" @click="handleDownload(row)">下载</el-button>
<el-button type="danger" link size="small" @click="handleDelete(row)">删除</el-button>
<el-button
type="primary"
link
size="small"
@click="handleDownload(row)"
>
下载
</el-button>
<el-button
type="danger"
link
size="small"
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
@@ -83,7 +122,9 @@ const handleDelete = async (row: any) => {
await request.delete(`/files/${row.id}`)
ElMessage.success('删除成功')
fetchData()
} catch {}
} catch (error) {
console.error('删除文件失败:', error)
}
}
const getFileTypeName = (fileType: string) => {
@@ -111,7 +152,7 @@ const getFileTypeTag = (fileType: string): '' | 'success' | 'warning' | 'danger'
onMounted(() => fetchData())
</script>
<style scoped lang="scss">
<style scoped lang="css">
.file-management .card-title {
display: flex;
justify-content: space-between;
@@ -4,60 +4,131 @@
<template #header>
<div class="card-title">
<span>通知公告</span>
<el-button type="primary" @click="handleAdd">新增公告</el-button>
<el-button
type="primary"
@click="handleAdd"
>
新增公告
</el-button>
</div>
</template>
<el-table :data="dataSource" v-loading="loading" style="width: 100%">
<el-table-column prop="id" label="ID" />
<el-table-column prop="noticeTitle" label="公告标题" />
<el-table-column label="公告类型" width="100">
<el-table
v-loading="loading"
:data="dataSource"
style="width: 100%"
>
<el-table-column
prop="id"
label="ID"
/>
<el-table-column
prop="noticeTitle"
label="公告标题"
/>
<el-table-column
label="公告类型"
width="100"
>
<template #default="{ row }">
<el-tag :type="row.noticeType === '1' ? '' : 'success'">
{{ row.noticeType === '1' ? '通知' : '公告' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="状态" width="80">
<el-table-column
label="状态"
width="80"
>
<template #default="{ row }">
<el-tag :type="row.status === '0' ? 'success' : 'danger'">
{{ row.status === '0' ? '正常' : '停用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createdAt" label="发布时间" />
<el-table-column label="操作" width="150">
<el-table-column
prop="createdAt"
label="发布时间"
/>
<el-table-column
label="操作"
width="150"
>
<template #default="{ row }">
<el-button type="primary" link size="small" @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" link size="small" @click="handleDelete(row)">删除</el-button>
<el-button
type="primary"
link
size="small"
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
type="danger"
link
size="small"
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog v-model="modalVisible" :title="modalTitle" width="500px">
<el-form :model="formState" label-width="80px">
<el-dialog
v-model="modalVisible"
:title="modalTitle"
width="500px"
>
<el-form
:model="formState"
label-width="80px"
>
<el-form-item label="公告标题">
<el-input v-model="formState.noticeTitle" />
</el-form-item>
<el-form-item label="公告类型">
<el-select v-model="formState.noticeType">
<el-option value="1" label="通知" />
<el-option value="2" label="公告" />
<el-option
value="1"
label="通知"
/>
<el-option
value="2"
label="公告"
/>
</el-select>
</el-form-item>
<el-form-item label="公告内容">
<el-input v-model="formState.noticeContent" type="textarea" :rows="4" />
<el-input
v-model="formState.noticeContent"
type="textarea"
:rows="4"
/>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="formState.status">
<el-option value="0" label="正常" />
<el-option value="1" label="停用" />
<el-option
value="0"
label="正常"
/>
<el-option
value="1"
label="停用"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="modalVisible = false">取消</el-button>
<el-button type="primary" @click="handleModalOk">确定</el-button>
<el-button @click="modalVisible = false">
取消
</el-button>
<el-button
type="primary"
@click="handleModalOk"
>
确定
</el-button>
</template>
</el-dialog>
</div>
@@ -103,10 +174,12 @@ const handleDelete = async (row: any) => {
cancelButtonText: '取消',
type: 'warning'
})
await request.delete(`/notices/${row.id}`)
await request.delete(`/notice/${row.id}`)
ElMessage.success('删除成功')
fetchData()
} catch {}
} catch (error) {
console.error('删除通知失败:', error)
}
}
const handleModalOk = async () => {
@@ -127,7 +200,7 @@ const handleModalOk = async () => {
onMounted(() => fetchData())
</script>
<style scoped lang="scss">
<style scoped lang="css">
.notice-management .card-title {
display: flex;
justify-content: space-between;
@@ -3,7 +3,10 @@
<el-row :gutter="16">
<el-col :span="6">
<el-card v-loading="loading">
<el-statistic title="用户总数" :value="stats.userCount">
<el-statistic
title="用户总数"
:value="stats.userCount"
>
<template #prefix>
<el-icon><User /></el-icon>
</template>
@@ -12,7 +15,10 @@
</el-col>
<el-col :span="6">
<el-card v-loading="loading">
<el-statistic title="角色总数" :value="stats.roleCount">
<el-statistic
title="角色总数"
:value="stats.roleCount"
>
<template #prefix>
<el-icon><UserFilled /></el-icon>
</template>
@@ -21,7 +27,10 @@
</el-col>
<el-col :span="6">
<el-card v-loading="loading">
<el-statistic title="今日登录" :value="stats.todayLogin">
<el-statistic
title="今日登录"
:value="stats.todayLogin"
>
<template #prefix>
<el-icon><ArrowRight /></el-icon>
</template>
@@ -30,7 +39,10 @@
</el-col>
<el-col :span="6">
<el-card v-loading="loading">
<el-statistic title="操作日志" :value="stats.operationLog">
<el-statistic
title="操作日志"
:value="stats.operationLog"
>
<template #prefix>
<el-icon><Document /></el-icon>
</template>
@@ -38,9 +50,15 @@
</el-card>
</el-col>
</el-row>
<el-row :gutter="16" style="margin-top: 16px">
<el-row
:gutter="16"
style="margin-top: 16px"
>
<el-col :span="12">
<el-card title="最近登录" v-loading="loading">
<el-card
v-loading="loading"
title="最近登录"
>
<el-timeline>
<el-timeline-item
v-for="item in recentLogins"
@@ -54,12 +72,26 @@
</el-card>
</el-col>
<el-col :span="12">
<el-card title="系统信息" v-loading="loading">
<el-descriptions :column="1" border>
<el-descriptions-item label="系统版本">{{ systemInfo.version }}</el-descriptions-item>
<el-descriptions-item label="Java版本">{{ systemInfo.javaVersion }}</el-descriptions-item>
<el-descriptions-item label="前端框架">{{ systemInfo.frontendFramework }}</el-descriptions-item>
<el-descriptions-item label="数据库">{{ systemInfo.database }}</el-descriptions-item>
<el-card
v-loading="loading"
title="系统信息"
>
<el-descriptions
:column="1"
border
>
<el-descriptions-item label="系统版本">
{{ systemInfo.version }}
</el-descriptions-item>
<el-descriptions-item label="Java版本">
{{ systemInfo.javaVersion }}
</el-descriptions-item>
<el-descriptions-item label="前端框架">
{{ systemInfo.frontendFramework }}
</el-descriptions-item>
<el-descriptions-item label="数据库">
{{ systemInfo.database }}
</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
@@ -127,7 +159,7 @@ onMounted(() => {
})
</script>
<style scoped lang="scss">
<style scoped lang="css">
.dashboard {
padding: 16px;
}
+19 -6
View File
@@ -6,25 +6,38 @@
</template>
<el-form
:model="formState"
@submit.prevent="onFinish"
label-position="top"
@submit.prevent="onFinish"
>
<el-form-item
label="用户名"
prop="username"
:rules="[{ required: true, message: '请输入用户名', trigger: 'blur' }]"
>
<el-input v-model="formState.username" placeholder="请输入用户名" />
<el-input
v-model="formState.username"
placeholder="请输入用户名"
/>
</el-form-item>
<el-form-item
label="密码"
prop="password"
:rules="[{ required: true, message: '请输入密码', trigger: 'blur' }]"
>
<el-input v-model="formState.password" type="password" placeholder="请输入密码" show-password />
<el-input
v-model="formState.password"
type="password"
placeholder="请输入密码"
show-password
/>
</el-form-item>
<el-form-item>
<el-button type="primary" native-type="submit" :loading="loading" style="width: 100%">
<el-button
type="primary"
native-type="submit"
:loading="loading"
style="width: 100%"
>
登录
</el-button>
</el-form-item>
@@ -63,13 +76,13 @@ const onFinish = async () => {
}
</script>
<style scoped lang="scss">
<style scoped lang="css">
.login-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
background: var(--el-color-primary-light-9);
.login-card {
width: 400px;
@@ -4,56 +4,131 @@
<template #header>
<div class="card-title">
<span>菜单管理</span>
<el-button type="primary" @click="handleAdd">新增菜单</el-button>
<el-button
type="primary"
@click="handleAdd"
>
新增菜单
</el-button>
</div>
</template>
<el-table :data="dataSource" v-loading="loading" :pagination="false" row-key="id" style="width: 100%">
<el-table-column prop="menuName" label="菜单名称" />
<el-table-column label="菜单类型" width="100">
<el-table
v-loading="loading"
:data="dataSource"
:pagination="false"
row-key="id"
style="width: 100%"
>
<el-table-column
prop="menuName"
label="菜单名称"
/>
<el-table-column
label="菜单类型"
width="100"
>
<template #default="{ row }">
<el-tag :type="row.menuType === 'M' ? '' : row.menuType === 'C' ? 'success' : 'warning'">
{{ row.menuType === 'M' ? '目录' : row.menuType === 'C' ? '菜单' : '按钮' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="perms" label="权限标识" />
<el-table-column prop="component" label="组件" />
<el-table-column prop="orderNum" label="排序" width="80" />
<el-table-column label="状态" width="80">
<el-table-column
prop="perms"
label="权限标识"
/>
<el-table-column
prop="component"
label="组件"
/>
<el-table-column
prop="orderNum"
label="排序"
width="80"
/>
<el-table-column
label="状态"
width="80"
>
<template #default="{ row }">
<el-tag :type="row.status === '0' ? 'success' : 'danger'">
{{ row.status === '0' ? '显示' : '隐藏' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="150">
<el-table-column
label="操作"
width="150"
>
<template #default="{ row }">
<el-button type="primary" link size="small" @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" link size="small" @click="handleDelete(row)">删除</el-button>
<el-button
type="primary"
link
size="small"
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
type="danger"
link
size="small"
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog v-model="modalVisible" :title="modalTitle" width="500px">
<el-form :model="formState" label-width="100px">
<el-dialog
v-model="modalVisible"
:title="modalTitle"
width="500px"
>
<el-form
:model="formState"
label-width="100px"
>
<el-form-item label="菜单名称">
<el-input v-model="formState.menuName" />
</el-form-item>
<el-form-item label="父级菜单">
<el-tree-select v-model="formState.parentId" :data="menuTree" placeholder="请选择父级菜单" clearable check-strictly />
<el-tree-select
v-model="formState.parentId"
:data="menuTree"
placeholder="请选择父级菜单"
clearable
check-strictly
/>
</el-form-item>
<el-form-item label="菜单类型">
<el-select v-model="formState.menuType">
<el-option value="M" label="目录" />
<el-option value="C" label="菜单" />
<el-option value="F" label="按钮" />
<el-option
value="M"
label="目录"
/>
<el-option
value="C"
label="菜单"
/>
<el-option
value="F"
label="按钮"
/>
</el-select>
</el-form-item>
<el-form-item label="路由地址" v-if="formState.menuType !== 'F'">
<el-form-item
v-if="formState.menuType !== 'F'"
label="路由地址"
>
<el-input v-model="formState.perms" />
</el-form-item>
<el-form-item label="组件路径" v-if="formState.menuType === 'C'">
<el-form-item
v-if="formState.menuType === 'C'"
label="组件路径"
>
<el-input v-model="formState.component" />
</el-form-item>
<el-form-item label="排序">
@@ -61,14 +136,27 @@
</el-form-item>
<el-form-item label="状态">
<el-select v-model="formState.status">
<el-option value="0" label="显示" />
<el-option value="1" label="隐藏" />
<el-option
value="0"
label="显示"
/>
<el-option
value="1"
label="隐藏"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="modalVisible = false">取消</el-button>
<el-button type="primary" @click="handleModalOk">确定</el-button>
<el-button @click="modalVisible = false">
取消
</el-button>
<el-button
type="primary"
@click="handleModalOk"
>
确定
</el-button>
</template>
</el-dialog>
</div>
@@ -125,7 +213,9 @@ const handleDelete = async (row: any) => {
await request.delete(`/menus/${row.id}`)
ElMessage.success('删除成功')
fetchData()
} catch {}
} catch (error) {
console.error('删除菜单失败:', error)
}
}
const handleModalOk = async () => {
@@ -146,7 +236,7 @@ const handleModalOk = async () => {
onMounted(() => fetchData())
</script>
<style scoped lang="scss">
<style scoped lang="css">
.menu-management .card-title {
display: flex;
justify-content: space-between;
@@ -16,16 +16,47 @@
<el-icon><Search /></el-icon>
</template>
</el-input>
<el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button
type="primary"
@click="handleSearch"
>
搜索
</el-button>
</div>
<el-button type="primary" @click="handleAdd">新增角色</el-button>
<el-button
type="primary"
@click="handleAdd"
>
新增角色
</el-button>
</div>
</template>
<el-table :data="dataSource" v-loading="loading" style="width: 100%" @sort-change="handleSortChange">
<el-table-column prop="id" label="ID" sortable="custom" />
<el-table-column prop="roleName" label="角色名称" sortable="custom" />
<el-table-column prop="roleKey" label="角色标识" sortable="custom" />
<el-table-column prop="roleSort" label="排序" sortable="custom" />
<el-table
v-loading="loading"
:data="dataSource"
style="width: 100%"
@sort-change="handleSortChange"
>
<el-table-column
prop="id"
label="ID"
sortable="custom"
/>
<el-table-column
prop="roleName"
label="角色名称"
sortable="custom"
/>
<el-table-column
prop="roleKey"
label="角色标识"
sortable="custom"
/>
<el-table-column
prop="roleSort"
label="排序"
sortable="custom"
/>
<el-table-column label="状态">
<template #default="{ row }">
<el-tag :type="row.status === '0' ? 'success' : 'danger'">
@@ -33,11 +64,30 @@
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createdAt" label="创建时间" sortable="custom" />
<el-table-column label="操作" width="200">
<el-table-column
prop="createdAt"
label="创建时间"
sortable="custom"
/>
<el-table-column
label="操作"
width="200"
>
<template #default="{ row }">
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
<el-button
type="primary"
link
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
type="danger"
link
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
@@ -46,15 +96,22 @@
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 50, 100]"
:total="pagination.total"
@current-change="handleTableChange"
@size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper"
style="margin-top: 16px; justify-content: flex-end"
@current-change="handleTableChange"
@size-change="handleSizeChange"
/>
</el-card>
<el-dialog v-model="modalVisible" :title="modalTitle" width="500px">
<el-form :model="formState" label-width="80px">
<el-dialog
v-model="modalVisible"
:title="modalTitle"
width="500px"
>
<el-form
:model="formState"
label-width="80px"
>
<el-form-item label="角色名称">
<el-input v-model="formState.roleName" />
</el-form-item>
@@ -66,14 +123,27 @@
</el-form-item>
<el-form-item label="状态">
<el-select v-model="formState.status">
<el-option value="0" label="正常" />
<el-option value="1" label="禁用" />
<el-option
value="0"
label="正常"
/>
<el-option
value="1"
label="禁用"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="modalVisible = false">取消</el-button>
<el-button type="primary" @click="handleModalOk">确定</el-button>
<el-button @click="modalVisible = false">
取消
</el-button>
<el-button
type="primary"
@click="handleModalOk"
>
确定
</el-button>
</template>
</el-dialog>
</div>
@@ -164,7 +234,9 @@ const handleDelete = async (row: any) => {
await request.delete(`/roles/${row.id}`)
ElMessage.success('删除成功')
fetchData()
} catch {}
} catch (error) {
console.error('删除角色失败:', error)
}
}
const handleModalOk = async () => {
@@ -185,7 +257,7 @@ const handleModalOk = async () => {
onMounted(() => fetchData())
</script>
<style scoped lang="scss">
<style scoped lang="css">
.role-management {
.card-header {
display: flex;
@@ -16,33 +16,82 @@
<el-icon><Search /></el-icon>
</template>
</el-input>
<el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button
type="primary"
@click="handleSearch"
>
搜索
</el-button>
</div>
<el-button type="primary" @click="handleAdd">新增用户</el-button>
<el-button
type="primary"
@click="handleAdd"
>
新增用户
</el-button>
</div>
</template>
<el-table
:data="dataSource"
v-loading="loading"
:data="dataSource"
style="width: 100%"
@sort-change="handleSortChange"
>
<el-table-column prop="id" label="ID" width="80" sortable="custom" />
<el-table-column prop="username" label="用户名" sortable="custom" />
<el-table-column prop="email" label="邮箱" sortable="custom" />
<el-table-column prop="phone" label="手机号" sortable="custom" />
<el-table-column label="状态" width="100">
<el-table-column
prop="id"
label="ID"
width="80"
sortable="custom"
/>
<el-table-column
prop="username"
label="用户名"
sortable="custom"
/>
<el-table-column
prop="email"
label="邮箱"
sortable="custom"
/>
<el-table-column
prop="phone"
label="手机号"
sortable="custom"
/>
<el-table-column
label="状态"
width="100"
>
<template #default="{ row }">
<el-tag :type="row.status === '0' ? 'success' : 'danger'">
{{ row.status === '0' ? '正常' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createdAt" label="创建时间" sortable="custom" />
<el-table-column label="操作" width="200">
<el-table-column
prop="createdAt"
label="创建时间"
sortable="custom"
/>
<el-table-column
label="操作"
width="200"
>
<template #default="{ row }">
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
<el-button
type="primary"
link
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
type="danger"
link
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
@@ -51,10 +100,10 @@
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 50, 100]"
:total="pagination.total"
@current-change="handleTableChange"
@size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper"
style="margin-top: 16px; justify-content: flex-end"
@current-change="handleTableChange"
@size-change="handleSizeChange"
/>
</el-card>
@@ -78,14 +127,27 @@
</el-form-item>
<el-form-item label="状态">
<el-select v-model="formState.status">
<el-option value="0" label="正常" />
<el-option value="1" label="禁用" />
<el-option
value="0"
label="正常"
/>
<el-option
value="1"
label="禁用"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleModalCancel">取消</el-button>
<el-button type="primary" @click="handleModalOk">确定</el-button>
<el-button @click="handleModalCancel">
取消
</el-button>
<el-button
type="primary"
@click="handleModalOk"
>
确定
</el-button>
</template>
</el-dialog>
</div>
@@ -212,7 +274,7 @@ onMounted(() => {
})
</script>
<style scoped lang="scss">
<style scoped lang="css">
.user-management {
.card-header {
display: flex;