feat: add bun-fullstack agent and update skills
This commit is contained in:
200
mock/comment.ts
Normal file
200
mock/comment.ts
Normal file
@@ -0,0 +1,200 @@
|
||||
import type { Request, Response } from 'express';
|
||||
import type {
|
||||
CommentItem,
|
||||
CommentStatus,
|
||||
CommentStatusUpdatePayload,
|
||||
} from '@/pages/CommentManagement/data';
|
||||
|
||||
const now = () => new Date().toISOString();
|
||||
|
||||
const parseString = (value: unknown): string | undefined => {
|
||||
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
||||
};
|
||||
|
||||
const COMMENT_STATUS_LIST: CommentStatus[] = [
|
||||
'pending',
|
||||
'approved',
|
||||
'rejected',
|
||||
'spam',
|
||||
];
|
||||
|
||||
const isCommentStatus = (value: unknown): value is CommentStatus => {
|
||||
return (
|
||||
typeof value === 'string' &&
|
||||
COMMENT_STATUS_LIST.includes(value as CommentStatus)
|
||||
);
|
||||
};
|
||||
|
||||
let commentList: CommentItem[] = [
|
||||
{
|
||||
id: 'cmt-1001',
|
||||
content: '这篇文章写得很实用,收藏了。',
|
||||
articleId: '1',
|
||||
articleTitle: '深入浅出 UmiJS 4 核心实战',
|
||||
userId: 'u-101',
|
||||
userName: '张伟',
|
||||
userAvatar: 'https://i.pravatar.cc/80?img=12',
|
||||
ipAddress: '10.12.3.8',
|
||||
status: 'approved',
|
||||
likeCount: 12,
|
||||
replyCount: 1,
|
||||
createdAt: '2024-02-14T10:18:00.000Z',
|
||||
updatedAt: '2024-02-14T10:18:00.000Z',
|
||||
},
|
||||
{
|
||||
id: 'cmt-1002',
|
||||
content: '能不能补一段关于路由权限控制的例子?',
|
||||
articleId: '1',
|
||||
articleTitle: '深入浅出 UmiJS 4 核心实战',
|
||||
userId: 'u-102',
|
||||
userName: '李娜',
|
||||
userAvatar: 'https://i.pravatar.cc/80?img=32',
|
||||
ipAddress: '10.12.9.21',
|
||||
status: 'pending',
|
||||
likeCount: 3,
|
||||
replyCount: 0,
|
||||
createdAt: '2024-02-14T10:45:00.000Z',
|
||||
updatedAt: '2024-02-14T10:45:00.000Z',
|
||||
},
|
||||
{
|
||||
id: 'cmt-1003',
|
||||
content: '文章不错,但封面图有点糊。',
|
||||
articleId: '2',
|
||||
articleTitle: 'Ant Design 5.0 设计趋势解析',
|
||||
userId: 'u-103',
|
||||
userName: '王强',
|
||||
userAvatar: 'https://i.pravatar.cc/80?img=7',
|
||||
ipAddress: '10.12.1.66',
|
||||
status: 'approved',
|
||||
likeCount: 1,
|
||||
replyCount: 0,
|
||||
createdAt: '2024-02-14T11:05:00.000Z',
|
||||
updatedAt: '2024-02-14T11:05:00.000Z',
|
||||
},
|
||||
{
|
||||
id: 'cmt-1004',
|
||||
content: '点这里领红包 http://example.com',
|
||||
articleId: '2',
|
||||
articleTitle: 'Ant Design 5.0 设计趋势解析',
|
||||
userId: 'u-104',
|
||||
userName: '匿名用户',
|
||||
ipAddress: '10.9.20.11',
|
||||
status: 'spam',
|
||||
likeCount: 0,
|
||||
replyCount: 0,
|
||||
createdAt: '2024-02-14T11:12:00.000Z',
|
||||
updatedAt: '2024-02-14T11:12:00.000Z',
|
||||
},
|
||||
{
|
||||
id: 'cmt-1005',
|
||||
content: '这条评论包含不当内容。',
|
||||
articleId: '1',
|
||||
articleTitle: '深入浅出 UmiJS 4 核心实战',
|
||||
userId: 'u-105',
|
||||
userName: '赵敏',
|
||||
userAvatar: 'https://i.pravatar.cc/80?img=19',
|
||||
ipAddress: '10.12.4.2',
|
||||
status: 'rejected',
|
||||
rejectReason: '包含不当词汇',
|
||||
likeCount: 0,
|
||||
replyCount: 0,
|
||||
createdAt: '2024-02-14T12:02:00.000Z',
|
||||
updatedAt: '2024-02-14T12:10:00.000Z',
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
'GET /api/comments': (req: Request, res: Response) => {
|
||||
const current = Number(req.query.current) || 1;
|
||||
const pageSize = Number(req.query.pageSize) || 10;
|
||||
const keyword = parseString(req.query.keyword);
|
||||
const status = parseString(req.query.status);
|
||||
const articleTitle = parseString(req.query.articleTitle);
|
||||
const userName = parseString(req.query.userName);
|
||||
|
||||
let filtered = [...commentList];
|
||||
|
||||
if (keyword) {
|
||||
filtered = filtered.filter(
|
||||
(item) =>
|
||||
item.content.includes(keyword) ||
|
||||
item.articleTitle.includes(keyword) ||
|
||||
item.userName.includes(keyword),
|
||||
);
|
||||
}
|
||||
|
||||
if (status && isCommentStatus(status)) {
|
||||
filtered = filtered.filter((item) => item.status === status);
|
||||
}
|
||||
|
||||
if (articleTitle) {
|
||||
filtered = filtered.filter((item) => item.articleTitle.includes(articleTitle));
|
||||
}
|
||||
|
||||
if (userName) {
|
||||
filtered = filtered.filter((item) => item.userName.includes(userName));
|
||||
}
|
||||
|
||||
const start = (current - 1) * pageSize;
|
||||
const data = filtered.slice(start, start + pageSize);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data,
|
||||
total: filtered.length,
|
||||
});
|
||||
},
|
||||
|
||||
'GET /api/comments/:id': (req: Request, res: Response) => {
|
||||
const { id } = req.params;
|
||||
const item = commentList.find((comment) => comment.id === id);
|
||||
|
||||
if (!item) {
|
||||
res.status(404).json({ success: false, message: '评论不存在' });
|
||||
return;
|
||||
}
|
||||
|
||||
res.json({ success: true, data: item });
|
||||
},
|
||||
|
||||
'PUT /api/comments/:id/status': (req: Request, res: Response) => {
|
||||
const { id } = req.params;
|
||||
const status = (req.body as any)?.status as unknown;
|
||||
const rejectReason = (req.body as any)?.rejectReason as unknown;
|
||||
const item = commentList.find((comment) => comment.id === id);
|
||||
|
||||
if (!item) {
|
||||
res.status(404).json({ success: false, message: '评论不存在' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isCommentStatus(status) || status === 'pending') {
|
||||
res.status(400).json({ success: false, message: '状态非法' });
|
||||
return;
|
||||
}
|
||||
|
||||
item.status = status;
|
||||
item.updatedAt = now();
|
||||
|
||||
if (status === 'rejected') {
|
||||
item.rejectReason = parseString(rejectReason) || '未填写原因';
|
||||
} else {
|
||||
item.rejectReason = undefined;
|
||||
}
|
||||
|
||||
res.json({ success: true });
|
||||
},
|
||||
|
||||
'DELETE /api/comments/:id': (req: Request, res: Response) => {
|
||||
const { id } = req.params;
|
||||
const index = commentList.findIndex((comment) => comment.id === id);
|
||||
|
||||
if (index === -1) {
|
||||
res.status(404).json({ success: false, message: '评论不存在' });
|
||||
return;
|
||||
}
|
||||
|
||||
commentList.splice(index, 1);
|
||||
res.json({ success: true });
|
||||
},
|
||||
};
|
||||
219
mock/vehicle.ts
Normal file
219
mock/vehicle.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import type { Request, Response } from 'express';
|
||||
import type {
|
||||
VehicleItem,
|
||||
VehicleListParams,
|
||||
VehicleStatus,
|
||||
VehicleType,
|
||||
} from '@/pages/VehicleManagement/data';
|
||||
|
||||
const now = () => new Date().toISOString();
|
||||
|
||||
const parseString = (value: unknown): string | undefined => {
|
||||
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
||||
};
|
||||
|
||||
const VEHICLE_STATUS_LIST: VehicleStatus[] = [
|
||||
'active',
|
||||
'inactive',
|
||||
'maintenance',
|
||||
'retired',
|
||||
];
|
||||
|
||||
const VEHICLE_TYPE_LIST: VehicleType[] = ['car', 'truck', 'van', 'bus', 'other'];
|
||||
|
||||
const isVehicleStatus = (value: unknown): value is VehicleStatus => {
|
||||
return (
|
||||
typeof value === 'string' &&
|
||||
VEHICLE_STATUS_LIST.includes(value as VehicleStatus)
|
||||
);
|
||||
};
|
||||
|
||||
const isVehicleType = (value: unknown): value is VehicleType => {
|
||||
return (
|
||||
typeof value === 'string' && VEHICLE_TYPE_LIST.includes(value as VehicleType)
|
||||
);
|
||||
};
|
||||
|
||||
let vehicleList: VehicleItem[] = [
|
||||
{
|
||||
id: 'vh-1001',
|
||||
plateNumber: '沪A·12345',
|
||||
brand: 'Tesla',
|
||||
model: 'Model 3',
|
||||
type: 'car',
|
||||
status: 'active',
|
||||
vin: '5YJ3E1EA7HF000001',
|
||||
ownerName: '张三',
|
||||
remark: '日常城市运营',
|
||||
createdAt: '2024-02-14T10:18:00.000Z',
|
||||
updatedAt: '2024-02-14T10:18:00.000Z',
|
||||
},
|
||||
{
|
||||
id: 'vh-1002',
|
||||
plateNumber: '沪B·67890',
|
||||
brand: 'BYD',
|
||||
model: '唐 DM-i',
|
||||
type: 'car',
|
||||
status: 'maintenance',
|
||||
ownerName: '李四',
|
||||
remark: '电池系统检查中',
|
||||
createdAt: '2024-02-14T11:05:00.000Z',
|
||||
updatedAt: '2024-02-14T11:30:00.000Z',
|
||||
},
|
||||
{
|
||||
id: 'vh-1003',
|
||||
plateNumber: '沪C·00001',
|
||||
brand: 'Mercedes-Benz',
|
||||
model: 'Sprinter',
|
||||
type: 'van',
|
||||
status: 'inactive',
|
||||
ownerName: '王五',
|
||||
remark: '备用车辆',
|
||||
createdAt: '2024-02-15T09:20:00.000Z',
|
||||
updatedAt: '2024-02-15T09:20:00.000Z',
|
||||
},
|
||||
];
|
||||
|
||||
const getQueryParams = (req: Request): VehicleListParams => {
|
||||
const { plateNumber, brand, status, type, current, pageSize } = req.query;
|
||||
|
||||
return {
|
||||
plateNumber: parseString(plateNumber),
|
||||
brand: parseString(brand),
|
||||
status: isVehicleStatus(status) ? status : undefined,
|
||||
type: isVehicleType(type) ? type : undefined,
|
||||
current: Number(current) || 1,
|
||||
pageSize: Number(pageSize) || 10,
|
||||
};
|
||||
};
|
||||
|
||||
export default {
|
||||
'GET /api/vehicles': (req: Request, res: Response) => {
|
||||
const { plateNumber, brand, status, type, current = 1, pageSize = 10 } =
|
||||
getQueryParams(req);
|
||||
|
||||
let filtered = [...vehicleList];
|
||||
|
||||
if (plateNumber) {
|
||||
filtered = filtered.filter((item) =>
|
||||
item.plateNumber.includes(plateNumber),
|
||||
);
|
||||
}
|
||||
|
||||
if (brand) {
|
||||
filtered = filtered.filter((item) => item.brand.includes(brand));
|
||||
}
|
||||
|
||||
if (status) {
|
||||
filtered = filtered.filter((item) => item.status === status);
|
||||
}
|
||||
|
||||
if (type) {
|
||||
filtered = filtered.filter((item) => item.type === type);
|
||||
}
|
||||
|
||||
const start = (current - 1) * pageSize;
|
||||
const data = filtered.slice(start, start + pageSize);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data,
|
||||
total: filtered.length,
|
||||
});
|
||||
},
|
||||
|
||||
'GET /api/vehicles/:id': (req: Request, res: Response) => {
|
||||
const { id } = req.params;
|
||||
const item = vehicleList.find((vehicle) => vehicle.id === id);
|
||||
|
||||
if (!item) {
|
||||
res.status(404).json({ success: false, message: '车辆不存在' });
|
||||
return;
|
||||
}
|
||||
|
||||
res.json({ success: true, data: item });
|
||||
},
|
||||
|
||||
'POST /api/vehicles': (req: Request, res: Response) => {
|
||||
const body = req.body as Partial<VehicleItem>;
|
||||
const id = `vh-${Math.floor(Math.random() * 9000 + 1000)}`;
|
||||
const timestamp = now();
|
||||
|
||||
const newItem: VehicleItem = {
|
||||
id,
|
||||
plateNumber: body.plateNumber || '',
|
||||
brand: body.brand || '',
|
||||
model: body.model || '',
|
||||
type: (body.type as VehicleType) || 'car',
|
||||
status: (body.status as VehicleStatus) || 'active',
|
||||
vin: body.vin,
|
||||
ownerName: body.ownerName,
|
||||
remark: body.remark,
|
||||
createdAt: timestamp,
|
||||
updatedAt: timestamp,
|
||||
};
|
||||
|
||||
vehicleList.unshift(newItem);
|
||||
|
||||
res.json({ success: true, data: newItem });
|
||||
},
|
||||
|
||||
'PUT /api/vehicles/:id': (req: Request, res: Response) => {
|
||||
const { id } = req.params;
|
||||
const body = req.body as Partial<VehicleItem>;
|
||||
const index = vehicleList.findIndex((vehicle) => vehicle.id === id);
|
||||
|
||||
if (index === -1) {
|
||||
res.status(404).json({ success: false, message: '车辆不存在' });
|
||||
return;
|
||||
}
|
||||
|
||||
const prev = vehicleList[index];
|
||||
const updated: VehicleItem = {
|
||||
...prev,
|
||||
...body,
|
||||
type: isVehicleType(body.type) ? body.type : prev.type,
|
||||
status: isVehicleStatus(body.status) ? body.status : prev.status,
|
||||
updatedAt: now(),
|
||||
};
|
||||
|
||||
vehicleList[index] = updated;
|
||||
|
||||
res.json({ success: true, data: updated });
|
||||
},
|
||||
|
||||
'PUT /api/vehicles/:id/status': (req: Request, res: Response) => {
|
||||
const { id } = req.params;
|
||||
const status = (req.body as any)?.status as unknown;
|
||||
const item = vehicleList.find((vehicle) => vehicle.id === id);
|
||||
|
||||
if (!item) {
|
||||
res.status(404).json({ success: false, message: '车辆不存在' });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isVehicleStatus(status)) {
|
||||
res.status(400).json({ success: false, message: '状态非法' });
|
||||
return;
|
||||
}
|
||||
|
||||
item.status = status;
|
||||
item.updatedAt = now();
|
||||
|
||||
res.json({ success: true });
|
||||
},
|
||||
|
||||
'DELETE /api/vehicles/:id': (req: Request, res: Response) => {
|
||||
const { id } = req.params;
|
||||
const index = vehicleList.findIndex((vehicle) => vehicle.id === id);
|
||||
|
||||
if (index === -1) {
|
||||
res.status(404).json({ success: false, message: '车辆不存在' });
|
||||
return;
|
||||
}
|
||||
|
||||
vehicleList.splice(index, 1);
|
||||
res.json({ success: true });
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user