280 lines
9.4 KiB
JavaScript
Raw Permalink Normal View History

2026-07-27 11:28:33 +08:00
const validator = require('../../utils/validator.js');
const Sm4Util = require('../../utils/sm4-util');
const { ObjectId } = require('mongodb');
const dayjs = require('dayjs');
exports.main = async ({ type, ...item }, db) => {
switch (type) {
case 'addAddress':
return await addAddress(item, db);
case 'updateAddress':
return await updateAddress(item, db);
case 'deleteAddress':
return await deleteAddress(item, db);
case 'getAddressList':
return await getAddressList(item, db);
case 'getDefaultAddress':
return await getDefaultAddress(item, db);
}
}
function verify(data) {
const { name, phone, address, accountId, latitude, longitude } = data || {};
const region = data && Array.isArray(data.region) ? data.region.filter(i => typeof i === 'string' && i.trim()) : [];
if (!(region.length > 1 && region.length < 4)) {
return { success: false, message: '省市区信息不正确' };
}
if (typeof address !== 'string' || address.trim() === '') {
return { success: false, message: '详细地址不能为空' };
}
if (typeof latitude !== 'number' || typeof longitude !== 'number') {
return { success: false, message: '经纬度信息不正确' };
}
if (!(latitude > 0 && longitude > 0)) {
return { success: false, message: '经纬度信息不正确' };
}
if (address.trim().length > 100) {
return { success: false, message: '详细地址最多100个字' };
}
if (typeof name !== 'string' || name.trim() === '') {
return { success: false, message: '收货人不能为空' };
}
if (name.trim().length > 20) {
return { success: false, message: '收货人最多20个字' };
}
if (typeof phone !== 'string' || phone.trim() === '') {
return { success: false, message: '手机号不能为空' };
}
if (!validator.isMobile(phone.trim())) {
return { success: false, message: '手机号格式不正确' };
}
if (typeof accountId !== 'string' || accountId.trim() === '') {
return { success: false, message: '账户ID不能为空' };
}
const docData = {
region,
address,
name: Sm4Util.encryptDataForSm3(name.trim()),
phone: Sm4Util.encryptDataForSm3(phone.trim()),
latitude,
longitude,
accountId: accountId.trim(),
}
if (typeof data.isDefault === 'boolean') {
docData.isDefault = data.isDefault
}
return { success: true, message: '验证通过', data: docData };
}
async function addAddress(item, db) {
try {
const { success, message, data } = verify(item);
if (success) {
const count = await db.collection('address').countDocuments({ accountId: data.accountId, disabled: false });
if (count >= 3) {
return { success: false, message: '每人最多可保存3个常用地址' };
}
data.createTime = Date.now();
data.updateTime = Date.now();
data.disabled = false;
if (data.isDefault) {
await db.collection('address').updateMany({ accountId: data.accountId }, { $set: { isDefault: false } });
}
const res = await db.collection('address').insertOne(data);
return { success: true, message: '新增地址成功', id: res.insertedId };
}
return { success, message };
} catch (e) {
return { success: false, message: e.message };
}
}
async function updateAddress(item, db) {
try {
if (typeof item.id !== 'string' || item.id.trim() === '') {
return { success: false, message: '地址ID不能为空' };
}
const { success, message, data } = verify(item);
if (success) {
const address = await db.collection('address').findOne({ _id: new ObjectId(item.id), accountId: data.accountId, disabled: false });
if (!address) {
return { success: false, message: '地址不存在或者账户id不匹配' };
}
const modified = checkModified(address, data);
if (modified) {
data.lockTime = dayjs().add(30, 'day').valueOf();
const lockTime = await getLockTime(data.accountId, db);
if (lockTime) {
return { success: false, message: `地址信息已被锁定, ${lockTime}前无法修改` };
}
}
data.updateTime = Date.now();
if (data.isDefault) {
await db.collection('address').updateMany({ accountId: data.accountId, _id: { $ne: new ObjectId(item.id) } }, { $set: { isDefault: false } });
}
const res = await db.collection('address').updateOne({ _id: new ObjectId(item.id) }, { $set: data });
if (res.modifiedCount > 0) {
await saveAddressHistory(address, data, 'update', db);
return { success: true, message: '更新地址成功' };
}
return { success: false, message: '更新地址失败' };
}
return { success, message };
} catch (e) {
return { success: false, message: e.message };
}
}
async function deleteAddress(item, db) {
try {
if (typeof item.id !== 'string' || item.id.trim() === '') {
return { success: false, message: '地址ID不能为空' };
}
if (typeof item.accountId !== 'string' || item.accountId.trim() === '') {
return { success: false, message: '账户ID不能为空' };
}
const lockTime = await getLockTime(item.accountId, db);
if (lockTime) {
return { success: false, message: `地址信息已被锁定, ${lockTime}前无法删除` };
}
const address = await db.collection('address').findOne({ _id: new ObjectId(item.id), accountId: item.accountId.trim(), disabled: false });
if (!address) {
return { success: false, message: '地址不存在或者账户id不匹配' };
}
const res = await db.collection('address').updateOne({ _id: new ObjectId(item.id), accountId: item.accountId.trim() }, { $set: { disabled: true, lockTime: dayjs().add(30, 'day').valueOf() } });
if (res.modifiedCount > 0) {
await saveAddressHistory(address, undefined, 'delete', db);
return { success: true, message: '删除地址成功' };
}
return { success: false, message: '删除地址失败' };
} catch (e) {
return { success: false, message: e.message };
}
}
async function getAddressList(item, db) {
try {
const { accountId } = item || {};
if (typeof accountId !== 'string' || accountId.trim() === '') {
return { success: false, message: '账户ID不能为空' };
}
const res = await db.collection('address').find({ accountId: accountId.trim(), disabled: false }).toArray();
const list = res.map(item => {
return {
id: item._id.toString(),
name: Sm4Util.decryptDataForSm3(item.name),
phone: Sm4Util.decryptDataForSm3(item.phone),
address: item.address,
isDefault: item.isDefault,
region: item.region,
latitude: item.latitude,
longitude: item.longitude
}
})
return { success: true, message: '查询地址列表成功', data: list };
} catch (e) {
return { success: false, message: e.message };
}
}
async function getDefaultAddress(item, db) {
try {
const { accountId } = item || {};
if (typeof accountId !== 'string' || accountId.trim() === '') {
return { success: false, message: '账户ID不能为空' };
}
const res = await db.collection('address').findOne({ accountId: accountId.trim(), disabled: false, isDefault: true });
if (res) {
return {
success: true, message: '查询默认地址成功', data: {
id: res._id.toString(),
name: Sm4Util.decryptDataForSm3(res.name),
phone: Sm4Util.decryptDataForSm3(res.phone),
address: res.address,
region: res.region,
latitude: res.latitude,
longitude: res.longitude
}
}
}
return { success: true, data: null, message: '未查询到默认地址' };
} catch (e) {
return { success: false, message: e.message };
}
}
function checkModified(address, data) {
try {
if (address.name !== data.name) {
return true
}
if (address.phone !== data.phone) {
return true
}
if (address.address !== data.address) {
return true
}
if (address.region.join(',') !== data.region.join(',')) {
return true
}
if (address.latitude !== data.latitude) {
return true
}
if (address.longitude !== data.longitude) {
return true
}
return false
} catch (e) {
return false
}
}
async function getLockTime(accountId, db) {
try {
const [data] = await db.collection('address').find({ accountId, lockTime: { $gt: Date.now() } }).sort({ lockTime: -1 }).toArray();
if (data && data.lockTime) {
return dayjs(data.lockTime).format('YYYY年MM月DD日 HH:mm');
}
return ''
} catch (e) {
return ''
}
}
async function saveAddressHistory(previous, current, type, db) {
try {
const history = {
addressId: previous._id,
accountId: previous.accountId,
type,
createTime: Date.now()
}
const { name, phone, address, region, latitude, longitude, isDefault } = previous;
history.previous = {
name,
phone,
address,
region,
latitude,
longitude,
isDefault
}
if (current) {
history.current = {
name: current.name,
phone: current.phone,
address: current.address,
region: current.region,
latitude: current.latitude,
longitude: current.longitude,
isDefault: current.isDefault
}
}
await db.collection('address-change-history').insertOne(history);
return { success: true, message: '保存地址历史成功' };
} catch (e) {
return { success: false, message: e.message };
}
}