前端

使用Vue3、TS和Element+构建的简单列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<template>
<div class="wraps">
<div>
<el-input v-model="search.keyWord" style="width:300px;"></el-input>
<el-button @click="init" style="margin-left:10px;">搜索</el-button>
<el-button @click="openDialog" type="primary" style="margin-left:10px;">添加</el-button>
</div>
<el-table border :data="tableData" style="width: 100%;margin-top: 30px;">
<el-table-column prop="name" label="名字" />
<el-table-column prop="desc" label="描述" />
<el-table-column prop="id" label="id" />
<el-table-column>
<template #default="scope">
<el-button @click="edit(scope.row)">编辑</el-button>
<el-button @click="deleteRow(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination @current-change="changeSize" style="float:right;margin-top:10px;" background
layout="prev, pager, next" :total="total" />
</div>
<el-dialog v-model="dialogVisible" title="弹框" width="50%">
<el-form :model="form">
<el-form-item prop="name" label="名称">
<el-input v-model="form.name" placeholder="名称" />
</el-form-item>
<el-form-item prop="desc" label="描述">
<el-input v-model="form.desc" placeholder="描述">
</el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="close">关闭</el-button>
<el-button type="primary" @click="save">
保存
</el-button>
</span>
</template>
</el-dialog>
</template>

<script setup lang='ts'>
import { ref, reactive } from 'vue'
import { addUser, updateUser, delUser, getList } from './server'
const total = ref<number>(0)
//搜索框
const search = reactive({
keyWord: "",
page: 1,
pageSize: 10
})
//表单
const form = reactive({
name: "",
desc: "",
id: 0
})
//清空数据
const resetForm = reactive({ ...form })
//表格数据
const tableData = ref([])
//弹框开关
const dialogVisible = ref<boolean>(false)
// 打开弹窗
const openDialog = () => {
dialogVisible.value = true;
Object.assign(form, resetForm)
}
//初始化表格数据
const init = async () => {
const result = await getList(search)
tableData.value = result?.data?.list ?? []
total.value = result?.data?.total ?? 0
}
init()
const changeSize = (page: number) => {
search.page = page
init()
}
//保存/修改表格数据
const save = async () => {
if (form.id) {
await updateUser(form)
} else {
await addUser(form)
}
close()
init()
}
//删除表格数据
const deleteRow = async (row: { id: any; }) => {
await delUser({ id: row.id })
init()
}
//获取详情
const edit = (row: any) => {
dialogVisible.value = true;
Object.assign(form, row)
}
//关闭弹框
const close = () => {
dialogVisible.value = false;
}
</script>

<style lang='less'>
* {
padding: 0;
margin: 0;
}

html,
body {
background: #ccc;
}

.wraps {
height: 100vh;
padding: 30px;
}
</style>

使用Axios构建的接口:

1
2
3
4
5
6
7
8
9
10
11
import axios from 'axios'

axios.defaults.baseURL = 'http://localhost:3000'

export const addUser = (data) => axios.post('/user',data).then(res => res.data)

export const getList = (data) => axios.get('/user',{params:data}).then(res => res.data)

export const delUser = (data) => axios.delete(`/user/${data.id}`).then(res => res.data)

export const updateUser = (data) => axios.patch(`/user/${data.id}`,data).then(res => res.data)

后端

Controller:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
Query,
} from '@nestjs/common';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';

@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {}

@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.userService.create(createUserDto);
}

@Get()
findAll(@Query() query: { keyWord: string; page: number; pageSize: number }) {
return this.userService.findAll(query);
}

@Patch(':id')
update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
return this.userService.update(+id, updateUserDto);
}

@Delete(':id')
remove(@Param('id') id: string) {
return this.userService.remove(+id);
}
}

Service:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like } from 'typeorm';
import { User } from './entities/user.entity';

@Injectable()
export class UserService {
constructor(
// 依赖注入,@InjectRepository接收实体参数
// @Repository接收实体泛型
@InjectRepository(User) private readonly user: Repository<User>,
) {}

create(createUserDto: CreateUserDto) {
// 创建实体实例
const data = new User();
// 将DTO内容整理到实体实例身上
data.name = createUserDto.name;
data.desc = createUserDto.desc;
// 保存实体实例
return this.user.save(data);
}

async findAll(query: { keyWord: string; page: number; pageSize: number }) {
// 查询当前页
const list = await this.user.find({
// 查询条件
where: {
// like用于模糊查询
name: Like(`%${query.keyWord}%`),
},
// 排序方式
order: {
id: 'DESC',
},
// 分页查询
// 偏移量
skip: (query.page - 1) * query.pageSize,
// 数量
take: query.pageSize,
});
// 获取总页数
const total = await this.user.count({
where: {
name: Like(`%${query.keyWord}%`),
},
});
return {
list,
total,
};
}

update(id: number, updateUserDto: UpdateUserDto) {
// 更新
return this.user.update(id, updateUserDto);
}

remove(id: number) {
// 删除
return this.user.delete(id);
}
}

Module:

1
2
3
4
5
6
7
8
9
10
11
12
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';

@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}

DTO:

1
2
3
4
export class CreateUserDto {
name: string;
desc: string;
}

Entity:

1
2
3
4
5
6
7
8
9
10
11
import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ name: 'name' })
name: string;
@Column({ name: 'desc' })
desc: string;
}