fetch(modify):修复API的URL
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 5m1s

This commit is contained in:
sexygoat
2026-02-03 10:04:59 +08:00
parent 06cde977ad
commit 2c6fe4375b
17 changed files with 225 additions and 205 deletions

View File

@@ -9,7 +9,7 @@
import zh from 'element-plus/es/locale/lang/zh-cn' import zh from 'element-plus/es/locale/lang/zh-cn'
import en from 'element-plus/es/locale/lang/en' import en from 'element-plus/es/locale/lang/en'
import { systemUpgrade } from '@/utils' import { systemUpgrade } from '@/utils'
import { UserService } from './api/usersApi' import { AuthService } from '@/api/modules'
import { ApiStatus } from './utils/http/status' import { ApiStatus } from './utils/http/status'
import { setThemeTransitionClass } from '@/utils' import { setThemeTransitionClass } from '@/utils'
import { checkStorageCompatibility } from '@/utils' import { checkStorageCompatibility } from '@/utils'
@@ -41,7 +41,7 @@
const getUserInfo = async () => { const getUserInfo = async () => {
if (userStore.isLogin && userStore.accessToken) { if (userStore.isLogin && userStore.accessToken) {
try { try {
const res = await UserService.getUserInfo() const res = await AuthService.getUserInfo()
if (res.code === ApiStatus.success && res.data) { if (res.code === ApiStatus.success && res.data) {
// API 返回的是 { user, permissions },我们需要保存 user 和 permissions // API 返回的是 { user, permissions },我们需要保存 user 和 permissions
userStore.setUserInfo(res.data.user) userStore.setUserInfo(res.data.user)

View File

@@ -1,54 +0,0 @@
/**
* 认证相关 API
*/
import request from '@/utils/http'
import {
BaseResponse,
LoginParams,
LoginData,
UserInfoResponse,
RefreshTokenData
} from '@/types/api'
export class AuthService {
/**
* 用户登录
* @param params 登录参数
*/
static login(params: LoginParams): Promise<BaseResponse<LoginData>> {
return request.post<BaseResponse<LoginData>>({
url: '/api/admin/login',
data: params
})
}
/**
* 获取用户信息
* GET /api/admin/me
*/
static getUserInfo(): Promise<BaseResponse<UserInfoResponse>> {
return request.get<BaseResponse<UserInfoResponse>>({
url: '/api/admin/me'
})
}
/**
* 用户登出
*/
static logout(): Promise<BaseResponse<void>> {
return request.post<BaseResponse<void>>({
url: '/api/admin/logout'
})
}
/**
* 刷新 Token
* @param refreshToken 刷新令牌
*/
static refreshToken(refreshToken: string): Promise<BaseResponse<RefreshTokenData>> {
return request.post<BaseResponse<RefreshTokenData>>({
url: '/api/auth/refresh',
data: { refreshToken }
})
}
}

View File

@@ -92,4 +92,24 @@ export class AccountService extends BaseService {
static removeRoleFromAccount(accountId: number, roleId: number): Promise<BaseResponse> { static removeRoleFromAccount(accountId: number, roleId: number): Promise<BaseResponse> {
return this.delete<BaseResponse>(`/api/admin/accounts/${accountId}/roles/${roleId}`) return this.delete<BaseResponse>(`/api/admin/accounts/${accountId}/roles/${roleId}`)
} }
/**
* 修改账号密码
* PUT /api/admin/accounts/{id}/password
* @param id 账号ID
* @param password 新密码
*/
static updateAccountPassword(id: number, password: string): Promise<BaseResponse> {
return this.put<BaseResponse>(`/api/admin/accounts/${id}/password`, { password })
}
/**
* 修改账号状态
* PUT /api/admin/accounts/{id}/status
* @param id 账号ID
* @param status 状态 (0:禁用, 1:启用)
*/
static updateAccountStatus(id: number, status: 0 | 1): Promise<BaseResponse> {
return this.put<BaseResponse>(`/api/admin/accounts/${id}/status`, { status })
}
} }

View File

@@ -16,42 +16,42 @@ import type {
export class AuthService extends BaseService { export class AuthService extends BaseService {
/** /**
* 用户登录 * 用户登录(统一认证接口)
* @param params 登录参数 * @param params 登录参数
*/ */
static login(params: LoginParams): Promise<BaseResponse<LoginData>> { static login(params: LoginParams): Promise<BaseResponse<LoginData>> {
return this.post<BaseResponse<LoginData>>('/api/admin/login', params) return this.post<BaseResponse<LoginData>>('/api/auth/login', params)
} }
/** /**
* 退出登录 * 退出登录(统一认证接口)
*/ */
static logout(): Promise<BaseResponse> { static logout(): Promise<BaseResponse> {
return this.post<BaseResponse>('/api/admin/logout') return this.post<BaseResponse>('/api/auth/logout')
} }
/** /**
* 获取当前用户信息 * 获取当前用户信息(统一认证接口)
* GET /api/admin/me * GET /api/auth/me
*/ */
static getUserInfo(): Promise<BaseResponse<UserInfoResponse>> { static getUserInfo(): Promise<BaseResponse<UserInfoResponse>> {
return this.get<BaseResponse<UserInfoResponse>>('/api/admin/me') return this.get<BaseResponse<UserInfoResponse>>('/api/auth/me')
} }
/** /**
* 刷新 Token * 刷新 Token(统一认证接口)
* @param params 刷新参数 * @param params 刷新参数
*/ */
static refreshToken(params: RefreshTokenParams): Promise<BaseResponse<RefreshTokenData>> { static refreshToken(params: RefreshTokenParams): Promise<BaseResponse<RefreshTokenData>> {
return this.post<BaseResponse<RefreshTokenData>>('/api/auth/refresh', params) return this.post<BaseResponse<RefreshTokenData>>('/api/auth/refresh-token', params)
} }
/** /**
* 修改密码 * 修改密码(统一认证接口)
* @param params 修改密码参数 * @param params 修改密码参数
*/ */
static changePassword(params: ChangePasswordParams): Promise<BaseResponse> { static changePassword(params: ChangePasswordParams): Promise<BaseResponse> {
return this.post<BaseResponse>('/api/auth/change-password', params) return this.put<BaseResponse>('/api/auth/password', params)
} }
/** /**

View File

@@ -1,5 +1,14 @@
/** /**
* 客户账号管理 API * 客户账号管理 API (企业账号)
*
* @deprecated 此 API 已废弃,请使用统一的 AccountService 代替
* @see AccountService - 统一账号管理接口 (/api/admin/accounts)
*
* 迁移说明:
* - 所有账号类型统一使用 /api/admin/accounts 接口
* - 通过 user_type 参数区分账号类型 (2=平台, 3=代理, 4=企业)
* - customer-accounts 已改名为 enterprise企业账号
* - 详见docs/迁移指南.md
*/ */
import { BaseService } from '../BaseService' import { BaseService } from '../BaseService'

View File

@@ -1,5 +1,13 @@
/** /**
* 平台账号相关 API - 匹配后端实际接口 * 平台账号相关 API - 匹配后端实际接口
*
* @deprecated 此 API 已废弃,请使用统一的 AccountService 代替
* @see AccountService - 统一账号管理接口 (/api/admin/accounts)
*
* 迁移说明:
* - 所有账号类型统一使用 /api/admin/accounts 接口
* - 通过 user_type 参数区分账号类型 (2=平台, 3=代理, 4=企业)
* - 详见docs/迁移指南.md
*/ */
import { BaseService } from '../BaseService' import { BaseService } from '../BaseService'

View File

@@ -1,5 +1,13 @@
/** /**
* 代理账号相关 API - 匹配后端实际接口 * 代理账号相关 API - 匹配后端实际接口
*
* @deprecated 此 API 已废弃,请使用统一的 AccountService 代替
* @see AccountService - 统一账号管理接口 (/api/admin/accounts)
*
* 迁移说明:
* - 所有账号类型统一使用 /api/admin/accounts 接口
* - 通过 user_type 参数区分账号类型 (2=平台, 3=代理, 4=企业)
* - 详见docs/迁移指南.md
*/ */
import { BaseService } from '../BaseService' import { BaseService } from '../BaseService'

View File

@@ -1,39 +0,0 @@
import request from '@/utils/http'
import { BaseResponse, UserInfoResponse } from '@/types/api'
interface LoginParams {
username: string
password: string
device?: string
}
interface UserListParams {
current?: number
size?: number
}
export class UserService {
// 登录
static login(params: LoginParams) {
return request.post<BaseResponse>({
url: '/api/admin/login',
params
})
}
// 获取用户信息
// GET /api/admin/me
static getUserInfo() {
return request.get<BaseResponse<UserInfoResponse>>({
url: '/api/admin/me'
})
}
// 获取用户列表
static getUserList(params?: UserListParams) {
return request.get<BaseResponse>({
url: '/api/user/list',
params
})
}
}

View File

@@ -12,7 +12,7 @@
<!-- 表格 --> <!-- 表格 -->
<ArtTable <ArtTable
ref="tableRef" ref="tableRef"
row-key="id" row-key="ID"
:loading="loading" :loading="loading"
:data="accountList" :data="accountList"
height="60vh" height="60vh"
@@ -24,7 +24,7 @@
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
> >
<template #default> <template #default>
<ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" /> <ElTableColumn v-for="col in columns" :key="col.prop || (col as any).type" v-bind="col" />
</template> </template>
</ArtTable> </ArtTable>
</ElDialog> </ElDialog>
@@ -33,23 +33,25 @@
<script setup lang="ts"> <script setup lang="ts">
import { h } from 'vue' import { h } from 'vue'
import { ElMessage, ElTag } from 'element-plus' import { ElMessage, ElTag } from 'element-plus'
import { CustomerAccountService } from '@/api/modules' import { AccountService } from '@/api/modules'
import type { SearchFormItem } from '@/types' import type { SearchFormItem } from '@/types'
import type { PlatformAccount } from '@/types/api'
import { formatDateTime } from '@/utils/business/format' import { formatDateTime } from '@/utils/business/format'
interface CustomerAccount { // 用户类型映射
id: number const getUserTypeName = (type: number): string => {
username: string const typeMap: Record<number, string> = {
phone: string 1: '超级管理员',
user_type: number 2: '平台用户',
user_type_name: string 3: '代理账号',
shop_id: number | null 4: '企业账号'
shop_name: string }
enterprise_id: number | null return typeMap[type] || '未知'
enterprise_name: string }
status: number
status_name: string // 状态名称映射
created_at: string const getStatusName = (status: number): string => {
return status === 1 ? '启用' : '禁用'
} }
const props = defineProps<{ const props = defineProps<{
@@ -69,7 +71,7 @@
const loading = ref(false) const loading = ref(false)
const tableRef = ref() const tableRef = ref()
const accountList = ref<CustomerAccount[]>([]) const accountList = ref<PlatformAccount[]>([])
// 搜索表单初始值 // 搜索表单初始值
const initialSearchState = { const initialSearchState = {
@@ -160,40 +162,38 @@
width: 130 width: 130
}, },
{ {
prop: 'user_type_name', prop: 'user_type',
label: '用户类型', label: '用户类型',
width: 110, width: 110,
formatter: (row: CustomerAccount) => { formatter: (row: PlatformAccount) => {
return h(ElTag, { type: getUserTypeTag(row.user_type) }, () => row.user_type_name) return h(ElTag, { type: getUserTypeTag(row.user_type) }, () => getUserTypeName(row.user_type))
} }
}, },
{ {
prop: 'shop_name', prop: 'shop_id',
label: '店铺名称', label: '店铺ID',
minWidth: 150, width: 100,
showOverflowTooltip: true, formatter: (row: PlatformAccount) => row.shop_id || '-'
formatter: (row: CustomerAccount) => row.shop_name || '-'
}, },
{ {
prop: 'enterprise_name', prop: 'enterprise_id',
label: '企业名称', label: '企业ID',
minWidth: 150, width: 100,
showOverflowTooltip: true, formatter: (row: PlatformAccount) => row.enterprise_id || '-'
formatter: (row: CustomerAccount) => row.enterprise_name || '-'
}, },
{ {
prop: 'status', prop: 'status',
label: '状态', label: '状态',
width: 100, width: 100,
formatter: (row: CustomerAccount) => { formatter: (row: PlatformAccount) => {
return h(ElTag, { type: getStatusTag(row.status) }, () => row.status_name) return h(ElTag, { type: getStatusTag(row.status) }, () => getStatusName(row.status))
} }
}, },
{ {
prop: 'created_at', prop: 'CreatedAt',
label: '创建时间', label: '创建时间',
width: 180, width: 180,
formatter: (row: CustomerAccount) => formatDateTime(row.created_at) formatter: (row: PlatformAccount) => formatDateTime(row.CreatedAt)
} }
]) ])
@@ -213,7 +213,7 @@
try { try {
const params: any = { const params: any = {
page: pagination.page, page: pagination.page,
page_size: pagination.pageSize, pageSize: pagination.pageSize,
username: searchForm.username || undefined, username: searchForm.username || undefined,
phone: searchForm.phone || undefined, phone: searchForm.phone || undefined,
user_type: searchForm.user_type, user_type: searchForm.user_type,
@@ -235,7 +235,7 @@
} }
}) })
const res = await CustomerAccountService.getCustomerAccounts(params) const res = await AccountService.getAccounts(params)
if (res.code === 0) { if (res.code === 0) {
accountList.value = res.data.items || [] accountList.value = res.data.items || []
pagination.total = res.data.total || 0 pagination.total = res.data.total || 0

View File

@@ -10,7 +10,7 @@ import type { FormInstance, FormRules } from 'element-plus'
import { useUserStore } from '@/store/modules/user' import { useUserStore } from '@/store/modules/user'
import { HOME_PAGE } from '@/router/routesAlias' import { HOME_PAGE } from '@/router/routesAlias'
import AppConfig from '@/config' import AppConfig from '@/config'
import { AuthService } from '@/api/authApi' import { AuthService } from '@/api/modules'
import { ApiStatus } from '@/utils/http/status' import { ApiStatus } from '@/utils/http/status'
import { MOCK_ACCOUNTS, mockLogin, mockGetUserInfo, type MockAccount } from '@/mock/auth' import { MOCK_ACCOUNTS, mockLogin, mockGetUserInfo, type MockAccount } from '@/mock/auth'
import { saveCredentials, getRememberedCredentials } from '@/utils/auth/rememberPassword' import { saveCredentials, getRememberedCredentials } from '@/utils/auth/rememberPassword'

View File

@@ -317,6 +317,7 @@ function buildRouteMap(routes: AppRouteRecord[], parentPath = ''): Map<string, A
/** /**
* 将后端菜单数据转换为路由格式 * 将后端菜单数据转换为路由格式
* 递归处理所有层级的 children
*/ */
function convertBackendMenuToRoute( function convertBackendMenuToRoute(
menu: any, menu: any,
@@ -328,6 +329,32 @@ function convertBackendMenuToRoute(
if (!matchedRoute) { if (!matchedRoute) {
console.warn(`未找到与菜单 URL "${menuUrl}" 匹配的路由定义: ${menu.name}`) console.warn(`未找到与菜单 URL "${menuUrl}" 匹配的路由定义: ${menu.name}`)
// 如果当前菜单没有匹配的路由,但有 children尝试递归处理 children
if (menu.children && menu.children.length > 0) {
const children = menu.children
.map((child: any) => convertBackendMenuToRoute(child, routeMap, menuUrl))
.filter((child: AppRouteRecord | null) => child !== null)
// 如果子菜单有有效的路由,返回一个包含子菜单的占位路由
if (children.length > 0) {
return {
path: menuUrl,
name: menu.name || menuUrl.replace(/\//g, '_'),
meta: {
title: menu.name,
permission: menu.perm_code,
sort: menu.sort || 0,
icon: menu.icon,
isHide: false,
roles: undefined,
permissions: undefined
},
children: children
} as AppRouteRecord
}
}
return null return null
} }
@@ -347,6 +374,7 @@ function convertBackendMenuToRoute(
} }
} }
// 递归处理所有层级的 children
if (menu.children && menu.children.length > 0) { if (menu.children && menu.children.length > 0) {
const children = menu.children const children = menu.children
.map((child: any) => convertBackendMenuToRoute(child, routeMap, menuUrl)) .map((child: any) => convertBackendMenuToRoute(child, routeMap, menuUrl))

View File

@@ -45,6 +45,7 @@ export interface PermissionTreeNode {
url?: string // 请求路径 url?: string // 请求路径
platform?: string // 适用端口 (all:全部, web:Web后台, h5:H5端) platform?: string // 适用端口 (all:全部, web:Web后台, h5:H5端)
sort?: number // 排序值 sort?: number // 排序值
status?: number // 状态 (0:禁用, 1:启用)
available_for_role_types?: string // 可用角色类型 (1:平台角色, 2:客户角色) available_for_role_types?: string // 可用角色类型 (1:平台角色, 2:客户角色)
children?: PermissionTreeNode[] // 子权限列表 children?: PermissionTreeNode[] // 子权限列表
} }

View File

@@ -44,11 +44,3 @@ export interface PlatformRoleFormData {
role_type: RoleType role_type: RoleType
status: RoleStatus status: RoleStatus
} }
// 权限树节点
export interface PermissionTreeNode {
id: number
label: string
value: string
children?: PermissionTreeNode[]
}

View File

@@ -165,9 +165,9 @@
import type { FormRules } from 'element-plus' import type { FormRules } from 'element-plus'
import { useCheckedColumns } from '@/composables/useCheckedColumns' import { useCheckedColumns } from '@/composables/useCheckedColumns'
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue' import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
import { PlatformAccountService, RoleService } from '@/api/modules' import { AccountService, RoleService } from '@/api/modules'
import type { SearchFormItem } from '@/types' import type { SearchFormItem } from '@/types'
import type { PlatformRole, PlatformAccountResponse } from '@/types/api' import type { PlatformRole, PlatformAccount } from '@/types/api'
import { formatDateTime } from '@/utils/business/format' import { formatDateTime } from '@/utils/business/format'
import { CommonStatus, getStatusText, STATUS_SELECT_OPTIONS } from '@/config/constants' import { CommonStatus, getStatusText, STATUS_SELECT_OPTIONS } from '@/config/constants'
@@ -202,7 +202,7 @@
}) })
// 表格数据 // 表格数据
const tableData = ref<PlatformAccountResponse[]>([]) const tableData = ref<PlatformAccount[]>([])
// 表格实例引用 // 表格实例引用
const tableRef = ref() const tableRef = ref()
@@ -268,7 +268,7 @@
] ]
// 显示对话框 // 显示对话框
const showDialog = (type: string, row?: PlatformAccountResponse) => { const showDialog = (type: string, row?: PlatformAccount) => {
dialogVisible.value = true dialogVisible.value = true
dialogType.value = type dialogType.value = type
@@ -284,7 +284,7 @@
formData.user_type = row.user_type formData.user_type = row.user_type
formData.enterprise_id = row.enterprise_id || null formData.enterprise_id = row.enterprise_id || null
formData.shop_id = row.shop_id || null formData.shop_id = row.shop_id || null
formData.status = row.status formData.status = row.status as CommonStatus
formData.password = '' formData.password = ''
} else { } else {
formData.id = 0 formData.id = 0
@@ -299,7 +299,7 @@
} }
// 删除账号 // 删除账号
const deleteAccount = (row: PlatformAccountResponse) => { const deleteAccount = (row: PlatformAccount) => {
ElMessageBox.confirm(`确定要删除平台账号 ${row.username} 吗?`, '删除平台账号', { ElMessageBox.confirm(`确定要删除平台账号 ${row.username} 吗?`, '删除平台账号', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
@@ -307,7 +307,7 @@
}) })
.then(async () => { .then(async () => {
try { try {
await PlatformAccountService.deletePlatformAccount(row.ID) await AccountService.deleteAccount(row.ID)
ElMessage.success('删除成功') ElMessage.success('删除成功')
getAccountList() getAccountList()
} catch (error) { } catch (error) {
@@ -320,7 +320,7 @@
} }
// 显示修改密码对话框 // 显示修改密码对话框
const showPasswordDialog = (row: PlatformAccountResponse) => { const showPasswordDialog = (row: PlatformAccount) => {
currentAccountId.value = row.ID currentAccountId.value = row.ID
passwordForm.new_password = '' passwordForm.new_password = ''
passwordDialogVisible.value = true passwordDialogVisible.value = true
@@ -346,7 +346,7 @@
{ {
prop: 'user_type', prop: 'user_type',
label: '账号类型', label: '账号类型',
formatter: (row: PlatformAccountResponse) => { formatter: (row: PlatformAccount) => {
const typeMap: Record<number, string> = { const typeMap: Record<number, string> = {
1: '超级管理员', 1: '超级管理员',
2: '平台用户', 2: '平台用户',
@@ -359,7 +359,7 @@
{ {
prop: 'status', prop: 'status',
label: '状态', label: '状态',
formatter: (row: PlatformAccountResponse) => { formatter: (row: PlatformAccount) => {
return h(ElSwitch, { return h(ElSwitch, {
modelValue: row.status, modelValue: row.status,
activeValue: CommonStatus.ENABLED, activeValue: CommonStatus.ENABLED,
@@ -375,14 +375,14 @@
{ {
prop: 'CreatedAt', prop: 'CreatedAt',
label: '创建时间', label: '创建时间',
formatter: (row: PlatformAccountResponse) => formatDateTime(row.CreatedAt) formatter: (row: PlatformAccount) => formatDateTime(row.CreatedAt)
}, },
{ {
prop: 'operation', prop: 'operation',
label: '操作', label: '操作',
width: 240, width: 240,
fixed: 'right', fixed: 'right',
formatter: (row: PlatformAccountResponse) => { formatter: (row: PlatformAccount) => {
return h('div', { style: 'display: flex; gap: 8px;' }, [ return h('div', { style: 'display: flex; gap: 8px;' }, [
h(ArtButtonTable, { h(ArtButtonTable, {
icon: '&#xe72b;', icon: '&#xe72b;',
@@ -444,7 +444,7 @@
} }
// 显示分配角色对话框 // 显示分配角色对话框
const showRoleDialog = async (row: PlatformAccountResponse) => { const showRoleDialog = async (row: PlatformAccount) => {
currentAccountId.value = row.ID currentAccountId.value = row.ID
selectedRoles.value = [] selectedRoles.value = []
@@ -453,7 +453,7 @@
await loadAllRoles() await loadAllRoles()
// 先加载当前账号的角色,再打开对话框 // 先加载当前账号的角色,再打开对话框
const res = await PlatformAccountService.getPlatformAccountRoles(row.ID) const res = await AccountService.getAccountRoles(row.ID)
if (res.code === 0) { if (res.code === 0) {
// 提取角色ID数组 // 提取角色ID数组
const roles = res.data || [] const roles = res.data || []
@@ -470,9 +470,7 @@
const handleAssignRoles = async () => { const handleAssignRoles = async () => {
roleSubmitLoading.value = true roleSubmitLoading.value = true
try { try {
await PlatformAccountService.assignRolesToPlatformAccount(currentAccountId.value, { await AccountService.assignRolesToAccount(currentAccountId.value, selectedRoles.value)
role_ids: selectedRoles.value
})
ElMessage.success('分配角色成功') ElMessage.success('分配角色成功')
roleDialogVisible.value = false roleDialogVisible.value = false
// 刷新列表以更新角色显示 // 刷新列表以更新角色显示
@@ -492,9 +490,10 @@
if (valid) { if (valid) {
passwordSubmitLoading.value = true passwordSubmitLoading.value = true
try { try {
await PlatformAccountService.changePlatformAccountPassword(currentAccountId.value, { await AccountService.updateAccountPassword(
new_password: passwordForm.new_password currentAccountId.value,
}) passwordForm.new_password
)
ElMessage.success('修改密码成功') ElMessage.success('修改密码成功')
passwordDialogVisible.value = false passwordDialogVisible.value = false
} catch (error) { } catch (error) {
@@ -512,12 +511,13 @@
try { try {
const params = { const params = {
page: pagination.currentPage, page: pagination.currentPage,
page_size: pagination.pageSize, pageSize: pagination.pageSize,
user_type: 2, // 筛选平台账号
username: searchForm.username || undefined, username: searchForm.username || undefined,
phone: searchForm.phone || undefined, phone: searchForm.phone || undefined,
status: searchForm.status status: searchForm.status
} }
const res = await PlatformAccountService.getPlatformAccounts(params) const res = await AccountService.getAccounts(params)
if (res.code === 0) { if (res.code === 0) {
tableData.value = res.data.items || [] tableData.value = res.data.items || []
pagination.total = res.data.total || 0 pagination.total = res.data.total || 0
@@ -611,16 +611,15 @@
data.enterprise_id = formData.enterprise_id data.enterprise_id = formData.enterprise_id
} }
await PlatformAccountService.createPlatformAccount(data) await AccountService.createAccount(data)
ElMessage.success('新增成功') ElMessage.success('新增成功')
} else { } else {
const data: any = { const data: any = {
username: formData.username, username: formData.username,
phone: formData.phone, phone: formData.phone
status: formData.status
} }
await PlatformAccountService.updatePlatformAccount(formData.id, data) await AccountService.updateAccount(formData.id, data)
ElMessage.success('更新成功') ElMessage.success('更新成功')
} }
@@ -652,7 +651,7 @@
// 先更新UI // 先更新UI
row.status = newStatus row.status = newStatus
try { try {
await PlatformAccountService.updatePlatformAccount(row.ID, { status: newStatus }) await AccountService.updateAccountStatus(row.ID, newStatus as 0 | 1)
ElMessage.success('状态切换成功') ElMessage.success('状态切换成功')
} catch (error) { } catch (error) {
// 切换失败,恢复原状态 // 切换失败,恢复原状态

View File

@@ -126,9 +126,9 @@
import type { FormRules } from 'element-plus' import type { FormRules } from 'element-plus'
import { useCheckedColumns } from '@/composables/useCheckedColumns' import { useCheckedColumns } from '@/composables/useCheckedColumns'
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue' import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
import { ShopAccountService, ShopService } from '@/api/modules' import { AccountService, ShopService } from '@/api/modules'
import type { SearchFormItem } from '@/types' import type { SearchFormItem } from '@/types'
import type { ShopAccountResponse, ShopResponse } from '@/types/api' import type { PlatformAccount, ShopResponse } from '@/types/api'
import { formatDateTime } from '@/utils/business/format' import { formatDateTime } from '@/utils/business/format'
import { CommonStatus, getStatusText, STATUS_SELECT_OPTIONS } from '@/config/constants' import { CommonStatus, getStatusText, STATUS_SELECT_OPTIONS } from '@/config/constants'
@@ -163,7 +163,7 @@
}) })
// 表格数据 // 表格数据
const tableData = ref<ShopAccountResponse[]>([]) const tableData = ref<PlatformAccount[]>([])
// 表格实例引用 // 表格实例引用
const tableRef = ref() const tableRef = ref()
@@ -243,14 +243,14 @@
] ]
// 显示对话框 // 显示对话框
const showDialog = (type: string, row?: ShopAccountResponse) => { const showDialog = (type: string, row?: PlatformAccount) => {
dialogType.value = type dialogType.value = type
if (type === 'edit' && row) { if (type === 'edit' && row) {
formData.id = row.id formData.id = row.ID
formData.username = row.username formData.username = row.username
formData.phone = row.phone formData.phone = row.phone
formData.shop_id = row.shop_id formData.shop_id = row.shop_id || 0
formData.password = '' formData.password = ''
} else { } else {
formData.id = 0 formData.id = 0
@@ -269,8 +269,8 @@
} }
// 显示修改密码对话框 // 显示修改密码对话框
const showPasswordDialog = (row: ShopAccountResponse) => { const showPasswordDialog = (row: PlatformAccount) => {
currentAccountId.value = row.id currentAccountId.value = row.ID
passwordForm.new_password = '' passwordForm.new_password = ''
// 重置表单验证状态 // 重置表单验证状态
@@ -282,12 +282,12 @@
} }
// 状态切换处理 // 状态切换处理
const handleStatusChange = async (row: ShopAccountResponse, newStatus: number) => { const handleStatusChange = async (row: PlatformAccount, newStatus: number) => {
const oldStatus = row.status const oldStatus = row.status
// 先更新UI // 先更新UI
row.status = newStatus row.status = newStatus
try { try {
await ShopAccountService.updateShopAccountStatus(row.id, { status: newStatus }) await AccountService.updateAccountStatus(row.ID, newStatus as 0 | 1)
ElMessage.success('状态切换成功') ElMessage.success('状态切换成功')
} catch (error) { } catch (error) {
// 切换失败,恢复原状态 // 切换失败,恢复原状态
@@ -318,7 +318,7 @@
{ {
prop: 'status', prop: 'status',
label: '状态', label: '状态',
formatter: (row: ShopAccountResponse) => { formatter: (row: PlatformAccount) => {
return h(ElSwitch, { return h(ElSwitch, {
modelValue: row.status, modelValue: row.status,
activeValue: CommonStatus.ENABLED, activeValue: CommonStatus.ENABLED,
@@ -334,14 +334,14 @@
{ {
prop: 'created_at', prop: 'created_at',
label: '创建时间', label: '创建时间',
formatter: (row: ShopAccountResponse) => formatDateTime(row.created_at) formatter: (row: PlatformAccount) => formatDateTime(row.CreatedAt)
}, },
{ {
prop: 'operation', prop: 'operation',
label: '操作', label: '操作',
width: 120, width: 120,
fixed: 'right', fixed: 'right',
formatter: (row: ShopAccountResponse) => { formatter: (row: PlatformAccount) => {
return h('div', { style: 'display: flex; gap: 8px;' }, [ return h('div', { style: 'display: flex; gap: 8px;' }, [
h(ArtButtonTable, { h(ArtButtonTable, {
icon: '&#xe722;', icon: '&#xe722;',
@@ -447,9 +447,10 @@
if (valid) { if (valid) {
passwordSubmitLoading.value = true passwordSubmitLoading.value = true
try { try {
await ShopAccountService.updateShopAccountPassword(currentAccountId.value, { await AccountService.updateAccountPassword(
new_password: passwordForm.new_password currentAccountId.value,
}) passwordForm.new_password
)
ElMessage.success('重置密码成功') ElMessage.success('重置密码成功')
passwordDialogVisible.value = false passwordDialogVisible.value = false
} catch (error) { } catch (error) {
@@ -467,13 +468,14 @@
try { try {
const params = { const params = {
page: pagination.currentPage, page: pagination.currentPage,
page_size: pagination.pageSize, pageSize: pagination.pageSize,
user_type: 3, // 筛选代理账号
username: searchForm.username || undefined, username: searchForm.username || undefined,
phone: searchForm.phone || undefined, phone: searchForm.phone || undefined,
shop_id: searchForm.shop_id, shop_id: searchForm.shop_id,
status: searchForm.status status: searchForm.status
} }
const res = await ShopAccountService.getShopAccounts(params) const res = await AccountService.getAccounts(params)
if (res.code === 0) { if (res.code === 0) {
tableData.value = res.data.items || [] tableData.value = res.data.items || []
pagination.total = res.data.total || 0 pagination.total = res.data.total || 0
@@ -536,17 +538,18 @@
username: formData.username, username: formData.username,
password: formData.password, password: formData.password,
phone: formData.phone, phone: formData.phone,
user_type: 3, // 代理账号
shop_id: formData.shop_id shop_id: formData.shop_id
} }
await ShopAccountService.createShopAccount(data) await AccountService.createAccount(data)
ElMessage.success('新增成功') ElMessage.success('新增成功')
} else { } else {
const data = { const data = {
username: formData.username username: formData.username
} }
await ShopAccountService.updateShopAccount(formData.id, data) await AccountService.updateAccount(formData.id, data)
ElMessage.success('更新成功') ElMessage.success('更新成功')
} }

View File

@@ -89,6 +89,12 @@
<ElFormItem label="排序序号" prop="sort"> <ElFormItem label="排序序号" prop="sort">
<ElInputNumber v-model="form.sort" :min="0" :max="9999" style="width: 100%" /> <ElInputNumber v-model="form.sort" :min="0" :max="9999" style="width: 100%" />
</ElFormItem> </ElFormItem>
<ElFormItem label="状态" prop="status">
<ElRadioGroup v-model="form.status">
<ElRadio :value="1">启用</ElRadio>
<ElRadio :value="0">禁用</ElRadio>
</ElRadioGroup>
</ElFormItem>
</ElForm> </ElForm>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
@@ -110,6 +116,8 @@
ElMessage, ElMessage,
ElMessageBox, ElMessageBox,
ElTag, ElTag,
ElRadio,
ElRadioGroup,
type FormInstance, type FormInstance,
type FormRules type FormRules
} from 'element-plus' } from 'element-plus'
@@ -123,7 +131,9 @@
PERMISSION_TYPE_OPTIONS, PERMISSION_TYPE_OPTIONS,
PERMISSION_TYPE_SELECT_OPTIONS, PERMISSION_TYPE_SELECT_OPTIONS,
getPermissionTypeText, getPermissionTypeText,
getPermissionTypeTag getPermissionTypeTag,
CommonStatus,
getStatusText
} from '@/config/constants' } from '@/config/constants'
defineOptions({ name: 'Permission' }) defineOptions({ name: 'Permission' })
@@ -177,6 +187,7 @@
{ label: '权限类型', prop: 'perm_type' }, { label: '权限类型', prop: 'perm_type' },
{ label: '菜单路径', prop: 'url' }, { label: '菜单路径', prop: 'url' },
{ label: '适用端口', prop: 'platform' }, { label: '适用端口', prop: 'platform' },
{ label: '状态', prop: 'status' },
{ label: '排序', prop: 'sort' }, { label: '排序', prop: 'sort' },
{ label: '操作', prop: 'operation' } { label: '操作', prop: 'operation' }
] ]
@@ -195,14 +206,15 @@
// 表单引用和数据 // 表单引用和数据
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const form = reactive<CreatePermissionParams>({ const form = reactive<CreatePermissionParams & { status?: number }>({
perm_name: '', perm_name: '',
perm_code: '', perm_code: '',
perm_type: PermissionType.MENU, perm_type: PermissionType.MENU,
parent_id: undefined, parent_id: undefined,
url: '', url: '',
platform: 'all', platform: 'all',
sort: 0 sort: 0,
status: CommonStatus.ENABLED
}) })
// 表单验证规则 // 表单验证规则
@@ -261,6 +273,21 @@
return platformMap[row.platform || 'all'] || row.platform return platformMap[row.platform || 'all'] || row.platform
} }
}, },
{
prop: 'status',
label: '状态',
width: 80,
formatter: (row: PermissionTreeNode) => {
const status = row.status ?? CommonStatus.ENABLED
return h(
ElTag,
{
type: status === CommonStatus.ENABLED ? 'success' : 'info'
},
() => getStatusText(status)
)
}
},
{ {
prop: 'sort', prop: 'sort',
label: '排序', label: '排序',
@@ -396,7 +423,8 @@
parent_id: undefined, // 树结构中没有parent_id需要从API获取 parent_id: undefined, // 树结构中没有parent_id需要从API获取
url: row.url || '', url: row.url || '',
platform: row.platform || 'all', platform: row.platform || 'all',
sort: row.sort || 0 sort: row.sort || 0,
status: row.status ?? CommonStatus.ENABLED
}) })
} else { } else {
currentPermissionId.value = 0 currentPermissionId.value = 0
@@ -469,7 +497,8 @@
parent_id: undefined, parent_id: undefined,
url: '', url: '',
platform: 'all', platform: 'all',
sort: 0 sort: 0,
status: CommonStatus.ENABLED
}) })
} }

View File

@@ -133,6 +133,12 @@
> >
{{ data.perm_type === 1 ? '菜单' : '按钮' }} {{ data.perm_type === 1 ? '菜单' : '按钮' }}
</ElTag> </ElTag>
<ElTag
:type="data.status === 1 ? 'success' : 'info'"
size="small"
>
{{ data.status === 1 ? '启用' : '禁用' }}
</ElTag>
</span> </span>
</template> </template>
</ElTree> </ElTree>
@@ -183,6 +189,12 @@
> >
{{ data.perm_type === 1 ? '菜单' : '按钮' }} {{ data.perm_type === 1 ? '菜单' : '按钮' }}
</ElTag> </ElTag>
<ElTag
:type="data.status === 1 ? 'success' : 'info'"
size="small"
>
{{ data.status === 1 ? '启用' : '禁用' }}
</ElTag>
</span> </span>
<ElButton <ElButton
type="danger" type="danger"
@@ -352,6 +364,7 @@
activeText: getStatusText(CommonStatus.ENABLED), activeText: getStatusText(CommonStatus.ENABLED),
inactiveText: getStatusText(CommonStatus.DISABLED), inactiveText: getStatusText(CommonStatus.DISABLED),
inlinePrompt: true, inlinePrompt: true,
disabled: !hasAuth('role:update_status'),
'onUpdate:modelValue': (val: string | number | boolean) => 'onUpdate:modelValue': (val: string | number | boolean) =>
handleStatusChange(row, val as number) handleStatusChange(row, val as number)
}) })
@@ -431,6 +444,7 @@
id: node.id, id: node.id,
label: node.perm_name, label: node.perm_name,
perm_type: node.perm_type, perm_type: node.perm_type,
status: node.status ?? 1,
children: node.children && node.children.length > 0 ? buildTreeData(node.children) : undefined children: node.children && node.children.length > 0 ? buildTreeData(node.children) : undefined
})) }))
} }
@@ -471,11 +485,13 @@
} }
// 根据权限ID列表设置树节点的禁用状态 // 根据权限ID列表设置树节点的禁用状态
// 同时禁用状态为禁用(status=0)的权限
const setTreeNodesDisabled = (treeNodes: any[], idsToDisable: number[]): any[] => { const setTreeNodesDisabled = (treeNodes: any[], idsToDisable: number[]): any[] => {
return treeNodes.map((node) => { return treeNodes.map((node) => {
const newNode = { const newNode = {
...node, ...node,
disabled: idsToDisable.includes(node.id) // 如果已分配或状态为禁用,则禁用该节点
disabled: idsToDisable.includes(node.id) || node.status === 0
} }
if (node.children && node.children.length > 0) { if (node.children && node.children.length > 0) {