提交
This commit is contained in:
@@ -11,183 +11,16 @@ const dayjs = require('dayjs');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* components:
|
||||
* schemas:
|
||||
* Transfer:
|
||||
* type: object
|
||||
* properties:
|
||||
* id:
|
||||
* type: integer
|
||||
* description: 转账记录ID
|
||||
* user_id:
|
||||
* type: integer
|
||||
* description: 用户ID
|
||||
* recipient_id:
|
||||
* type: integer
|
||||
* description: 接收方用户ID
|
||||
* amount:
|
||||
* type: number
|
||||
* format: float
|
||||
* description: 转账金额
|
||||
* status:
|
||||
* type: string
|
||||
* enum: [pending, completed, failed, cancelled]
|
||||
* description: 转账状态
|
||||
* transfer_type:
|
||||
* type: string
|
||||
* enum: [user_to_user, user_to_system, system_to_user]
|
||||
* description: 转账类型
|
||||
* voucher_image:
|
||||
* type: string
|
||||
* description: 转账凭证图片路径
|
||||
* remark:
|
||||
* type: string
|
||||
* description: 转账备注
|
||||
* created_at:
|
||||
* type: string
|
||||
* format: date-time
|
||||
* description: 创建时间
|
||||
* updated_at:
|
||||
* type: string
|
||||
* format: date-time
|
||||
* description: 更新时间
|
||||
* Pagination:
|
||||
* type: object
|
||||
* properties:
|
||||
* total:
|
||||
* type: integer
|
||||
* description: 总记录数
|
||||
* page:
|
||||
* type: integer
|
||||
* description: 当前页码
|
||||
* limit:
|
||||
* type: integer
|
||||
* description: 每页记录数
|
||||
* total_pages:
|
||||
* type: integer
|
||||
* description: 总页数
|
||||
*/
|
||||
|
||||
// 配置文件上传
|
||||
const storage = multer.diskStorage({
|
||||
destination: function (req, file, cb) {
|
||||
cb(null, 'uploads/')
|
||||
},
|
||||
filename: function (req, file, cb) {
|
||||
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
|
||||
cb(null, 'voucher-' + uniqueSuffix + path.extname(file.originalname))
|
||||
}
|
||||
});
|
||||
|
||||
const upload = multer({
|
||||
storage: storage,
|
||||
fileFilter: (req, file, cb) => {
|
||||
if (file.mimetype.startsWith('image/')) {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(new Error('只允许上传图片文件'));
|
||||
}
|
||||
},
|
||||
limits: {
|
||||
fileSize: 5 * 1024 * 1024 // 5MB
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /transfers:
|
||||
* get:
|
||||
* summary: 获取转账列表
|
||||
* tags: [Transfers]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: status
|
||||
* schema:
|
||||
* type: string
|
||||
* description: 转账状态过滤
|
||||
* - in: query
|
||||
* name: transfer_type
|
||||
* schema:
|
||||
* type: string
|
||||
* description: 转账类型过滤
|
||||
* - in: query
|
||||
* name: start_date
|
||||
* schema:
|
||||
* type: string
|
||||
* format: date
|
||||
* description: 开始日期过滤
|
||||
* - in: query
|
||||
* name: end_date
|
||||
* schema:
|
||||
* type: string
|
||||
* format: date
|
||||
* description: 结束日期过滤
|
||||
* - in: query
|
||||
* name: search
|
||||
* schema:
|
||||
* type: string
|
||||
* description: 搜索关键词(用户名或真实姓名)
|
||||
* - in: query
|
||||
* name: page
|
||||
* schema:
|
||||
* type: integer
|
||||
* default: 1
|
||||
* description: 页码
|
||||
* - in: query
|
||||
* name: limit
|
||||
* schema:
|
||||
* type: integer
|
||||
* default: 10
|
||||
* description: 每页数量
|
||||
* - in: query
|
||||
* name: sort
|
||||
* schema:
|
||||
* type: string
|
||||
* description: 排序字段
|
||||
* - in: query
|
||||
* name: order
|
||||
* schema:
|
||||
* type: string
|
||||
* enum: [asc, desc]
|
||||
* description: 排序方向
|
||||
* responses:
|
||||
* 200:
|
||||
* description: 成功获取转账列表
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* data:
|
||||
* type: object
|
||||
* properties:
|
||||
* transfers:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/Transfer'
|
||||
* pagination:
|
||||
* $ref: '#/components/schemas/Pagination'
|
||||
* 401:
|
||||
* description: 未授权
|
||||
* 500:
|
||||
* description: 服务器错误
|
||||
*/
|
||||
router.get('/',
|
||||
authenticateToken,
|
||||
validateQuery(transferSchemas.query),
|
||||
async (req, res, next) => {
|
||||
try {
|
||||
const { page, limit, status, transfer_type, start_date, end_date, search, sort, order } = req.query;
|
||||
const { page, limit, status, start_date, end_date, search, sort, order } = req.query;
|
||||
|
||||
const filters = {
|
||||
status,
|
||||
transfer_type,
|
||||
start_date,
|
||||
end_date,
|
||||
search
|
||||
@@ -216,84 +49,38 @@ router.get('/',
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /transfers/list:
|
||||
* get:
|
||||
* summary: 获取转账记录列表
|
||||
* tags: [Transfers]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: status
|
||||
* schema:
|
||||
* type: string
|
||||
* description: 转账状态过滤
|
||||
* - in: query
|
||||
* name: transfer_type
|
||||
* schema:
|
||||
* type: string
|
||||
* description: 转账类型过滤
|
||||
* - in: query
|
||||
* name: start_date
|
||||
* schema:
|
||||
* type: string
|
||||
* format: date
|
||||
* description: 开始日期过滤
|
||||
* - in: query
|
||||
* name: end_date
|
||||
* schema:
|
||||
* type: string
|
||||
* format: date
|
||||
* description: 结束日期过滤
|
||||
* - in: query
|
||||
* name: page
|
||||
* schema:
|
||||
* type: integer
|
||||
* default: 1
|
||||
* description: 页码
|
||||
* - in: query
|
||||
* name: limit
|
||||
* schema:
|
||||
* type: integer
|
||||
* default: 10
|
||||
* description: 每页数量
|
||||
* - in: query
|
||||
* name: sort
|
||||
* schema:
|
||||
* type: string
|
||||
* description: 排序字段
|
||||
* - in: query
|
||||
* name: order
|
||||
* schema:
|
||||
* type: string
|
||||
* enum: [asc, desc]
|
||||
* description: 排序方向
|
||||
* responses:
|
||||
* 200:
|
||||
* description: 成功获取转账记录列表
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* data:
|
||||
* type: object
|
||||
* properties:
|
||||
* transfers:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/Transfer'
|
||||
* pagination:
|
||||
* $ref: '#/components/schemas/Pagination'
|
||||
* 401:
|
||||
* description: 未授权
|
||||
* 500:
|
||||
* description: 服务器错误
|
||||
*/
|
||||
router.get('/history',authenticateToken,async (req, res, next) => {
|
||||
try {
|
||||
const { page, limit, start_date, end_date, search, sort, order } = req.query;
|
||||
|
||||
const filters = {
|
||||
start_date,
|
||||
end_date,
|
||||
search
|
||||
};
|
||||
|
||||
// 非管理员只能查看自己相关的转账
|
||||
if (req.user.role !== 'admin') {
|
||||
filters.user_id = req.user.id;
|
||||
}
|
||||
|
||||
const result = await transferService.getTransfersHistory(filters, { page, limit, sort, order });
|
||||
|
||||
logger.info('Transfer list requested', {
|
||||
userId: req.user.id,
|
||||
filters,
|
||||
resultCount: result.transfers.length
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
})
|
||||
|
||||
router.get('/list',
|
||||
authenticateToken,
|
||||
validateQuery(transferSchemas.query),
|
||||
@@ -331,49 +118,7 @@ router.get('/list',
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /transfers/public-account:
|
||||
* get:
|
||||
* summary: 获取公户信息
|
||||
* tags: [Transfers]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: 成功获取公户信息
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* example: true
|
||||
* data:
|
||||
* type: object
|
||||
* properties:
|
||||
* id:
|
||||
* type: integer
|
||||
* description: 公户ID
|
||||
* username:
|
||||
* type: string
|
||||
* description: 公户用户名
|
||||
* example: public_account
|
||||
* real_name:
|
||||
* type: string
|
||||
* description: 公户名称
|
||||
* balance:
|
||||
* type: number
|
||||
* format: float
|
||||
* description: 公户余额
|
||||
* 401:
|
||||
* description: 未授权
|
||||
* 404:
|
||||
* description: 公户不存在
|
||||
* 500:
|
||||
* description: 服务器错误
|
||||
*/
|
||||
|
||||
router.get('/public-account', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const db = getDB();
|
||||
@@ -394,66 +139,7 @@ router.get('/public-account', authenticateToken, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /transfers/create:
|
||||
* post:
|
||||
* summary: 创建转账记录
|
||||
* tags: [Transfers]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - to_user_id
|
||||
* - amount
|
||||
* - transfer_type
|
||||
* properties:
|
||||
* to_user_id:
|
||||
* type: integer
|
||||
* description: 接收方用户ID
|
||||
* amount:
|
||||
* type: number
|
||||
* format: float
|
||||
* description: 转账金额
|
||||
* transfer_type:
|
||||
* type: string
|
||||
* enum: [user_to_user, user_to_system, system_to_user]
|
||||
* description: 转账类型
|
||||
* remark:
|
||||
* type: string
|
||||
* description: 转账备注
|
||||
* responses:
|
||||
* 201:
|
||||
* description: 转账记录创建成功
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* example: true
|
||||
* message:
|
||||
* type: string
|
||||
* example: 转账记录创建成功,等待确认
|
||||
* data:
|
||||
* type: object
|
||||
* properties:
|
||||
* transfer_id:
|
||||
* type: integer
|
||||
* description: 转账记录ID
|
||||
* 400:
|
||||
* description: 请求参数错误
|
||||
* 401:
|
||||
* description: 未授权
|
||||
* 500:
|
||||
* description: 服务器错误
|
||||
*/
|
||||
|
||||
router.post('/create',
|
||||
authenticateToken,
|
||||
validate(transferSchemas.create),
|
||||
@@ -478,72 +164,7 @@ router.post('/create',
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /transfers/admin/create:
|
||||
* post:
|
||||
* summary: 管理员创建转账记录
|
||||
* tags: [Transfers]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - from_user_id
|
||||
* - to_user_id
|
||||
* - amount
|
||||
* - transfer_type
|
||||
* properties:
|
||||
* from_user_id:
|
||||
* type: integer
|
||||
* description: 发送方用户ID
|
||||
* to_user_id:
|
||||
* type: integer
|
||||
* description: 接收方用户ID
|
||||
* amount:
|
||||
* type: number
|
||||
* format: float
|
||||
* description: 转账金额
|
||||
* transfer_type:
|
||||
* type: string
|
||||
* enum: [user_to_user, user_to_system, system_to_user]
|
||||
* description: 转账类型
|
||||
* description:
|
||||
* type: string
|
||||
* description: 转账描述
|
||||
* responses:
|
||||
* 201:
|
||||
* description: 转账记录创建成功
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* example: true
|
||||
* message:
|
||||
* type: string
|
||||
* example: 转账记录创建成功
|
||||
* data:
|
||||
* type: object
|
||||
* properties:
|
||||
* transfer_id:
|
||||
* type: integer
|
||||
* description: 转账记录ID
|
||||
* 400:
|
||||
* description: 请求参数错误
|
||||
* 401:
|
||||
* description: 未授权
|
||||
* 403:
|
||||
* description: 权限不足
|
||||
* 500:
|
||||
* description: 服务器错误
|
||||
*/
|
||||
|
||||
router.post('/admin/create',
|
||||
authenticateToken,
|
||||
async (req, res, next) => {
|
||||
|
||||
Reference in New Issue
Block a user