blog-admin-web/src/views/system/SystemRole.vue
灌糖包子 4dd48489a5
refactor: 统一接口响应格式处理
- 修改 axios 响应拦截器,统一处理包装后的响应格式:
  - code === 0: 返回 data 中的实际数据
  - code === -1: ElMessage.error 提示 message 并 reject
  - 其他情况: 兼容原始响应格式

- 更新各页面数据取值方式:
  - 分页列表: data.data → data.list
  - SystemUser.vue, SystemRole.vue, Article.vue
  - Music.vue, Hitokoto.vue, PhotoWall.vue, SourceImage.vue
  - SystemConfigAdd.vue: data.data.exists → data.exists

- Home.vue: 简化 verifyToken 响应处理
- SystemConfig.vue: 简化 save 响应处理
- SystemRole.vue/SystemUser.vue: 简化 delete 响应处理

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 11:46:15 +08:00

223 lines
7.1 KiB
Vue

<template>
<div class="page-wrapper">
<el-form inline :model="search" @submit.prevent>
<el-form-item label="角色名称/描述">
<el-input v-model="search.name" />
</el-form-item>
</el-form>
<div class="btn-container">
<el-button type="primary" @click="add">添加</el-button>
<div class="search-btn">
<el-button type="primary" @click="loadDataBase(true)" icon="Search">搜索</el-button>
<el-button @click="reset" icon="RefreshLeft">重置</el-button>
</div>
</div>
<div class="table-container">
<el-table :data="systemRoleData" v-loading="loading" stripe>
<el-table-column prop="name" label="角色名称" />
<el-table-column prop="methods" label="允许的请求类型" >
<template #default="scope">
<el-tag type="info" v-for="method in scope.row.methods" :key="method">{{method}}</el-tag>
</template>
</el-table-column>
<el-table-column prop="createdAt" label="创建时间" >
<template #default="scope">
{{ datetimeFormat(scope.row.createdAt) }}
</template>
</el-table-column>
<el-table-column prop="updatedAt" label="更新时间" >
<template #default="scope">
{{ datetimeFormat(scope.row.updatedAt) }}
</template>
</el-table-column>
<el-table-column label="操作" >
<template #default="scope">
<el-button link icon="Edit" @click="update(scope.row)" title="修改"></el-button>
<el-button link type="danger" icon="Delete" @click="remove(scope.row)" title="删除"></el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="page-container">
<el-pagination background
:page-sizes="store.state.pageSizeOpts"
:layout="store.state.pageLayout"
:current-page="search.pageNum"
:total="total"
@size-change="pageSizeChange"
@current-change="pageChange">
</el-pagination>
</div>
<el-dialog v-model="addModal" :title="modalTitle" >
<el-form ref="roleForm" :model="formData" :rules="ruleValidate" :label-width="120">
<el-form-item label="角色名称" prop="name">
<el-input v-model="formData.name" />
</el-form-item>
<el-form-item label="描述">
<el-input v-model="formData.description" />
</el-form-item>
<el-form-item label="允许的请求类型">
<el-select v-model="formData.methods" multiple collapse-tags>
<el-option value="GET">GET</el-option>
<el-option value="POST">POST</el-option>
<el-option value="PUT">PUT</el-option>
<el-option value="DELETE">DELETE</el-option>
</el-select>
</el-form-item>
<el-form-item label="允许的URI">
<el-input v-model="uri.include">
<template #append>
<el-button icon="Plus" @click="addUri('includeUri', uri.include)"></el-button>
</template>
</el-input>
<el-tag v-for="uri in formData.includeUri" :key="uri" closable @close="removeUri('includeUri', uri)">{{uri}}</el-tag>
</el-form-item>
<el-form-item label="禁止的URI">
<el-input v-model="uri.exclude">
<template #append>
<el-button icon="Plus" @click="addUri('excludeUri', uri.exclude)"></el-button>
</template>
</el-input>
<el-tag v-for="uri in formData.excludeUri" :key="uri" closable @close="removeUri('excludeUri', uri)">{{uri}}</el-tag>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="addModal = false">取消</el-button>
<el-button type="primary" @click="save" :loading="modalLoading">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, nextTick } from 'vue'
import { useStore } from 'vuex'
import { useBaseList } from '@/model/baselist'
import { Page } from '@/model/common.dto'
import http from '@/utils/http'
import { SystemRoleModel } from '@/model/system/system-role'
import { ElMessage, ElMessageBox } from 'element-plus'
import { VForm } from '@/types'
const store = useStore()
class SystemRolePage extends Page {
name?: string
reset() {
super.reset()
this.name = undefined
}
}
const { loading, modalLoading, total, search, setLoadData, loadDataBase, reset, pageChange, pageSizeChange, datetimeFormat } = useBaseList(new SystemRolePage())
const ruleValidate = {
name: [
{ required: true, message: '请输入角色名称', trigger: 'blur' }
],
}
const systemRoleData = ref<SystemRoleModel[]>([])
const addModal = ref(false)
const modalTitle = ref<string | null>(null)
const uri = reactive<{
include: string | null,
exclude: string | null
}>({
include: null,
exclude: null
})
const formData = reactive<SystemRoleModel>({
_id: null,
name: null,
description: null,
methods: [],
includeUri: [],
excludeUri: []
})
const roleForm = ref<VForm>()
async function loadData() {
loading.value = true
const data = await http.get<{params: SystemRolePage}, any>('/api/v2/system/role/list', {params: search})
loading.value = false
total.value = data.total
systemRoleData.value = data.list
}
setLoadData(loadData)
function add() {
uri.include = null
uri.exclude = null
Object.assign(formData, {
_id: null,
name: null,
description: null,
methods: [],
includeUri: [],
excludeUri: []
})
modalTitle.value = '新增角色'
addModal.value = true
clearValidate()
}
function addUri(fieldName: 'includeUri' | 'excludeUri', uriValue: string | null) {
if(!uriValue) return
if(formData[fieldName].indexOf(uriValue) === -1) {
formData[fieldName].push(uriValue)
}
}
function removeUri(fieldName: 'includeUri' | 'excludeUri', uriValue: string) {
let index = formData[fieldName].indexOf(uriValue)
if(index !== -1) {
formData[fieldName].splice(index, 1)
}
}
function update(row: SystemRoleModel) {
uri.include = null
uri.exclude = null
Object.assign(formData, {
_id: row._id,
name: row.name,
description: row.description,
methods: row.methods,
includeUri: row.includeUri,
excludeUri: row.excludeUri
})
modalTitle.value = '修改角色'
addModal.value = true
clearValidate()
}
function remove(row: SystemRoleModel) {
ElMessageBox.confirm(`是否确认删除 ${row.name} 角色?`, '确认删除', {type: 'warning'}).then(async () => {
await http.delete<{params: {id: string}}, any>('/api/v2/system/role/delete', {params: {id: row._id}})
ElMessage.success('删除成功')
loadData()
})
}
async function save() {
roleForm.value?.validate(async (valid: boolean) => {
if (!valid) return
modalLoading.value = true
const data = await http.post<SystemRoleModel, any>('/api/v2/system/role/save', formData)
modalLoading.value = false
addModal.value = false
ElMessage.success(data.message)
loadData()
})
}
function clearValidate() {
nextTick(() => {
roleForm.value?.clearValidate()
})
}
loadData()
</script>