mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-23 03:56:37 +08:00
feat(projects): 添加请求适配adapter层应用的示例页面
This commit is contained in:
parent
f6b61418e5
commit
8d11a6affc
17
README.md
17
README.md
@ -7,13 +7,13 @@
|
||||
|
||||
## 简介
|
||||
|
||||
Soybean Admin 是一个基于 Vue3、Vite3、TypeScript、Naive UI和UnoCSS 的清新优雅的中后台模版,它使用了最新的前端技术栈,内置丰富的主题配置,有着极高的代码规范,基于mock实现的动态权限路由,开箱即用的中后台前端解决方案,也可用于学习参考。
|
||||
[Soybean Admin](https://github.com/honghuangdc/soybean-admin) 是一个基于 Vue3、Vite3、TypeScript、NaiveUI、Pinia和UnoCSS 的清新优雅的中后台模版,它使用了最新的前端技术栈,内置丰富的主题配置,有着极高的代码规范,基于mock实现的动态权限路由,开箱即用的中后台前端解决方案,也可用于学习参考。
|
||||
|
||||
## 特性
|
||||
|
||||
- **最新技术栈**:使用 Vue3/vite3 等前端前沿技术开发, 使用高效率的npm包管理器pnpm
|
||||
- **最新技术栈**:使用 Vue3/Vite3 等前端前沿技术开发, 使用高效率的npm包管理器pnpm
|
||||
- **TypeScript**:应用程序级 JavaScript 的语言
|
||||
- **主题**:丰富可配置的主题、暗黑模式,基于原子css - UnoCSS的动态主题颜色
|
||||
- **主题**:丰富可配置的主题、暗黑模式,基于原子css框架 - UnoCSS的动态主题颜色
|
||||
- **代码规范**:丰富的规范插件及极高的代码规范
|
||||
- **权限路由**:简易的路由配置、基于mock的动态路由能快速实现后端动态路由
|
||||
- **请求函数**:基于axios的完善的请求函数封装,提供Promise和hooks两种请求函数,加入请求结果数据转换的适配器
|
||||
@ -94,6 +94,14 @@ Soybean Admin 是一个基于 Vue3、Vite3、TypeScript、Naive UI和UnoCSS 的
|
||||
|
||||
## 安装使用
|
||||
|
||||
- 环境配置
|
||||
|
||||
**本地环境需要安装 pnpm 7.x 、Node.js 14.18+ 和 Git**
|
||||
- [Nodejs安装教程]()
|
||||
|
||||
- [Nodejs版本管理工具fnm安装教程]()
|
||||
|
||||
|
||||
- 克隆代码
|
||||
|
||||
```bash
|
||||
@ -118,9 +126,6 @@ pnpm dev
|
||||
pnpm build
|
||||
```
|
||||
|
||||
**本地环境需要安装 pnpm 6.x 、Node.js 14.x 和 Git**
|
||||
|
||||
|
||||
## 如何贡献
|
||||
|
||||
非常欢迎您的加入 或者提交一个 Pull Request。
|
||||
|
@ -1,4 +1,5 @@
|
||||
import auth from './auth';
|
||||
import route from './route';
|
||||
import management from './management';
|
||||
|
||||
export default [...auth, ...route];
|
||||
export default [...auth, ...route, ...management];
|
||||
|
51
mock/api/management.ts
Normal file
51
mock/api/management.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import type { MockMethod } from 'vite-plugin-mock';
|
||||
|
||||
const apis: MockMethod[] = [
|
||||
{
|
||||
url: '/mock/getUserManagementList',
|
||||
method: 'post',
|
||||
response: (): Service.MockServiceResult<ApiUserManagement.UserTable[]> => {
|
||||
const data: ApiUserManagement.UserTable[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: '张三',
|
||||
age: 24,
|
||||
gender: null,
|
||||
createTime: '2022-04-13',
|
||||
updateTime: '2022-07-29'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '李四',
|
||||
age: 22,
|
||||
gender: '1',
|
||||
createTime: '2022-05-13',
|
||||
updateTime: '2022-06-29'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: '王五',
|
||||
gender: '1',
|
||||
createTime: '2022-04-18',
|
||||
updateTime: '2022-07-30'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: '王小梅',
|
||||
age: 20,
|
||||
gender: '0',
|
||||
createTime: '2022-05-18',
|
||||
updateTime: '2022-07-30'
|
||||
}
|
||||
];
|
||||
|
||||
return {
|
||||
code: 200,
|
||||
message: 'ok',
|
||||
data
|
||||
};
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export default apis;
|
@ -13,3 +13,9 @@ export enum EnumLoginModule {
|
||||
'reset-pwd' = '重置密码',
|
||||
'bind-wechat' = '微信绑定'
|
||||
}
|
||||
|
||||
export enum EnumGender {
|
||||
male = '男',
|
||||
female = '女',
|
||||
null = ''
|
||||
}
|
||||
|
@ -1,69 +1 @@
|
||||
import type { DataTableColumn } from 'naive-ui';
|
||||
|
||||
type UnionColumn<T> = T extends DataTableColumn[] ? TypeUtil.ArrayToUnion<T> : never;
|
||||
|
||||
type ColumnKey = 'key';
|
||||
|
||||
type InterfaceArray = {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
type ColumnKeyData = {
|
||||
key: unknown;
|
||||
};
|
||||
|
||||
type ExcludeArrayByKey<T extends InterfaceArray[]> = T extends [infer First, ...infer Rest]
|
||||
? First extends ColumnKeyData
|
||||
? Rest extends InterfaceArray[]
|
||||
? [First, ...ExcludeArrayByKey<Rest>]
|
||||
: [First]
|
||||
: Rest extends InterfaceArray[]
|
||||
? ExcludeArrayByKey<Rest>
|
||||
: []
|
||||
: [];
|
||||
|
||||
type GetUnionColumnKey<T extends InterfaceArray[]> = ColumnKey extends keyof UnionColumn<T>
|
||||
? UnionColumn<T>[ColumnKey]
|
||||
: never;
|
||||
|
||||
export const columns: DataTableColumn[] = [
|
||||
{
|
||||
type: 'selection'
|
||||
},
|
||||
{
|
||||
title: 'Name',
|
||||
key: 'name',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: 'Age',
|
||||
key: 'age'
|
||||
},
|
||||
{
|
||||
title: 'Address',
|
||||
key: 'address'
|
||||
}
|
||||
];
|
||||
|
||||
export type UnionColumnKey = GetUnionColumnKey<
|
||||
ExcludeArrayByKey<
|
||||
[
|
||||
{
|
||||
type: 'selection';
|
||||
},
|
||||
{
|
||||
title: 'Name';
|
||||
key: 'name';
|
||||
align: 'center';
|
||||
},
|
||||
{
|
||||
title: 'Age';
|
||||
key: 'age';
|
||||
},
|
||||
{
|
||||
title: 'Address';
|
||||
key: 'address';
|
||||
}
|
||||
]
|
||||
>
|
||||
>;
|
||||
// import type { DataTableColumn } from 'naive-ui';
|
||||
|
@ -1,5 +1,9 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
/**
|
||||
* boolean组合式函数
|
||||
* @param initValue 初始值
|
||||
*/
|
||||
export default function useBoolean(initValue = false) {
|
||||
const bool = ref(initValue);
|
||||
|
||||
|
@ -1,2 +1,3 @@
|
||||
export * from './auth';
|
||||
export * from './demo';
|
||||
export * from './management';
|
||||
|
39
src/service/api/management.adapter.ts
Normal file
39
src/service/api/management.adapter.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { EnumGender } from '@/enum';
|
||||
import { isUndefined } from '@/utils';
|
||||
|
||||
export function adapterOfFetchUserManagementList(
|
||||
requestData: ApiUserManagement.UserTable[],
|
||||
adminId: string
|
||||
): UserManagement.UserTable[] {
|
||||
const genderMap: Record<
|
||||
NonNullable<ApiUserManagement.UserTable['gender']>,
|
||||
NonNullable<UserManagement.UserTable['userGender']>
|
||||
> = {
|
||||
'0': 'female',
|
||||
'1': 'male'
|
||||
};
|
||||
|
||||
// 1. 有可能依赖于多个接口的结果,再转换成页面的数据
|
||||
// 2. 接口定义的字段有可能为null, 例如 预期是数组却返回了null,导致调用数组方法报错
|
||||
// 3. 字段可能丢失
|
||||
|
||||
return requestData.map(item => {
|
||||
const { id, name, age, gender } = item;
|
||||
|
||||
const userName = name + (adminId === id ? '(管理员)' : '');
|
||||
|
||||
const userAge = isUndefined(age) ? '无' : String(age);
|
||||
|
||||
const userGender = gender !== null ? genderMap[gender] : 'null';
|
||||
|
||||
const result: UserManagement.UserTable = {
|
||||
id,
|
||||
userName,
|
||||
userAge,
|
||||
userGender,
|
||||
userGenderLabel: EnumGender[userGender]
|
||||
};
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
22
src/service/api/management.ts
Normal file
22
src/service/api/management.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { adapter } from '@/utils';
|
||||
import { mockRequest } from '../request';
|
||||
import { adapterOfFetchUserManagementList } from './management.adapter';
|
||||
|
||||
/**
|
||||
* 获取用户管理列表
|
||||
*/
|
||||
export async function fetchUserManagementList() {
|
||||
const data = await mockRequest.post<ApiUserManagement.UserTable[]>('/getUserManagementList');
|
||||
|
||||
const id = '2';
|
||||
|
||||
return adapter(adapterOfFetchUserManagementList, data, { error: null, data: id });
|
||||
}
|
||||
|
||||
// export async function fetchFilterUserManagementList(
|
||||
// filterKey: keyof UserManagement.UserTable,
|
||||
// mode: 'fontEnd' | 'backEnd',
|
||||
// source: UserManagement.UserTable[]
|
||||
// ) {
|
||||
|
||||
// }
|
21
src/typings/api.d.ts
vendored
21
src/typings/api.d.ts
vendored
@ -28,3 +28,24 @@ declare namespace ApiDemo {
|
||||
dataName: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare namespace ApiUserManagement {
|
||||
interface UserTable {
|
||||
/** 用户id */
|
||||
id: string;
|
||||
/** 用户名 */
|
||||
name: string;
|
||||
/** 用户年龄 */
|
||||
age?: number;
|
||||
/**
|
||||
* 用户性别
|
||||
* - 男 1
|
||||
* - 女 0
|
||||
*/
|
||||
gender: '0' | '1' | null;
|
||||
/** 创建时间 */
|
||||
createTime: string;
|
||||
/** 更新时间 */
|
||||
updateTime: string;
|
||||
}
|
||||
}
|
||||
|
20
src/typings/business.d.ts
vendored
20
src/typings/business.d.ts
vendored
@ -62,3 +62,23 @@ declare namespace Message {
|
||||
tagProps?: import('naive-ui').TagProps;
|
||||
}
|
||||
}
|
||||
|
||||
/** 用户管理 */
|
||||
declare namespace UserManagement {
|
||||
/** 用户表格 */
|
||||
interface UserTable {
|
||||
/** 用户id */
|
||||
id: string;
|
||||
/** 用户名 */
|
||||
userName: string;
|
||||
/** 用户年龄 */
|
||||
userAge: string;
|
||||
/**
|
||||
* 用户性别
|
||||
* - male 男
|
||||
* - female 女
|
||||
*/
|
||||
userGender: keyof typeof import('@/enum').EnumGender;
|
||||
userGenderLabel: import('@/enum').EnumGender;
|
||||
}
|
||||
}
|
||||
|
10
src/typings/utils.d.ts
vendored
10
src/typings/utils.d.ts
vendored
@ -7,15 +7,9 @@ declare namespace TypeUtil {
|
||||
|
||||
type GetFunReturn<F extends Noop> = F extends (...args: any) => infer R ? R : never;
|
||||
|
||||
type Writable<T> = { [K in keyof T]: T[K] };
|
||||
|
||||
type FirstOfArray<T extends any[]> = T extends [infer First, ...infer _Rest] ? First : never;
|
||||
|
||||
type LastOfArray<T extends any[]> = T extends [...infer _Rest, infer Last] ? Last : never;
|
||||
|
||||
type ArrayToUnion<T extends any[]> = T extends [infer First, ...infer Rest]
|
||||
? First extends any
|
||||
? Rest extends any[]
|
||||
? FirstOfArray<[First]> | ArrayToUnion<Rest>
|
||||
: [First]
|
||||
: never
|
||||
: never;
|
||||
}
|
||||
|
@ -1,9 +1,55 @@
|
||||
<template>
|
||||
<div>
|
||||
<n-data-table />
|
||||
<n-data-table :columns="columns" :data="tableData" :loading="loading" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import type { DataTableColumns } from 'naive-ui';
|
||||
import { fetchUserManagementList } from '@/service';
|
||||
import { useLoading } from '@/hooks';
|
||||
|
||||
const { loading, startLoading, endLoading } = useLoading(false);
|
||||
|
||||
const columns: DataTableColumns = [
|
||||
{
|
||||
key: 'userName',
|
||||
title: '用户名'
|
||||
},
|
||||
{
|
||||
key: 'userAge',
|
||||
title: '用户年龄'
|
||||
},
|
||||
{
|
||||
key: 'userGenderLabel',
|
||||
title: '性别'
|
||||
}
|
||||
];
|
||||
|
||||
const tableData = ref<UserManagement.UserTable[]>([]);
|
||||
|
||||
function setTableData(data: UserManagement.UserTable[]) {
|
||||
tableData.value = data;
|
||||
}
|
||||
|
||||
async function getTableData() {
|
||||
startLoading();
|
||||
const { data } = await fetchUserManagementList();
|
||||
if (data) {
|
||||
setTimeout(() => {
|
||||
setTableData(data);
|
||||
endLoading();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
getTableData();
|
||||
}
|
||||
|
||||
// 初始化
|
||||
init();
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
0
src/views/management/user/user.ts
Normal file
0
src/views/management/user/user.ts
Normal file
Loading…
Reference in New Issue
Block a user