Skip to content

Commit

Permalink
feat(projects): 添加请求适配adapter层应用的示例页面
Browse files Browse the repository at this point in the history
  • Loading branch information
honghuangdc committed Jul 30, 2022
1 parent f6b6141 commit 8d11a6a
Show file tree
Hide file tree
Showing 14 changed files with 228 additions and 86 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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两种请求函数,加入请求结果数据转换的适配器
Expand Down Expand Up @@ -94,6 +94,14 @@ Soybean Admin 是一个基于 Vue3、Vite3、TypeScript、Naive UI和UnoCSS 的

## 安装使用

- 环境配置

**本地环境需要安装 pnpm 7.x 、Node.js 14.18+ 和 Git**
- [Nodejs安装教程]()

- [Nodejs版本管理工具fnm安装教程]()


- 克隆代码

```bash
Expand All @@ -118,9 +126,6 @@ pnpm dev
pnpm build
```

**本地环境需要安装 pnpm 6.x 、Node.js 14.x 和 Git**


## 如何贡献

非常欢迎您的加入![提一个 Issue](https://github.com/honghuangdc/soybean-admin/issues/new) 或者提交一个 Pull Request。
Expand Down
3 changes: 2 additions & 1 deletion mock/api/index.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 51 additions & 0 deletions mock/api/management.ts
Original file line number Diff line number Diff line change
@@ -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;
6 changes: 6 additions & 0 deletions src/enum/business.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ export enum EnumLoginModule {
'reset-pwd' = '重置密码',
'bind-wechat' = '微信绑定'
}

export enum EnumGender {
male = '男',
female = '女',
null = ''
}
70 changes: 1 addition & 69 deletions src/hooks/business/useNaiveTable.ts
Original file line number Diff line number Diff line change
@@ -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';
4 changes: 4 additions & 0 deletions src/hooks/common/useBoolean.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { ref } from 'vue';

/**
* boolean组合式函数
* @param initValue 初始值
*/
export default function useBoolean(initValue = false) {
const bool = ref(initValue);

Expand Down
1 change: 1 addition & 0 deletions src/service/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './auth';
export * from './demo';
export * from './management';
39 changes: 39 additions & 0 deletions src/service/api/management.adapter.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 22 additions & 0 deletions src/service/api/management.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 21 additions & 0 deletions src/typings/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 20 additions & 0 deletions src/typings/business.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 2 additions & 8 deletions src/typings/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
50 changes: 48 additions & 2 deletions src/views/management/user/index.vue
Original file line number Diff line number Diff line change
@@ -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>
Empty file.

1 comment on commit 8d11a6a

@vercel
Copy link

@vercel vercel bot commented on 8d11a6a Jul 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.