重构动物模型和路由系统,优化查询逻辑并新增商户和促销活动功能

This commit is contained in:
ylweng
2025-09-22 02:38:50 +08:00
parent 47c816270d
commit 6876683d80
8 changed files with 552 additions and 88 deletions

View File

@@ -0,0 +1,431 @@
<template>
<div class="animal-management">
<a-page-header
title="动物管理"
subtitle="管理认养动物信息"
:breadcrumb="{ routes: [{ path: '/dashboard', breadcrumbName: '首页' }, { path: '', breadcrumbName: '动物管理' }] }"
>
<template #extra>
<a-button type="primary" @click="showCreateModal">
<template #icon><PlusOutlined /></template>
新增动物
</a-button>
</template>
</a-page-header>
<a-card class="mt-4">
<!-- 搜索区域 -->
<div class="search-section mb-4">
<a-form layout="inline" :model="searchForm">
<a-form-item label="动物名称">
<a-input v-model:value="searchForm.name" placeholder="请输入动物名称" />
</a-form-item>
<a-form-item label="动物类型">
<a-select v-model:value="searchForm.animalType" placeholder="请选择类型" style="width: 120px">
<a-select-option value="dog">狗狗</a-select-option>
<a-select-option value="cat">猫咪</a-select-option>
<a-select-option value="sheep">小羊</a-select-option>
<a-select-option value="cow">奶牛</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="状态">
<a-select v-model:value="searchForm.status" placeholder="请选择状态" style="width: 120px">
<a-select-option value="available">可认养</a-select-option>
<a-select-option value="adopted">已认养</a-select-option>
<a-select-option value="pending">审核中</a-select-option>
</a-select>
</a-form-item>
<a-form-item>
<a-button type="primary" @click="handleSearch">
<template #icon><SearchOutlined /></template>
搜索
</a-button>
<a-button class="ml-2" @click="resetSearch">
<template #icon><ReloadOutlined /></template>
重置
</a-button>
</a-form-item>
</a-form>
</div>
<!-- 表格区域 -->
<a-table
:columns="columns"
:data-source="animalList"
:pagination="pagination"
:loading="loading"
row-key="id"
@change="handleTableChange"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'animalType'">
<a-tag :color="getAnimalTypeColor(record.animalType)">
{{ getAnimalTypeText(record.animalType) }}
</a-tag>
</template>
<template v-else-if="column.key === 'status'">
<a-tag :color="getStatusColor(record.status)">
{{ getStatusText(record.status) }}
</a-tag>
</template>
<template v-else-if="column.key === 'action'">
<a-space>
<a-button size="small" @click="handleView(record)">查看</a-button>
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
<a-button size="small" danger @click="handleDelete(record)">删除</a-button>
</a-space>
</template>
</template>
</a-table>
</a-card>
<!-- 创建/编辑模态框 -->
<a-modal
v-model:visible="modalVisible"
:title="modalTitle"
width="600px"
:confirm-loading="confirmLoading"
@ok="handleModalOk"
@cancel="handleModalCancel"
>
<a-form
ref="formRef"
:model="formState"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 16 }"
:rules="rules"
>
<a-form-item label="动物名称" name="name">
<a-input v-model:value="formState.name" placeholder="请输入动物名称" />
</a-form-item>
<a-form-item label="动物类型" name="animalType">
<a-select v-model:value="formState.animalType" placeholder="请选择动物类型">
<a-select-option value="dog">狗狗</a-select-option>
<a-select-option value="cat">猫咪</a-select-option>
<a-select-option value="sheep">小羊</a-select-option>
<a-select-option value="cow">奶牛</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="品种" name="breed">
<a-input v-model:value="formState.breed" placeholder="请输入品种" />
</a-form-item>
<a-form-item label="年龄" name="age">
<a-input-number v-model:value="formState.age" :min="0" :max="30" placeholder="请输入年龄" />
</a-form-item>
<a-form-item label="状态" name="status">
<a-select v-model:value="formState.status" placeholder="请选择状态">
<a-select-option value="available">可认养</a-select-option>
<a-select-option value="adopted">已认养</a-select-option>
<a-select-option value="pending">审核中</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="描述" name="description">
<a-textarea
v-model:value="formState.description"
placeholder="请输入动物描述"
:rows="4"
/>
</a-form-item>
</a-form>
</a-modal>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { message, type FormInstance } from 'ant-design-vue'
import {
PlusOutlined,
SearchOutlined,
ReloadOutlined
} from '@ant-design/icons-vue'
interface Animal {
id: number
name: string
animalType: string
breed: string
age: number
status: string
description: string
createTime: string
}
interface SearchForm {
name?: string
animalType?: string
status?: string
}
interface FormState {
name: string
animalType: string
breed: string
age: number
status: string
description: string
}
// 表格列配置
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 80
},
{
title: '动物名称',
dataIndex: 'name',
key: 'name'
},
{
title: '动物类型',
key: 'animalType',
width: 120
},
{
title: '品种',
dataIndex: 'breed',
key: 'breed'
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
width: 80
},
{
title: '状态',
key: 'status',
width: 100
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
width: 150
},
{
title: '操作',
key: 'action',
width: 200,
fixed: 'right'
}
]
// 响应式数据
const animalList = ref<Animal[]>([])
const loading = ref(false)
const modalVisible = ref(false)
const confirmLoading = ref(false)
const formRef = ref<FormInstance>()
const isEdit = ref(false)
const editingId = ref<number>()
const searchForm = reactive<SearchForm>({})
const formState = reactive<FormState>({
name: '',
animalType: '',
breed: '',
age: 0,
status: '',
description: ''
})
const pagination = reactive({
current: 1,
pageSize: 10,
total: 0,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total: number) => `${total} 条记录`
})
const rules = {
name: [{ required: true, message: '请输入动物名称', trigger: 'blur' }],
animalType: [{ required: true, message: '请选择动物类型', trigger: 'change' }],
status: [{ required: true, message: '请选择状态', trigger: 'change' }]
}
const modalTitle = computed(() => isEdit.value ? '编辑动物' : '新增动物')
// 方法
const getAnimalTypeText = (type: string) => {
const map: Record<string, string> = {
dog: '狗狗',
cat: '猫咪',
sheep: '小羊',
cow: '奶牛'
}
return map[type] || type
}
const getAnimalTypeColor = (type: string) => {
const map: Record<string, string> = {
dog: 'blue',
cat: 'pink',
sheep: 'green',
cow: 'orange'
}
return map[type] || 'default'
}
const getStatusText = (status: string) => {
const map: Record<string, string> = {
available: '可认养',
adopted: '已认养',
pending: '审核中'
}
return map[status] || status
}
const getStatusColor = (status: string) => {
const map: Record<string, string> = {
available: 'green',
adopted: 'red',
pending: 'orange'
}
return map[status] || 'default'
}
const fetchAnimals = async () => {
loading.value = true
try {
// 模拟数据
animalList.value = [
{
id: 1,
name: '小白',
animalType: 'dog',
breed: '萨摩耶',
age: 2,
status: 'available',
description: '温顺可爱的萨摩耶',
createTime: '2024-01-15 10:30:00'
},
{
id: 2,
name: '小花',
animalType: 'cat',
breed: '英短',
age: 1,
status: 'adopted',
description: '活泼好动的英短猫',
createTime: '2024-01-16 14:20:00'
}
]
pagination.total = animalList.value.length
} catch (error) {
message.error('获取动物列表失败')
} finally {
loading.value = false
}
}
const handleSearch = () => {
pagination.current = 1
fetchAnimals()
}
const resetSearch = () => {
Object.assign(searchForm, {
name: undefined,
animalType: undefined,
status: undefined
})
handleSearch()
}
const handleTableChange = (pag: any) => {
pagination.current = pag.current
pagination.pageSize = pag.pageSize
fetchAnimals()
}
const showCreateModal = () => {
isEdit.value = false
editingId.value = undefined
Object.assign(formState, {
name: '',
animalType: '',
breed: '',
age: 0,
status: '',
description: ''
})
modalVisible.value = true
}
const handleEdit = (record: Animal) => {
isEdit.value = true
editingId.value = record.id
Object.assign(formState, record)
modalVisible.value = true
}
const handleView = (record: Animal) => {
// 查看详情逻辑
message.info(`查看动物: ${record.name}`)
}
const handleDelete = (record: Animal) => {
// 删除逻辑
message.warning(`删除动物: ${record.name}`)
}
const handleModalOk = async () => {
try {
await formRef.value?.validate()
confirmLoading.value = true
if (isEdit.value) {
// 编辑逻辑
message.success('编辑成功')
} else {
// 新增逻辑
message.success('新增成功')
}
modalVisible.value = false
fetchAnimals()
} catch (error) {
console.error('表单验证失败', error)
} finally {
confirmLoading.value = false
}
}
const handleModalCancel = () => {
modalVisible.value = false
}
// 生命周期
onMounted(() => {
fetchAnimals()
})
</script>
<style scoped>
.animal-management {
padding: 20px;
}
.search-section {
background: #fafafa;
padding: 16px;
border-radius: 6px;
}
.mt-4 {
margin-top: 16px;
}
.mb-4 {
margin-bottom: 16px;
}
.ml-2 {
margin-left: 8px;
}
</style>

View File

@@ -1,4 +1,4 @@
const db = require('../config/database');
const { query } = require('../config/database');
/**
* 动物模型类
@@ -12,7 +12,7 @@ class Animal {
*/
static async findById(id) {
try {
const [rows] = await db.execute(
const [rows] = await query(
'SELECT * FROM animals WHERE id = ?',
[id]
);
@@ -52,7 +52,7 @@ class Animal {
LIMIT ? OFFSET ?
`;
const [rows] = await db.execute(query, [...params, limit, offset]);
const [rows] = await query(query, [...params, limit, offset]);
return rows;
} catch (error) {
console.error('获取动物列表失败:', error);
@@ -75,7 +75,7 @@ class Animal {
WHERE 1=1 ${whereClause}
`;
const [rows] = await db.execute(query, params);
const [rows] = await query(query, params);
return rows[0].count;
} catch (error) {
console.error('获取动物数量失败:', error);
@@ -102,7 +102,7 @@ class Animal {
WHERE a.id = ?
`;
const [rows] = await db.execute(query, [id]);
const [rows] = await query(query, [id]);
return rows[0] || null;
} catch (error) {
console.error('获取动物详情失败:', error);
@@ -126,11 +126,11 @@ class Animal {
WHERE id = ?
`;
const [result] = await db.execute(query, [status, id]);
const [result] = await query(query, [status, id]);
// 记录状态变更日志
if (reason) {
await db.execute(
await query(
`INSERT INTO animal_status_logs (animal_id, old_status, new_status, admin_id, reason, created_at)
SELECT ?, status, ?, ?, ?, NOW() FROM animals WHERE id = ?`,
[id, status, adminId, reason, id]
@@ -161,7 +161,7 @@ class Animal {
WHERE id IN (${placeholders})
`;
const [result] = await db.execute(query, [status, ...ids]);
const [result] = await query(query, [status, ...ids]);
return result;
} catch (error) {
console.error('批量更新动物状态失败:', error);
@@ -187,7 +187,7 @@ class Animal {
FROM animals
`;
const [rows] = await db.execute(query);
const [rows] = await query(query);
return rows[0];
} catch (error) {
console.error('获取动物总体统计失败:', error);
@@ -212,7 +212,7 @@ class Animal {
ORDER BY count DESC
`;
const [rows] = await db.execute(query);
const [rows] = await query(query);
return rows;
} catch (error) {
console.error('获取动物统计信息失败:', error);
@@ -236,7 +236,7 @@ class Animal {
ORDER BY count DESC
`;
const [rows] = await db.execute(query);
const [rows] = await query(query);
return rows;
} catch (error) {
console.error('获取按状态分类的统计失败:', error);
@@ -264,7 +264,7 @@ class Animal {
ORDER BY animal_count DESC
`;
const [rows] = await db.execute(query);
const [rows] = await query(query);
return rows;
} catch (error) {
console.error('获取按商家分类的统计失败:', error);
@@ -290,7 +290,7 @@ class Animal {
ORDER BY month ASC
`;
const [rows] = await db.execute(query);
const [rows] = await query(query);
return rows;
} catch (error) {
console.error('获取月度趋势数据失败:', error);
@@ -325,7 +325,7 @@ class Animal {
ORDER BY a.created_at DESC
`;
const [rows] = await db.execute(query, params);
const [rows] = await query(query, params);
return rows;
} catch (error) {
console.error('获取导出数据失败:', error);
@@ -366,7 +366,7 @@ class Animal {
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
`;
const [result] = await db.execute(query, [
const [result] = await query(query, [
name, type, breed, age, gender, weight, price,
description, health_status, JSON.stringify(vaccination_records || []),
JSON.stringify(images || []), merchant_id, farm_location,
@@ -406,7 +406,7 @@ class Animal {
values.push(id);
const query = `UPDATE animals SET ${fields.join(', ')} WHERE id = ?`;
const [result] = await db.execute(query, values);
const [result] = await query(query, values);
return result;
} catch (error) {
@@ -422,7 +422,7 @@ class Animal {
*/
static async delete(id) {
try {
const [result] = await db.execute('DELETE FROM animals WHERE id = ?', [id]);
const [result] = await query('DELETE FROM animals WHERE id = ?', [id]);
return result;
} catch (error) {
console.error('删除动物失败:', error);

View File

@@ -1,4 +1,4 @@
const db = require('../config/database');
const { query } = require('../config/database');
class AnimalClaim {
/**
@@ -26,7 +26,7 @@ class AnimalClaim {
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
`;
const [result] = await db.execute(query, [
const [result] = await query(query, [
claim_no,
animal_id,
user_id,
@@ -68,7 +68,7 @@ class AnimalClaim {
WHERE ac.id = ? AND ac.deleted_at IS NULL
`;
const [rows] = await db.execute(query, [id]);
const [rows] = await query(query, [id]);
return rows[0] || null;
} catch (error) {
console.error('查找认领申请数据库错误:', error);
@@ -97,7 +97,7 @@ class AnimalClaim {
WHERE ac.claim_no = ? AND ac.deleted_at IS NULL
`;
const [rows] = await db.execute(query, [claimNo]);
const [rows] = await query(query, [claimNo]);
return rows[0] || null;
} catch (error) {
console.error('根据订单号查找认领申请数据库错误:', error);
@@ -122,7 +122,7 @@ class AnimalClaim {
LIMIT 1
`;
const [rows] = await db.execute(query, [userId, animalId]);
const [rows] = await query(query, [userId, animalId]);
return rows[0] || null;
} catch (error) {
console.error('查找活跃认领申请数据库错误:', error);
@@ -158,7 +158,7 @@ class AnimalClaim {
WHERE id = ?
`;
await db.execute(query, values);
await query(query, values);
return await this.findById(id);
} catch (error) {
console.error('更新认领申请状态数据库错误:', error);
@@ -225,7 +225,7 @@ class AnimalClaim {
LIMIT ? OFFSET ?
`;
const [dataRows] = await db.execute(dataQuery, [...queryParams, limit, offset]);
const [dataRows] = await query(dataQuery, [...queryParams, limit, offset]);
// 查询总数
const countQuery = `
@@ -235,7 +235,7 @@ class AnimalClaim {
WHERE ${whereClause}
`;
const [countRows] = await db.execute(countQuery, queryParams);
const [countRows] = await query(countQuery, queryParams);
const total = countRows[0].total;
return {
@@ -292,7 +292,7 @@ class AnimalClaim {
LIMIT ? OFFSET ?
`;
const [dataRows] = await db.execute(dataQuery, [...queryParams, limit, offset]);
const [dataRows] = await query(dataQuery, [...queryParams, limit, offset]);
// 查询总数
const countQuery = `
@@ -301,7 +301,7 @@ class AnimalClaim {
WHERE ${whereClause}
`;
const [countRows] = await db.execute(countQuery, queryParams);
const [countRows] = await query(countQuery, queryParams);
const total = countRows[0].total;
return {
@@ -396,7 +396,7 @@ class AnimalClaim {
LIMIT ? OFFSET ?
`;
const [dataRows] = await db.execute(dataQuery, [...queryParams, limit, offset]);
const [dataRows] = await query(dataQuery, [...queryParams, limit, offset]);
// 查询总数
const countQuery = `
@@ -407,7 +407,7 @@ class AnimalClaim {
WHERE ${whereClause}
`;
const [countRows] = await db.execute(countQuery, queryParams);
const [countRows] = await query(countQuery, queryParams);
const total = countRows[0].total;
return {
@@ -446,7 +446,7 @@ class AnimalClaim {
) VALUES (?, ?, ?, ?, ?, NOW(), NOW())
`;
const [result] = await db.execute(query, [
const [result] = await query(query, [
claim_id,
duration,
amount,
@@ -511,7 +511,7 @@ class AnimalClaim {
WHERE ${whereClause}
`;
const [basicStats] = await db.execute(basicStatsQuery, queryParams);
const [basicStats] = await query(basicStatsQuery, queryParams);
// 按动物类型统计
const typeStatsQuery = `
@@ -527,7 +527,7 @@ class AnimalClaim {
ORDER BY claim_count DESC
`;
const [typeStats] = await db.execute(typeStatsQuery, queryParams);
const [typeStats] = await query(typeStatsQuery, queryParams);
// 按月份统计
const monthlyStatsQuery = `
@@ -544,7 +544,7 @@ class AnimalClaim {
LIMIT 12
`;
const [monthlyStats] = await db.execute(monthlyStatsQuery, queryParams);
const [monthlyStats] = await query(monthlyStatsQuery, queryParams);
return {
basic: basicStats[0],
@@ -570,7 +570,7 @@ class AnimalClaim {
WHERE id = ?
`;
const [result] = await db.execute(query, [id]);
const [result] = await query(query, [id]);
return result.affectedRows > 0;
} catch (error) {
console.error('软删除认领申请数据库错误:', error);

View File

@@ -9,7 +9,7 @@ class Merchant {
static async findById(id) {
try {
const sql = 'SELECT * FROM merchants WHERE id = ?';
const [rows] = await query(sql, [id]);
const rows = await query(sql, [id]);
return rows.length > 0 ? rows[0] : null;
} catch (error) {
console.error('查找商户失败:', error);
@@ -53,17 +53,12 @@ class Merchant {
// 查询总数
const countSql = `SELECT COUNT(*) as total FROM merchants ${whereClause}`;
const [countResult] = await query(countSql, params);
const total = countResult[0].total;
const countResult = await query(countSql, params);
const total = countResult && countResult.length > 0 ? countResult[0].total : 0;
// 查询数据
const dataSql = `
SELECT * FROM merchants
${whereClause}
ORDER BY created_at DESC
LIMIT ? OFFSET ?
`;
const [rows] = await query(dataSql, [...params, limit, offset]);
const dataSql = `SELECT * FROM merchants ${whereClause} ORDER BY created_at DESC LIMIT ${parseInt(limit)} OFFSET ${parseInt(offset)}`;
const rows = await query(dataSql, params);
return {
data: rows,
@@ -99,7 +94,7 @@ class Merchant {
`;
const params = [name, type, contact_person, contact_phone, email, address, description];
const [result] = await query(sql, params);
const result = await query(sql, params);
// 返回创建的商户信息
return await this.findById(result.insertId);
@@ -133,7 +128,7 @@ class Merchant {
params.push(id);
const sql = `UPDATE merchants SET ${updateFields.join(', ')} WHERE id = ?`;
const [result] = await query(sql, params);
const result = await query(sql, params);
if (result.affectedRows === 0) {
throw new Error('商户不存在或更新失败');
@@ -151,7 +146,7 @@ class Merchant {
static async delete(id) {
try {
const sql = 'DELETE FROM merchants WHERE id = ?';
const [result] = await query(sql, [id]);
const result = await query(sql, [id]);
if (result.affectedRows === 0) {
throw new Error('商户不存在或删除失败');
@@ -174,16 +169,16 @@ class Merchant {
// 获取关联的动物数量
const animalCountSql = 'SELECT COUNT(*) as count FROM animals WHERE merchant_id = ?';
const [animalResult] = await query(animalCountSql, [id]);
const animalResult = await query(animalCountSql, [id]);
// 获取关联的订单数量
const orderCountSql = 'SELECT COUNT(*) as count FROM orders WHERE merchant_id = ?';
const [orderResult] = await query(orderCountSql, [id]);
const orderResult = await query(orderCountSql, [id]);
return {
...merchant,
animal_count: animalResult[0].count,
order_count: orderResult[0].count
animal_count: animalResult && animalResult.length > 0 ? animalResult[0].count : 0,
order_count: orderResult && orderResult.length > 0 ? orderResult[0].count : 0
};
} catch (error) {
console.error('获取商户详情失败:', error);
@@ -205,7 +200,7 @@ class Merchant {
FROM merchants
`;
const [rows] = await query(sql);
const rows = await query(sql);
return rows[0];
} catch (error) {
console.error('获取商户统计信息失败:', error);

View File

@@ -1,4 +1,4 @@
const db = require('../config/database');
const { query } = require('../config/database');
class Payment {
/**
@@ -24,7 +24,7 @@ class Payment {
) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', NOW(), NOW())
`;
const [result] = await db.execute(query, [
const [result] = await query(query, [
payment_no, order_id, user_id, amount, payment_method,
return_url, notify_url
]);
@@ -46,7 +46,7 @@ class Payment {
WHERE p.id = ? AND p.deleted_at IS NULL
`;
const [rows] = await db.execute(query, [id]);
const [rows] = await query(query, [id]);
return rows[0] || null;
}
@@ -64,7 +64,7 @@ class Payment {
WHERE p.payment_no = ? AND p.deleted_at IS NULL
`;
const [rows] = await db.execute(query, [paymentNo]);
const [rows] = await query(query, [paymentNo]);
return rows[0] || null;
}
@@ -80,7 +80,7 @@ class Payment {
ORDER BY created_at DESC
`;
const [rows] = await db.execute(query, [orderId]);
const [rows] = await query(query, [orderId]);
return rows;
}
@@ -106,7 +106,7 @@ class Payment {
WHERE id = ? AND deleted_at IS NULL
`;
await db.execute(query, [
await query(query, [
status, transaction_id, paid_amount,
paid_at, failure_reason, id
]);
@@ -163,7 +163,7 @@ class Payment {
FROM payments p
WHERE ${whereClause}
`;
const [countResult] = await db.execute(countQuery, params);
const [countResult] = await query(countQuery, params);
const total = countResult[0].total;
// 查询数据
@@ -176,7 +176,7 @@ class Payment {
LIMIT ? OFFSET ?
`;
params.push(limit, offset);
const [rows] = await db.execute(dataQuery, params);
const [rows] = await query(dataQuery, params);
return {
data: rows,
@@ -252,7 +252,7 @@ class Payment {
LEFT JOIN users u ON p.user_id = u.id
WHERE ${whereClause}
`;
const [countResult] = await db.execute(countQuery, params);
const [countResult] = await query(countQuery, params);
const total = countResult[0].total;
// 查询数据
@@ -267,7 +267,7 @@ class Payment {
LIMIT ? OFFSET ?
`;
params.push(limit, offset);
const [rows] = await db.execute(dataQuery, params);
const [rows] = await query(dataQuery, params);
return {
data: rows,
@@ -301,7 +301,7 @@ class Payment {
) VALUES (?, ?, ?, ?, ?, 'pending', NOW(), NOW())
`;
const [result] = await db.execute(query, [
const [result] = await query(query, [
refund_no, payment_id, user_id, refund_amount, refund_reason
]);
@@ -325,7 +325,7 @@ class Payment {
WHERE r.id = ? AND r.deleted_at IS NULL
`;
const [rows] = await db.execute(query, [id]);
const [rows] = await query(query, [id]);
return rows[0] || null;
}
@@ -352,7 +352,7 @@ class Payment {
WHERE id = ? AND deleted_at IS NULL
`;
await db.execute(query, [
await query(query, [
status, processed_by, process_remark,
refund_transaction_id, refunded_at, id
]);
@@ -402,7 +402,7 @@ class Payment {
FROM payments
WHERE ${whereClause}
`;
const [totalResult] = await db.execute(totalQuery, params);
const [totalResult] = await query(totalQuery, params);
// 退款统计
const refundQuery = `
@@ -421,7 +421,7 @@ class Payment {
if (end_date) refundParams.push(end_date);
if (payment_method) refundParams.push(payment_method);
const [refundResult] = await db.execute(refundQuery, refundParams);
const [refundResult] = await query(refundQuery, refundParams);
// 按支付方式统计
const methodQuery = `
@@ -433,7 +433,7 @@ class Payment {
WHERE ${whereClause}
GROUP BY payment_method
`;
const [methodResult] = await db.execute(methodQuery, params);
const [methodResult] = await query(methodQuery, params);
return {
total_count: totalResult[0].total_count,
@@ -457,7 +457,7 @@ class Payment {
*/
static async exists(id) {
const query = 'SELECT 1 FROM payments WHERE id = ? AND deleted_at IS NULL';
const [rows] = await db.execute(query, [id]);
const [rows] = await query(query, [id]);
return rows.length > 0;
}
@@ -473,7 +473,7 @@ class Payment {
WHERE id = ? AND deleted_at IS NULL
`;
const [result] = await db.execute(query, [id]);
const [result] = await query(query, [id]);
return result.affectedRows > 0;
}
@@ -491,7 +491,7 @@ class Payment {
AND deleted_at IS NULL
`;
const [result] = await db.execute(query, [hours]);
const [result] = await query(query, [hours]);
return result.affectedRows;
}
}

View File

@@ -354,7 +354,7 @@ class Travel {
SET current_participants = GREATEST(0, current_participants - ?), updated_at = NOW()
WHERE id = ?
`;
const [result] = await query(sql, [count, id]);
const [result] = await query(query, [count, id]);
return result.affectedRows > 0;
}
@@ -372,7 +372,7 @@ class Travel {
FROM travel_plans
WHERE id = ?
`;
const [rows] = await query(sql, [id]);
const [rows] = await query(query, [id]);
if (rows.length === 0) {
return false;
@@ -403,7 +403,7 @@ class Travel {
LIMIT ?
`;
const [rows] = await query(sql, [limit]);
const [rows] = await query(query, [limit]);
// 解析JSON字段
return rows.map(travel => {

View File

@@ -1,4 +1,4 @@
const db = require('../config/database');
const { query } = require('../config/database');
/**
* 旅行报名数据模型
@@ -25,7 +25,7 @@ class TravelRegistration {
VALUES (?, ?, ?, ?, ?, 'pending', NOW())
`;
const [result] = await db.execute(query, [
const [result] = await query(query, [
travel_plan_id,
user_id,
message || null,
@@ -58,7 +58,7 @@ class TravelRegistration {
WHERE tr.id = ?
`;
const [rows] = await db.execute(query, [id]);
const [rows] = await query(query, [id]);
return rows[0] || null;
}
@@ -74,7 +74,7 @@ class TravelRegistration {
WHERE user_id = ? AND travel_plan_id = ? AND status != 'cancelled'
`;
const [rows] = await db.execute(query, [userId, travelPlanId]);
const [rows] = await query(query, [userId, travelPlanId]);
return rows[0] || null;
}
@@ -106,7 +106,7 @@ class TravelRegistration {
FROM travel_registrations tr
${whereClause}
`;
const [countResult] = await db.execute(countQuery, params);
const [countResult] = await query(countQuery, params);
const total = countResult[0].total;
// 获取数据
@@ -127,7 +127,7 @@ class TravelRegistration {
`;
params.push(pageSize, offset);
const [rows] = await db.execute(query, params);
const [rows] = await query(query, params);
return {
registrations: rows,
@@ -168,7 +168,7 @@ class TravelRegistration {
FROM travel_registrations tr
${whereClause}
`;
const [countResult] = await db.execute(countQuery, params);
const [countResult] = await query(countQuery, params);
const total = countResult[0].total;
// 获取数据
@@ -188,7 +188,7 @@ class TravelRegistration {
`;
params.push(pageSize, offset);
const [rows] = await db.execute(query, params);
const [rows] = await query(query, params);
return {
registrations: rows,
@@ -215,7 +215,7 @@ class TravelRegistration {
WHERE id = ?
`;
await db.execute(query, [status, rejectReason, id]);
await query(query, [status, rejectReason, id]);
return this.findById(id);
}
@@ -245,7 +245,7 @@ class TravelRegistration {
WHERE travel_plan_id = ?
`;
const [rows] = await db.execute(query, [travelPlanId]);
const [rows] = await query(query, [travelPlanId]);
return rows[0];
}
@@ -261,7 +261,7 @@ class TravelRegistration {
WHERE id = ? AND created_by = ?
`;
const [rows] = await db.execute(query, [travelPlanId, userId]);
const [rows] = await query(query, [travelPlanId, userId]);
return rows.length > 0;
}
@@ -279,7 +279,7 @@ class TravelRegistration {
WHERE tr.id = ? AND tp.created_by = ?
`;
const [rows] = await db.execute(query, [registrationId, userId]);
const [rows] = await query(query, [registrationId, userId]);
return rows.length > 0;
}
@@ -295,7 +295,7 @@ class TravelRegistration {
WHERE travel_plan_id = ? AND status = 'approved'
`;
const [rows] = await db.execute(query, [travelPlanId]);
const [rows] = await query(query, [travelPlanId]);
return rows[0].count;
}

View File

@@ -342,7 +342,8 @@ class OrderService {
pageSize = 10,
status,
merchantId,
userId
userId,
order_no
} = filters;
const offset = (page - 1) * pageSize;
@@ -390,6 +391,13 @@ class OrderService {
countParams.push(userId);
}
if (order_no) {
query += ' AND o.order_no = ?';
countQuery += ' AND o.order_no = ?';
params.push(order_no);
countParams.push(order_no);
}
query += ' ORDER BY o.created_at DESC LIMIT ? OFFSET ?';
params.push(pageSize, offset);
@@ -410,6 +418,36 @@ class OrderService {
throw new Error('获取所有订单失败');
}
}
/**
* 获取订单统计信息(管理员)
* @returns {Promise<Object>} 统计信息
*/
async getOrderStatistics() {
try {
const query = `
SELECT
COUNT(*) as total_orders,
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending_orders,
SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END) as paid_orders,
SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) as processing_orders,
SUM(CASE WHEN status = 'shipped' THEN 1 ELSE 0 END) as shipped_orders,
SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed_orders,
SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) as cancelled_orders,
SUM(CASE WHEN status = 'refunded' THEN 1 ELSE 0 END) as refunded_orders,
SUM(total_amount) as total_revenue
FROM orders
WHERE is_deleted = 0
`;
const [stats] = await database.query(query);
return stats;
} catch (error) {
console.error('获取订单统计失败:', error);
throw new Error('获取订单统计失败');
}
}
}
module.exports = new OrderService();