Files
jurong_circle_black/routes/addresses.js
2025-09-02 09:29:20 +08:00

567 lines
16 KiB
JavaScript

const express = require('express');
const router = express.Router();
const { getDB } = require('../database');
const { auth } = require('../middleware/auth');
/**
* @swagger
* components:
* schemas:
* Address:
* type: object
* properties:
* id:
* type: integer
* description: 地址ID
* user_id:
* type: integer
* description: 用户ID
* recipient_name:
* type: string
* description: 收件人姓名
* phone:
* type: string
* description: 联系电话
* province_code:
* type: string
* description: 省份编码
* province_name:
* type: string
* description: 省份名称
* city_code:
* type: string
* description: 城市编码
* city_name:
* type: string
* description: 城市名称
* district_code:
* type: string
* description: 区县编码
* district_name:
* type: string
* description: 区县名称
* detailed_address:
* type: string
* description: 详细地址
* postal_code:
* type: string
* description: 邮政编码
* label_id:
* type: integer
* description: 地址标签ID
* is_default:
* type: boolean
* description: 是否为默认地址
* label_name:
* type: string
* description: 标签名称
* label_color:
* type: string
* description: 标签颜色
* required:
* - recipient_name
* - phone
* - province_code
* - province_name
* - city_code
* - city_name
* - district_code
* - district_name
* - detailed_address
*/
/**
* @swagger
* /addresses:
* get:
* summary: 获取用户收货地址列表
* tags: [Addresses]
* security:
* - bearerAuth: []
* responses:
* 200:
* description: 成功获取地址列表
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* type: array
* items:
* $ref: '#/components/schemas/Address'
* 401:
* description: 未授权
* 500:
* description: 服务器错误
*/
router.get('/', auth, async (req, res) => {
try {
const userId = req.user.id;
const [addresses] = await getDB().execute(
`SELECT ua.*, al.name as label_name, al.color as label_color,
p.name as province_name, c.name as city_name, d.name as district_name
FROM user_addresses ua
LEFT JOIN address_labels al ON ua.label = al.id
LEFT JOIN china_regions p ON ua.province = p.code
LEFT JOIN china_regions c ON ua.city = c.code
LEFT JOIN china_regions d ON ua.district = d.code
WHERE ua.user_id = ?
ORDER BY ua.is_default DESC, ua.created_at DESC`,
[userId]
);
res.json({
success: true,
data: addresses
});
} catch (error) {
console.error('获取收货地址列表错误:', error);
res.status(500).json({ message: '获取收货地址列表失败' });
}
});
/**
* @swagger
* /addresses/{id}:
* get:
* summary: 获取单个收货地址详情
* tags: [Addresses]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 地址ID
* responses:
* 200:
* description: 成功获取地址详情
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* data:
* $ref: '#/components/schemas/Address'
* 401:
* description: 未授权
* 404:
* description: 地址不存在
* 500:
* description: 服务器错误
*/
router.get('/:id', auth, async (req, res) => {
try {
const addressId = req.params.id;
const userId = req.user.id;
const [addresses] = await getDB().execute(
`SELECT ua.*, al.name as label_name, al.color as label_color
FROM user_addresses ua
LEFT JOIN address_labels al ON ua.label_id = al.id
WHERE ua.id = ? AND ua.user_id = ? AND ua.deleted_at IS NULL`,
[addressId, userId]
);
if (addresses.length === 0) {
return res.status(404).json({ message: '收货地址不存在' });
}
res.json({
success: true,
data: addresses[0]
});
} catch (error) {
console.error('获取收货地址详情错误:', error);
res.status(500).json({ message: '获取收货地址详情失败' });
}
});
/**
* @swagger
* /addresses:
* post:
* summary: 创建收货地址
* tags: [Addresses]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* recipient_name:
* type: string
* description: 收件人姓名
* phone:
* type: string
* description: 联系电话
* province_code:
* type: string
* description: 省份编码
* province_name:
* type: string
* description: 省份名称
* city_code:
* type: string
* description: 城市编码
* city_name:
* type: string
* description: 城市名称
* district_code:
* type: string
* description: 区县编码
* district_name:
* type: string
* description: 区县名称
* detailed_address:
* type: string
* description: 详细地址
* postal_code:
* type: string
* description: 邮政编码
* label_id:
* type: integer
* description: 地址标签ID
* is_default:
* type: boolean
* description: 是否为默认地址
* required:
* - recipient_name
* - phone
* - province_code
* - province_name
* - city_code
* - city_name
* - district_code
* - district_name
* - detailed_address
* responses:
* 201:
* description: 地址创建成功
* 400:
* description: 请求参数错误
* 401:
* description: 未授权
* 500:
* description: 服务器错误
*/
router.post('/', auth, async (req, res) => {
try {
const userId = req.user.id;
const {
recipient_name,
phone,
province_code,
city_code,
district_code,
detailed_address,
is_default = false
} = req.body;
// 验证必填字段
if (!recipient_name || !phone || !province_code || !city_code || !district_code || !detailed_address) {
return res.status(400).json({ message: '收件人姓名、电话、省市区和详细地址不能为空' });
}
// 如果设置为默认地址,先取消其他默认地址
if (is_default) {
await getDB().execute(
'UPDATE user_addresses SET is_default = false WHERE user_id = ? ',
[userId]
);
}
const [result] = await getDB().execute(
`INSERT INTO user_addresses (
user_id, receiver_name, receiver_phone, province, city,
district, detailed_address, is_default, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())`,
[
userId, recipient_name, phone, province_code, city_code,
district_code, detailed_address, is_default
]
);
res.status(201).json({
success: true,
message: '收货地址创建成功',
data: { addressId: result.insertId }
});
} catch (error) {
console.error('创建收货地址错误:', error);
res.status(500).json({ message: '创建收货地址失败' });
}
});
/**
* @swagger
* /addresses/{id}:
* put:
* summary: 更新收货地址
* tags: [Addresses]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 地址ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* recipient_name:
* type: string
* description: 收件人姓名
* phone:
* type: string
* description: 联系电话
* province_code:
* type: string
* description: 省份编码
* province_name:
* type: string
* description: 省份名称
* city_code:
* type: string
* description: 城市编码
* city_name:
* type: string
* description: 城市名称
* district_code:
* type: string
* description: 区县编码
* district_name:
* type: string
* description: 区县名称
* detailed_address:
* type: string
* description: 详细地址
* postal_code:
* type: string
* description: 邮政编码
* label_id:
* type: integer
* description: 地址标签ID
* is_default:
* type: boolean
* description: 是否为默认地址
* responses:
* 200:
* description: 地址更新成功
* 400:
* description: 请求参数错误
* 401:
* description: 未授权
* 404:
* description: 地址不存在
* 500:
* description: 服务器错误
*/
router.put('/:id', auth, async (req, res) => {
try {
const addressId = req.params.id;
const userId = req.user.id;
const {
recipient_name,
phone,
province_code,
city_code,
district_code,
detailed_address,
is_default
} = req.body;
if (!recipient_name || !phone || !province_code || !city_code || !district_code || !detailed_address) {
return res.status(400).json({ message: '收件人姓名、电话、省市区和详细地址不能为空' });
}
// 检查地址是否存在且属于当前用户
const [existing] = await getDB().execute(
'SELECT id FROM user_addresses WHERE id = ? AND user_id = ? ',
[addressId, userId]
);
if (existing.length === 0) {
return res.status(404).json({ message: '收货地址不存在' });
}
// 如果设置为默认地址,先取消其他默认地址
if (is_default) {
await getDB().execute(
'UPDATE user_addresses SET is_default = false WHERE user_id = ? AND id != ? ',
[userId, addressId]
);
}
const [result] = await getDB().execute(
`UPDATE user_addresses SET
receiver_name = ?, receiver_phone = ?, province = ?, city = ?,
district = ?, detailed_address = ?, is_default = ?, updated_at = NOW()
WHERE id = ? AND user_id = ?`,
[
recipient_name, phone, province_code, city_code,
district_code, detailed_address, is_default,
addressId, userId
]
);
res.json({
success: true,
message: '收货地址更新成功'
});
} catch (error) {
console.error('更新收货地址错误:', error);
res.status(500).json({ message: '更新收货地址失败' });
}
});
/**
* @swagger
* /addresses/{id}:
* delete:
* summary: 删除收货地址
* tags: [Addresses]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 地址ID
* responses:
* 200:
* description: 地址删除成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: 收货地址删除成功
* 401:
* description: 未授权
* 404:
* description: 地址不存在
* 500:
* description: 服务器错误
*/
router.delete('/:id', auth, async (req, res) => {
try {
const addressId = req.params.id;
const userId = req.user.id;
const [result] = await getDB().execute(
'DELETE FROM user_addresses WHERE id = ? AND user_id = ?',
[addressId, userId]
);
if (result.affectedRows === 0) {
return res.status(404).json({ message: '收货地址不存在' });
}
res.json({
success: true,
message: '收货地址删除成功'
});
} catch (error) {
console.error('删除收货地址错误:', error);
res.status(500).json({ message: '删除收货地址失败' });
}
});
/**
* @swagger
* /addresses/{id}/default:
* put:
* summary: 设置默认地址
* tags: [Addresses]
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: 地址ID
* responses:
* 200:
* description: 默认地址设置成功
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* message:
* type: string
* example: 默认地址设置成功
* 401:
* description: 未授权
* 404:
* description: 地址不存在
* 500:
* description: 服务器错误
*/
router.put('/:id/default', auth, async (req, res) => {
try {
const addressId = req.params.id;
const userId = req.user.id;
// 检查地址是否存在且属于当前用户
const [existing] = await getDB().execute(
'SELECT id FROM user_addresses WHERE id = ? AND user_id = ? AND deleted_at IS NULL',
[addressId, userId]
);
if (existing.length === 0) {
return res.status(404).json({ message: '收货地址不存在' });
}
// 取消其他默认地址
await getDB().execute(
'UPDATE user_addresses SET is_default = false WHERE user_id = ? AND deleted_at IS NULL',
[userId]
);
// 设置当前地址为默认
await getDB().execute(
'UPDATE user_addresses SET is_default = true WHERE id = ? AND user_id = ?',
[addressId, userId]
);
res.json({
success: true,
message: '默认地址设置成功'
});
} catch (error) {
console.error('设置默认地址错误:', error);
res.status(500).json({ message: '设置默认地址失败' });
}
});
module.exports = router;