2026-05-26 13:37:55 +08:00
|
|
|
const { query } = require('../config/database')
|
|
|
|
|
|
2026-06-03 14:15:55 +08:00
|
|
|
function currentUserId(ctx) {
|
|
|
|
|
return ctx.state.user ? ctx.state.user.id : null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ensureOwner(ctx, row, action) {
|
|
|
|
|
if (!row) return true
|
|
|
|
|
if (ctx.state.user.role === 2) return true
|
|
|
|
|
return row.user_id === currentUserId(ctx)
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-26 13:37:55 +08:00
|
|
|
async function getAddresses(ctx) {
|
2026-06-03 14:15:55 +08:00
|
|
|
const userId = currentUserId(ctx)
|
2026-05-26 13:37:55 +08:00
|
|
|
if (!userId) {
|
2026-06-03 14:15:55 +08:00
|
|
|
ctx.status = 401
|
|
|
|
|
ctx.body = { code: 401, message: '未登录' }
|
2026-05-26 13:37:55 +08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const rows = await query(
|
|
|
|
|
'SELECT * FROM addresses WHERE user_id = ? ORDER BY is_default DESC, created_at DESC',
|
|
|
|
|
[userId]
|
|
|
|
|
)
|
|
|
|
|
ctx.body = { code: 200, data: rows }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function getAddressById(ctx) {
|
|
|
|
|
const id = ctx.params.id
|
|
|
|
|
const rows = await query('SELECT * FROM addresses WHERE id = ?', [id])
|
2026-06-03 14:15:55 +08:00
|
|
|
if (rows.length === 0) {
|
|
|
|
|
ctx.status = 404
|
2026-05-26 13:37:55 +08:00
|
|
|
ctx.body = { code: 404, message: '地址不存在' }
|
2026-06-03 14:15:55 +08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!ensureOwner(ctx, rows[0])) {
|
|
|
|
|
ctx.status = 403
|
|
|
|
|
ctx.body = { code: 403, message: '无权查看该地址' }
|
|
|
|
|
return
|
2026-05-26 13:37:55 +08:00
|
|
|
}
|
2026-06-03 14:15:55 +08:00
|
|
|
ctx.body = { code: 200, data: rows[0] }
|
2026-05-26 13:37:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function createAddress(ctx) {
|
2026-06-03 14:15:55 +08:00
|
|
|
const userId = currentUserId(ctx)
|
|
|
|
|
if (!userId) {
|
|
|
|
|
ctx.status = 401
|
|
|
|
|
ctx.body = { code: 401, message: '未登录' }
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const { name, phone, region, detail, is_default = 0 } = ctx.request.body || {}
|
2026-05-26 13:37:55 +08:00
|
|
|
|
2026-06-03 14:15:55 +08:00
|
|
|
if (!name || !phone || !detail) {
|
2026-05-26 13:37:55 +08:00
|
|
|
ctx.body = { code: 400, message: '缺少必填参数' }
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-06-03 14:15:55 +08:00
|
|
|
if (!/^1\d{10}$/.test(phone)) {
|
|
|
|
|
ctx.body = { code: 400, message: '手机号格式错误' }
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-05-26 13:37:55 +08:00
|
|
|
|
|
|
|
|
if (is_default) {
|
2026-06-03 14:15:55 +08:00
|
|
|
await query('UPDATE addresses SET is_default = 0 WHERE user_id = ?', [userId])
|
2026-05-26 13:37:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await query(
|
|
|
|
|
'INSERT INTO addresses (user_id, name, phone, region, detail, is_default) VALUES (?, ?, ?, ?, ?, ?)',
|
2026-06-03 14:15:55 +08:00
|
|
|
[userId, name, phone, region || '', detail, is_default ? 1 : 0]
|
2026-05-26 13:37:55 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
ctx.body = { code: 200, data: { id: result.insertId } }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function updateAddress(ctx) {
|
|
|
|
|
const id = ctx.params.id
|
2026-06-03 14:15:55 +08:00
|
|
|
const updates = ctx.request.body || {}
|
2026-05-26 13:37:55 +08:00
|
|
|
|
|
|
|
|
const current = await query('SELECT * FROM addresses WHERE id = ?', [id])
|
2026-06-03 14:15:55 +08:00
|
|
|
if (current.length === 0) {
|
|
|
|
|
ctx.status = 404
|
2026-05-26 13:37:55 +08:00
|
|
|
ctx.body = { code: 404, message: '地址不存在' }
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-06-03 14:15:55 +08:00
|
|
|
if (!ensureOwner(ctx, current[0])) {
|
|
|
|
|
ctx.status = 403
|
|
|
|
|
ctx.body = { code: 403, message: '无权修改该地址' }
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-05-26 13:37:55 +08:00
|
|
|
|
|
|
|
|
if (updates.is_default) {
|
|
|
|
|
await query('UPDATE addresses SET is_default = 0 WHERE user_id = ?', [current[0].user_id])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const fields = []
|
|
|
|
|
const params = []
|
|
|
|
|
for (const key of ['name', 'phone', 'region', 'detail', 'is_default']) {
|
|
|
|
|
if (updates[key] !== undefined) {
|
2026-06-03 14:15:55 +08:00
|
|
|
if (key === 'phone' && !/^1\d{10}$/.test(updates[key])) {
|
|
|
|
|
ctx.body = { code: 400, message: '手机号格式错误' }
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-05-26 13:37:55 +08:00
|
|
|
fields.push(`${key} = ?`)
|
|
|
|
|
params.push(key === 'is_default' ? (updates[key] ? 1 : 0) : updates[key])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fields.length > 0) {
|
|
|
|
|
params.push(id)
|
|
|
|
|
await query(`UPDATE addresses SET ${fields.join(', ')} WHERE id = ?`, params)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const updated = await query('SELECT * FROM addresses WHERE id = ?', [id])
|
|
|
|
|
ctx.body = { code: 200, data: updated[0] }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function deleteAddress(ctx) {
|
|
|
|
|
const id = ctx.params.id
|
2026-06-03 14:15:55 +08:00
|
|
|
const current = await query('SELECT user_id FROM addresses WHERE id = ?', [id])
|
|
|
|
|
if (current.length === 0) {
|
|
|
|
|
ctx.status = 404
|
|
|
|
|
ctx.body = { code: 404, message: '地址不存在' }
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (!ensureOwner(ctx, current[0])) {
|
|
|
|
|
ctx.status = 403
|
|
|
|
|
ctx.body = { code: 403, message: '无权删除该地址' }
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-05-26 13:37:55 +08:00
|
|
|
await query('DELETE FROM addresses WHERE id = ?', [id])
|
|
|
|
|
ctx.body = { code: 200, message: '删除成功' }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function setDefault(ctx) {
|
|
|
|
|
const id = ctx.params.id
|
|
|
|
|
const rows = await query('SELECT * FROM addresses WHERE id = ?', [id])
|
|
|
|
|
|
2026-06-03 14:15:55 +08:00
|
|
|
if (rows.length === 0) {
|
|
|
|
|
ctx.status = 404
|
2026-05-26 13:37:55 +08:00
|
|
|
ctx.body = { code: 404, message: '地址不存在' }
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-06-03 14:15:55 +08:00
|
|
|
if (!ensureOwner(ctx, rows[0])) {
|
|
|
|
|
ctx.status = 403
|
|
|
|
|
ctx.body = { code: 403, message: '无权操作该地址' }
|
|
|
|
|
return
|
|
|
|
|
}
|
2026-05-26 13:37:55 +08:00
|
|
|
|
|
|
|
|
await query('UPDATE addresses SET is_default = 0 WHERE user_id = ?', [rows[0].user_id])
|
|
|
|
|
await query('UPDATE addresses SET is_default = 1 WHERE id = ?', [id])
|
|
|
|
|
|
|
|
|
|
ctx.body = { code: 200, message: '设置成功' }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
getAddresses,
|
|
|
|
|
getAddressById,
|
|
|
|
|
createAddress,
|
|
|
|
|
updateAddress,
|
|
|
|
|
deleteAddress,
|
|
|
|
|
setDefault
|
|
|
|
|
}
|