feat: 分类页面以树级结构显示
parent
8b551a72be
commit
9ce121af3f
2
.env
2
.env
|
|
@ -6,7 +6,7 @@ VITE_TITLE = 绝弹管理后台
|
||||||
# 网站副标题
|
# 网站副标题
|
||||||
VITE_SUBTITLE = 快速开发web应用的模板工具
|
VITE_SUBTITLE = 快速开发web应用的模板工具
|
||||||
# 接口前缀 说明:参见 axios 的 baseURL
|
# 接口前缀 说明:参见 axios 的 baseURL
|
||||||
VITE_API = http://demo.dev.juetan.cn/
|
VITE_API = http://127.0.0.1:3030/
|
||||||
|
|
||||||
# =====================================================================================
|
# =====================================================================================
|
||||||
# 开发设置
|
# 开发设置
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ api.instance.interceptors.response.use(
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
const code = error.response.data?.code;
|
const code = error.response.data?.code;
|
||||||
if (code === 4050 || code === 4051) {
|
if (code === 4050 || code === 4051) {
|
||||||
|
Message.warning('提示:登陆过期,请重新登陆!')
|
||||||
userStore.clearUser();
|
userStore.clearUser();
|
||||||
api.tokenExpiredHandler?.();
|
api.tokenExpiredHandler?.();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,11 @@ export interface LoginLog {
|
||||||
* @example "1"
|
* @example "1"
|
||||||
*/
|
*/
|
||||||
description: string;
|
description: string;
|
||||||
|
/**
|
||||||
|
* 操作状态
|
||||||
|
* @example true
|
||||||
|
*/
|
||||||
|
status: boolean;
|
||||||
/**
|
/**
|
||||||
* 登陆IP
|
* 登陆IP
|
||||||
* @example "127.0.0.1"
|
* @example "127.0.0.1"
|
||||||
|
|
@ -199,39 +204,6 @@ export interface UpdateLogDto {
|
||||||
demo?: string;
|
demo?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Role {
|
|
||||||
/**
|
|
||||||
* 角色名称
|
|
||||||
* @example "管理员"
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
/**
|
|
||||||
* 角色标识
|
|
||||||
* @example "admin"
|
|
||||||
*/
|
|
||||||
slug: string;
|
|
||||||
/**
|
|
||||||
* 角色描述
|
|
||||||
* @example "拥有所有权限"
|
|
||||||
*/
|
|
||||||
description: string;
|
|
||||||
/**
|
|
||||||
* 角色权限
|
|
||||||
* @example [1,2,3]
|
|
||||||
*/
|
|
||||||
permissions: Permission[];
|
|
||||||
/**
|
|
||||||
* 角色权限ID
|
|
||||||
* @example [1,2,3]
|
|
||||||
*/
|
|
||||||
permissionIds: number[];
|
|
||||||
/**
|
|
||||||
* 角色用户
|
|
||||||
* @example [1,2,3]
|
|
||||||
*/
|
|
||||||
user: User;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Permission {
|
export interface Permission {
|
||||||
/**
|
/**
|
||||||
* 权限名称
|
* 权限名称
|
||||||
|
|
@ -243,16 +215,16 @@ export interface Permission {
|
||||||
* @example "post:list"
|
* @example "post:list"
|
||||||
*/
|
*/
|
||||||
slug: string;
|
slug: string;
|
||||||
|
/**
|
||||||
|
* 权限类型
|
||||||
|
* @example "menu"
|
||||||
|
*/
|
||||||
|
type: "menu" | "api";
|
||||||
/**
|
/**
|
||||||
* 权限描述
|
* 权限描述
|
||||||
* @example "文章列表"
|
* @example "文章列表"
|
||||||
*/
|
*/
|
||||||
description: string;
|
description: string;
|
||||||
/**
|
|
||||||
* 权限角色
|
|
||||||
* @example "文章列表"
|
|
||||||
*/
|
|
||||||
roles: Role[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateRoleDto {
|
export interface CreateRoleDto {
|
||||||
|
|
@ -379,6 +351,120 @@ export interface UpdatePostDto {
|
||||||
content?: string;
|
content?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CreateCategoryDto {
|
||||||
|
/**
|
||||||
|
* 分类名称
|
||||||
|
* @example "待分类"
|
||||||
|
*/
|
||||||
|
title: string;
|
||||||
|
/**
|
||||||
|
* 分类别名
|
||||||
|
* @example "default"
|
||||||
|
*/
|
||||||
|
slug: string;
|
||||||
|
/**
|
||||||
|
* 分类描述
|
||||||
|
* @example "默认分类"
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
/**
|
||||||
|
* 分类图标
|
||||||
|
* @example "default"
|
||||||
|
*/
|
||||||
|
icon?: string;
|
||||||
|
/**
|
||||||
|
* 分类排序
|
||||||
|
* @example 0
|
||||||
|
*/
|
||||||
|
sort?: number;
|
||||||
|
/**
|
||||||
|
* 分类类型
|
||||||
|
* @example "category"
|
||||||
|
*/
|
||||||
|
type: object;
|
||||||
|
/**
|
||||||
|
* 父级分类ID
|
||||||
|
* @example 0
|
||||||
|
*/
|
||||||
|
parentId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Category {
|
||||||
|
/**
|
||||||
|
* 分类名称
|
||||||
|
* @example "待分类"
|
||||||
|
*/
|
||||||
|
title: string;
|
||||||
|
/**
|
||||||
|
* 分类别名
|
||||||
|
* @example "default"
|
||||||
|
*/
|
||||||
|
slug: string;
|
||||||
|
/**
|
||||||
|
* 分类描述
|
||||||
|
* @example "默认分类"
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
/**
|
||||||
|
* 分类图标
|
||||||
|
* @example "default"
|
||||||
|
*/
|
||||||
|
icon?: string;
|
||||||
|
/**
|
||||||
|
* 分类排序
|
||||||
|
* @example 0
|
||||||
|
*/
|
||||||
|
sort?: number;
|
||||||
|
/**
|
||||||
|
* 分类类型
|
||||||
|
* @example "category"
|
||||||
|
*/
|
||||||
|
type?: object;
|
||||||
|
/**
|
||||||
|
* 父级分类ID
|
||||||
|
* @example 0
|
||||||
|
*/
|
||||||
|
parentId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateCategoryDto {
|
||||||
|
/**
|
||||||
|
* 分类名称
|
||||||
|
* @example "待分类"
|
||||||
|
*/
|
||||||
|
title?: string;
|
||||||
|
/**
|
||||||
|
* 分类别名
|
||||||
|
* @example "default"
|
||||||
|
*/
|
||||||
|
slug?: string;
|
||||||
|
/**
|
||||||
|
* 分类描述
|
||||||
|
* @example "默认分类"
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
/**
|
||||||
|
* 分类图标
|
||||||
|
* @example "default"
|
||||||
|
*/
|
||||||
|
icon?: string;
|
||||||
|
/**
|
||||||
|
* 分类排序
|
||||||
|
* @example 0
|
||||||
|
*/
|
||||||
|
sort?: number;
|
||||||
|
/**
|
||||||
|
* 分类类型
|
||||||
|
* @example "category"
|
||||||
|
*/
|
||||||
|
type?: object;
|
||||||
|
/**
|
||||||
|
* 父级分类ID
|
||||||
|
* @example 0
|
||||||
|
*/
|
||||||
|
parentId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Response {
|
export interface Response {
|
||||||
/**
|
/**
|
||||||
* 状态码
|
* 状态码
|
||||||
|
|
@ -496,6 +582,33 @@ export interface GetPostsParams {
|
||||||
size?: number;
|
size?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GetCategorysParams {
|
||||||
|
/**
|
||||||
|
* 字段描述(Swagger用途)
|
||||||
|
* @example "示例值"
|
||||||
|
*/
|
||||||
|
demo?: string;
|
||||||
|
/**
|
||||||
|
* 排序规则
|
||||||
|
* @default "id:desc"
|
||||||
|
* @pattern /^(\w+:\w+,)*\w+:\w+$/
|
||||||
|
* @example "id:desc"
|
||||||
|
*/
|
||||||
|
sort?: string;
|
||||||
|
/**
|
||||||
|
* 页码
|
||||||
|
* @min 1
|
||||||
|
* @example 1
|
||||||
|
*/
|
||||||
|
page?: number;
|
||||||
|
/**
|
||||||
|
* 每页条数
|
||||||
|
* @min 0
|
||||||
|
* @example 10
|
||||||
|
*/
|
||||||
|
size?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export namespace User {
|
export namespace User {
|
||||||
/**
|
/**
|
||||||
* @description 新增用户
|
* @description 新增用户
|
||||||
|
|
@ -676,7 +789,7 @@ export namespace Log {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* No description
|
* @description 分页查询登陆日志
|
||||||
* @tags log
|
* @tags log
|
||||||
* @name GetLoginLogs
|
* @name GetLoginLogs
|
||||||
* @request GET:/api/v1/logs/login
|
* @request GET:/api/v1/logs/login
|
||||||
|
|
@ -893,10 +1006,10 @@ export namespace Permission {
|
||||||
/**
|
/**
|
||||||
* @description 更新权限
|
* @description 更新权限
|
||||||
* @tags permission
|
* @tags permission
|
||||||
* @name UpdatePermission
|
* @name SetPermission
|
||||||
* @request PATCH:/api/v1/permissions/{id}
|
* @request PATCH:/api/v1/permissions/{id}
|
||||||
*/
|
*/
|
||||||
export namespace UpdatePermission {
|
export namespace SetPermission {
|
||||||
export type RequestParams = {
|
export type RequestParams = {
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
@ -1115,6 +1228,111 @@ export namespace Post {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export namespace Category {
|
||||||
|
/**
|
||||||
|
* @description 新增分类
|
||||||
|
* @tags category
|
||||||
|
* @name AddCategory
|
||||||
|
* @request POST:/api/v1/categories
|
||||||
|
*/
|
||||||
|
export namespace AddCategory {
|
||||||
|
export type RequestParams = {};
|
||||||
|
export type RequestQuery = {};
|
||||||
|
export type RequestBody = CreateCategoryDto;
|
||||||
|
export type RequestHeaders = {};
|
||||||
|
export type ResponseBody = Response & {
|
||||||
|
data: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description 根据分页/过滤参数查询分类
|
||||||
|
* @tags category
|
||||||
|
* @name GetCategorys
|
||||||
|
* @request GET:/api/v1/categories
|
||||||
|
*/
|
||||||
|
export namespace GetCategorys {
|
||||||
|
export type RequestParams = {};
|
||||||
|
export type RequestQuery = {
|
||||||
|
/**
|
||||||
|
* 字段描述(Swagger用途)
|
||||||
|
* @example "示例值"
|
||||||
|
*/
|
||||||
|
demo?: string;
|
||||||
|
/**
|
||||||
|
* 排序规则
|
||||||
|
* @default "id:desc"
|
||||||
|
* @pattern /^(\w+:\w+,)*\w+:\w+$/
|
||||||
|
* @example "id:desc"
|
||||||
|
*/
|
||||||
|
sort?: string;
|
||||||
|
/**
|
||||||
|
* 页码
|
||||||
|
* @min 1
|
||||||
|
* @example 1
|
||||||
|
*/
|
||||||
|
page?: number;
|
||||||
|
/**
|
||||||
|
* 每页条数
|
||||||
|
* @min 0
|
||||||
|
* @example 10
|
||||||
|
*/
|
||||||
|
size?: number;
|
||||||
|
};
|
||||||
|
export type RequestBody = never;
|
||||||
|
export type RequestHeaders = {};
|
||||||
|
export type ResponseBody = Response & {
|
||||||
|
data: Category[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description 根据ID查询分类
|
||||||
|
* @tags category
|
||||||
|
* @name GetCategory
|
||||||
|
* @request GET:/api/v1/categories/{id}
|
||||||
|
*/
|
||||||
|
export namespace GetCategory {
|
||||||
|
export type RequestParams = {
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
export type RequestQuery = {};
|
||||||
|
export type RequestBody = never;
|
||||||
|
export type RequestHeaders = {};
|
||||||
|
export type ResponseBody = Response & {
|
||||||
|
data: Category;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description 根据ID更新分类
|
||||||
|
* @tags category
|
||||||
|
* @name UpdateCategory
|
||||||
|
* @request PATCH:/api/v1/categories/{id}
|
||||||
|
*/
|
||||||
|
export namespace UpdateCategory {
|
||||||
|
export type RequestParams = {
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
export type RequestQuery = {};
|
||||||
|
export type RequestBody = UpdateCategoryDto;
|
||||||
|
export type RequestHeaders = {};
|
||||||
|
export type ResponseBody = Response;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description 根据ID删除分类
|
||||||
|
* @tags category
|
||||||
|
* @name DelCategory
|
||||||
|
* @request DELETE:/api/v1/categories/{id}
|
||||||
|
*/
|
||||||
|
export namespace DelCategory {
|
||||||
|
export type RequestParams = {
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
export type RequestQuery = {};
|
||||||
|
export type RequestBody = never;
|
||||||
|
export type RequestHeaders = {};
|
||||||
|
export type ResponseBody = Response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, HeadersDefaults, ResponseType } from "axios";
|
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, HeadersDefaults, ResponseType } from "axios";
|
||||||
|
|
||||||
export type QueryParamsType = Record<string | number, any>;
|
export type QueryParamsType = Record<string | number, any>;
|
||||||
|
|
@ -1426,7 +1644,7 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No description
|
* 分页查询登陆日志
|
||||||
*
|
*
|
||||||
* @tags log
|
* @tags log
|
||||||
* @name GetLoginLogs
|
* @name GetLoginLogs
|
||||||
|
|
@ -1667,10 +1885,10 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
|
||||||
* 更新权限
|
* 更新权限
|
||||||
*
|
*
|
||||||
* @tags permission
|
* @tags permission
|
||||||
* @name UpdatePermission
|
* @name SetPermission
|
||||||
* @request PATCH:/api/v1/permissions/{id}
|
* @request PATCH:/api/v1/permissions/{id}
|
||||||
*/
|
*/
|
||||||
updatePermission: (id: string, data: UpdatePermissionDto, params: RequestParams = {}) => {
|
setPermission: (id: string, data: UpdatePermissionDto, params: RequestParams = {}) => {
|
||||||
return this.request<Response, any>({
|
return this.request<Response, any>({
|
||||||
path: `/api/v1/permissions/${id}`,
|
path: `/api/v1/permissions/${id}`,
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
|
|
@ -1912,4 +2130,105 @@ export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDa
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
category = {
|
||||||
|
/**
|
||||||
|
* 新增分类
|
||||||
|
*
|
||||||
|
* @tags category
|
||||||
|
* @name AddCategory
|
||||||
|
* @request POST:/api/v1/categories
|
||||||
|
*/
|
||||||
|
addCategory: (data: CreateCategoryDto, params: RequestParams = {}) => {
|
||||||
|
return this.request<
|
||||||
|
Response & {
|
||||||
|
data: number;
|
||||||
|
},
|
||||||
|
any
|
||||||
|
>({
|
||||||
|
path: `/api/v1/categories`,
|
||||||
|
method: "POST",
|
||||||
|
body: data,
|
||||||
|
type: ContentType.Json,
|
||||||
|
format: "json",
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据分页/过滤参数查询分类
|
||||||
|
*
|
||||||
|
* @tags category
|
||||||
|
* @name GetCategorys
|
||||||
|
* @request GET:/api/v1/categories
|
||||||
|
*/
|
||||||
|
getCategorys: (query: GetCategorysParams, params: RequestParams = {}) => {
|
||||||
|
return this.request<
|
||||||
|
Response & {
|
||||||
|
data: Category[];
|
||||||
|
},
|
||||||
|
any
|
||||||
|
>({
|
||||||
|
path: `/api/v1/categories`,
|
||||||
|
method: "GET",
|
||||||
|
query: query,
|
||||||
|
format: "json",
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询分类
|
||||||
|
*
|
||||||
|
* @tags category
|
||||||
|
* @name GetCategory
|
||||||
|
* @request GET:/api/v1/categories/{id}
|
||||||
|
*/
|
||||||
|
getCategory: (id: number, params: RequestParams = {}) => {
|
||||||
|
return this.request<
|
||||||
|
Response & {
|
||||||
|
data: Category;
|
||||||
|
},
|
||||||
|
any
|
||||||
|
>({
|
||||||
|
path: `/api/v1/categories/${id}`,
|
||||||
|
method: "GET",
|
||||||
|
format: "json",
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID更新分类
|
||||||
|
*
|
||||||
|
* @tags category
|
||||||
|
* @name UpdateCategory
|
||||||
|
* @request PATCH:/api/v1/categories/{id}
|
||||||
|
*/
|
||||||
|
updateCategory: (id: number, data: UpdateCategoryDto, params: RequestParams = {}) => {
|
||||||
|
return this.request<Response, any>({
|
||||||
|
path: `/api/v1/categories/${id}`,
|
||||||
|
method: "PATCH",
|
||||||
|
body: data,
|
||||||
|
type: ContentType.Json,
|
||||||
|
format: "json",
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID删除分类
|
||||||
|
*
|
||||||
|
* @tags category
|
||||||
|
* @name DelCategory
|
||||||
|
* @request DELETE:/api/v1/categories/{id}
|
||||||
|
*/
|
||||||
|
delCategory: (id: number, params: RequestParams = {}) => {
|
||||||
|
return this.request<Response, any>({
|
||||||
|
path: `/api/v1/categories/${id}`,
|
||||||
|
method: "DELETE",
|
||||||
|
format: "json",
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<BreadPage>
|
<BreadPage>
|
||||||
<Table v-bind="table"></Table>
|
<Table v-bind="table">
|
||||||
|
|
||||||
|
</Table>
|
||||||
</BreadPage>
|
</BreadPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -8,53 +10,52 @@
|
||||||
import { api } from "@/api";
|
import { api } from "@/api";
|
||||||
import { Table, useTable } from "@/components";
|
import { Table, useTable } from "@/components";
|
||||||
import { dayjs } from "@/libs/dayjs";
|
import { dayjs } from "@/libs/dayjs";
|
||||||
import { Tag } from "@arco-design/web-vue";
|
import { listToTree } from "@/utils/listToTree";
|
||||||
|
|
||||||
const table = useTable({
|
const table = useTable({
|
||||||
data: async (model, paging) => {
|
data: async (model, paging) => {
|
||||||
return api.log.getLoginLogs({ ...model, ...paging });
|
const res = await api.category.getCategorys({ ...model, ...paging });
|
||||||
|
const data = listToTree(res.data.data);
|
||||||
|
return { data: { data, total: (res.data as any).total } };
|
||||||
},
|
},
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
title: "登陆账号",
|
title: "名称",
|
||||||
dataIndex: "nickname",
|
dataIndex: "title",
|
||||||
width: 140,
|
width: 240,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "操作描述",
|
title: "描述",
|
||||||
dataIndex: "description",
|
dataIndex: "description",
|
||||||
render: ({ record: { status, description } }) => {
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
<Tag color={status === null || status ? "green" : "red"} class="mr-2">
|
|
||||||
{ status === null || status ? "成功" : "失败" }
|
|
||||||
</Tag>
|
|
||||||
{description}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "登陆地址",
|
title: "别名",
|
||||||
dataIndex: "ip",
|
dataIndex: "slug",
|
||||||
width: 200,
|
width: 200,
|
||||||
render: ({ record }) => `${record.addr || "未知"}(${record.ip})`,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "操作系统",
|
title: "创建时间",
|
||||||
dataIndex: "os",
|
|
||||||
width: 160,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "浏览器",
|
|
||||||
dataIndex: "browser",
|
|
||||||
width: 160,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "登陆时间",
|
|
||||||
dataIndex: "createdAt",
|
dataIndex: "createdAt",
|
||||||
|
width: 200,
|
||||||
|
render: ({ record }) => dayjs(record.createdAt).format(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "button",
|
||||||
|
title: "操作",
|
||||||
width: 120,
|
width: 120,
|
||||||
render: ({ record }) => dayjs(record.createdAt).fromNow(),
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'modify',
|
||||||
|
text: '修改'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "delete",
|
||||||
|
text: "删除",
|
||||||
|
onClick({ record }) {
|
||||||
|
return api.category.delCategory(record.id);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
search: {
|
search: {
|
||||||
|
|
@ -65,14 +66,68 @@ const table = useTable({
|
||||||
type: "input",
|
type: "input",
|
||||||
required: false,
|
required: false,
|
||||||
nodeProps: {
|
nodeProps: {
|
||||||
placeholder: '请输入登陆账号',
|
placeholder: "名称关键字",
|
||||||
},
|
},
|
||||||
itemProps: {
|
itemProps: {
|
||||||
hideLabel: true,
|
hideLabel: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
create: {
|
||||||
|
title: "添加分类",
|
||||||
|
modalProps: {
|
||||||
|
width: 580,
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
field: "parentId",
|
||||||
|
label: "父级分类",
|
||||||
|
type: "select",
|
||||||
|
options: async () => {
|
||||||
|
const res = await api.category.getCategorys({ size: 0 });
|
||||||
|
return res.data.data.map(({ id, title }: any) => ({ value: id, label: title }));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "title",
|
||||||
|
label: "分类名称",
|
||||||
|
type: "input",
|
||||||
|
required: true,
|
||||||
|
nodeProps: {
|
||||||
|
placeholder: "请输入分类名称",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "slug",
|
||||||
|
label: "分类别名",
|
||||||
|
type: "input",
|
||||||
|
required: true,
|
||||||
|
nodeProps: {
|
||||||
|
placeholder: "请输入分类别名",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "description",
|
||||||
|
label: "描述",
|
||||||
|
type: "textarea",
|
||||||
|
required: false,
|
||||||
|
nodeProps: {
|
||||||
|
placeholder: "请输入描述",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
submit: async ({ model }) => {
|
||||||
|
return api.category.addCategory(model);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modify: {
|
||||||
|
extend: true,
|
||||||
|
title: "修改分类",
|
||||||
|
submit: async ({ model }) => {
|
||||||
|
return api.category.updateCategory(model.id, model);
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<BreadPage>
|
<BreadPage>
|
||||||
<Table v-bind="table"></Table>
|
<Table v-bind="table">
|
||||||
|
<template #action>
|
||||||
|
<a-button type="primary">
|
||||||
|
<template #icon>
|
||||||
|
<i class="icon-park-outline-upload"></i>
|
||||||
|
</template>
|
||||||
|
上传
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
</BreadPage>
|
</BreadPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -8,71 +17,54 @@
|
||||||
import { api } from "@/api";
|
import { api } from "@/api";
|
||||||
import { Table, useTable } from "@/components";
|
import { Table, useTable } from "@/components";
|
||||||
import { dayjs } from "@/libs/dayjs";
|
import { dayjs } from "@/libs/dayjs";
|
||||||
import { Tag } from "@arco-design/web-vue";
|
|
||||||
|
|
||||||
const table = useTable({
|
const table = useTable({
|
||||||
data: async (model, paging) => {
|
data: async (model, paging) => {
|
||||||
return api.log.getLoginLogs({ ...model, ...paging });
|
return api.upload.getUploads();
|
||||||
},
|
},
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
title: "登陆账号",
|
title: "文件名称",
|
||||||
dataIndex: "nickname",
|
dataIndex: "name",
|
||||||
width: 140,
|
width: 260,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "操作描述",
|
title: "操作描述",
|
||||||
dataIndex: "description",
|
dataIndex: "description",
|
||||||
render: ({ record: { status, description } }) => {
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
<Tag color={status === null || status ? "green" : "red"} class="mr-2">
|
|
||||||
{ status === null || status ? "成功" : "失败" }
|
|
||||||
</Tag>
|
|
||||||
{description}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "登陆地址",
|
|
||||||
dataIndex: "ip",
|
|
||||||
width: 200,
|
|
||||||
render: ({ record }) => `${record.addr || "未知"}(${record.ip})`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "操作系统",
|
|
||||||
dataIndex: "os",
|
|
||||||
width: 160,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "浏览器",
|
|
||||||
dataIndex: "browser",
|
|
||||||
width: 160,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "登陆时间",
|
title: "登陆时间",
|
||||||
dataIndex: "createdAt",
|
dataIndex: "createdAt",
|
||||||
|
width: 200,
|
||||||
|
render: ({ record }) => dayjs(record.createdAt).format(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "button",
|
||||||
|
title: "操作",
|
||||||
width: 120,
|
width: 120,
|
||||||
render: ({ record }) => dayjs(record.createdAt).fromNow(),
|
buttons: [
|
||||||
|
{
|
||||||
|
type: "modify",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "delete",
|
||||||
|
text: "删除",
|
||||||
|
onClick({ record }) {
|
||||||
|
return api.upload.delFile(record.id);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
search: {
|
search: {
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
field: "nickname",
|
field: 'name',
|
||||||
label: "登陆账号",
|
label: '文件名称',
|
||||||
type: "input",
|
type: 'input',
|
||||||
required: false,
|
}
|
||||||
nodeProps: {
|
]
|
||||||
placeholder: '请输入登陆账号',
|
|
||||||
},
|
|
||||||
itemProps: {
|
|
||||||
hideLabel: true,
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
export const listToTree = (list: any[], id = "id", pid = "parentId", cid = "children") => {
|
||||||
|
const map = list.reduce((res, v) => ((res[v[id]] = v), res), {});
|
||||||
|
return list.filter((item) => {
|
||||||
|
const parent = map[item[pid]];
|
||||||
|
if (parent) {
|
||||||
|
!parent[cid] && (parent[cid] = []);
|
||||||
|
parent[cid].push(item);
|
||||||
|
}
|
||||||
|
return !item[pid];
|
||||||
|
});
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue