소스 검색

feat(订单管理): 将推送短信功能改为短信记录查看功能

重构推送短信弹窗为短信记录查看页面,优化退款金额计算逻辑
修改按钮文本从"推送短信"为"短信记录"
添加全选退款时的金额计算处理
使用CommonTable组件展示短信记录
ylong 1 주 전
부모
커밋
115196919a

+ 1 - 1
src/views/mallOrder/all/components/order-item.vue

@@ -171,7 +171,7 @@
                     >[手工发货]</el-button
                 >
                 <el-button link type="primary" @click="$emit('push-sms', order)"
-                    >[推送短信]</el-button
+                    >[短信记录]</el-button
                 >
                 <el-button link type="warning" @click="$emit('refund', order)"
                     >[缺货退款]</el-button

+ 26 - 149
src/views/mallOrder/all/components/push-sms-dialog.vue

@@ -1,113 +1,42 @@
 <template>
     <ele-modal
-        form
         :width="800"
         v-model="visible"
-        title="推送短信"
-        @closed="handleCancel"
+        title="短信记录"
+        @open="handleOpen"
     >
-        <el-form
-            ref="formRef"
-            :model="form"
-            :rules="rules"
-            label-width="80px"
-            @submit.prevent=""
-            v-loading="loading"
-        >
-            <el-form-item label="短信类型" prop="type">
-                <el-radio-group v-model="form.type" @change="handleChangeType">
-                    <el-radio
-                        :value="item.type"
-                        v-for="item in smsContentList"
-                        :key="item.type"
-                        >{{ item.typeName }}</el-radio
-                    >
-                </el-radio-group>
-            </el-form-item>
-            <el-form-item label="短信预览" prop="remark">
-                <el-input
-                    :rows="4"
-                    type="textarea"
-                    v-model="form.remark"
-                    disabled
-                    placeholder="请输入短信预览"
-                />
-            </el-form-item>
-            <el-form-item label="推送历史" prop="records">
-                <ele-data-table
-                    row-key="id"
-                    :columns="columns"
-                    :data="smsRecords"
-                    height="200px"
-                    :show-overflow-tooltip="true"
-                />
-            </el-form-item>
-        </el-form>
+        <common-table
+            ref="tableRef"
+            row-key="id"
+            :columns="columns"
+            :page-config="pageConfig"
+            height="400px"
+            :show-overflow-tooltip="true"
+            :tools="false"
+            :flex-table="false"
+        />
 
         <template #footer>
             <el-button @click="handleCancel">关闭</el-button>
-            <el-button
-                type="primary"
-                @click="handleSubmit"
-                :loading="submitLoading"
-                >确定</el-button
-            >
         </template>
     </ele-modal>
 </template>
 
 <script setup>
-    import { ref, reactive } from 'vue';
-    import { EleMessage } from 'ele-admin-plus/es';
-    import request from '@/utils/request';
+    import { ref, reactive, nextTick } from 'vue';
+    import CommonTable from '@/components/CommonPage/CommonTable.vue';
 
     const emit = defineEmits(['success']);
 
     /** 弹窗是否打开 */
     const visible = defineModel({ type: Boolean });
+    const tableRef = ref(null);
+    const currentOrderId = ref(null);
 
-    /** 表单引用 */
-    const formRef = ref();
-
-    /** SMS记录数据 */
-    const smsRecords = ref([]);
-
-    /** 短信内容列表 */
-    const smsContentList = ref([]);
-    const loading = ref(false);
-    const submitLoading = ref(false);
-
-    const form = reactive({
-        orderId: null,
-        type: '',
-        remark: ''
-    });
-
-    /** 短信类型变化 */
-    const handleChangeType = (val) => {
-        const found = smsContentList.value.find((item) => item.type === val);
-        if (found) {
-            form.remark = found.smsContent;
-        }
-    };
-
-    /** 表单验证规则 */
-    const rules = reactive({
-        type: [
-            {
-                required: true,
-                message: '请选择短信类型',
-                trigger: 'change'
-            }
-        ],
-        remark: [
-            {
-                required: true,
-                message: '请输入短信预览',
-                type: 'string',
-                trigger: 'blur'
-            }
-        ]
+    const pageConfig = reactive({
+        pageUrl: '', // Will be set dynamically
+        cacheKey: 'sms-log-table',
+        params: {}
     });
 
     // 表格列配置
@@ -132,70 +61,19 @@
     /** 关闭弹窗 */
     const handleCancel = () => {
         visible.value = false;
-        resetForm();
-    };
-
-    /** 重置表单 */
-    const resetForm = () => {
-        form.orderId = null;
-        form.type = '';
-        form.remark = '';
-        formRef.value?.resetFields();
-        smsRecords.value = [];
     };
 
     /** 弹窗打开事件 */
     const handleOpen = (row) => {
-        resetForm();
         if (row && row.orderId) {
-            form.orderId = row.orderId;
-            getSmsLogInfo(form.orderId);
+            currentOrderId.value = row.orderId;
+            pageConfig.pageUrl = `/shop/shopOrderSmsLog/orderSmsLogList/${row.orderId}`;
         }
         visible.value = true;
-    };
-
-    /** 获取短信记录信息 */
-    const getSmsLogInfo = (orderId) => {
-        loading.value = true;
-        request
-            .get(`/shop/shopOrderSmsLog/getInfo/${orderId}`)
-            .then((res) => {
-                const data = res.data.data || res.data;
-                smsContentList.value = data.smsContentList || [];
-                smsRecords.value = data.smsLogList || [];
-            })
-            .finally(() => {
-                loading.value = false;
-            });
-    };
-
-    /** 提交表单 */
-    const handleSubmit = () => {
-        formRef.value?.validate(async (valid) => {
-            if (!valid) return;
-
-            submitLoading.value = true;
-            request
-                .post('/shop/shopOrderSmsLog/send', {
-                    orderId: form.orderId,
-                    type: form.type
-                })
-                .then((res) => {
-                    if (res.data.code === 200) {
-                        EleMessage.success('短信发送成功');
-                        handleCancel();
-                        emit('success');
-                    } else {
-                        EleMessage.error(res.data.msg || '短信发送失败');
-                    }
-                })
-                .catch((e) => {
-                    console.error(e);
-                    EleMessage.error('网络错误');
-                })
-                .finally(() => {
-                    submitLoading.value = false;
-                });
+        nextTick(() => {
+            if (tableRef.value) {
+                tableRef.value.reload({ page: 1 });
+            }
         });
     };
 
@@ -205,5 +83,4 @@
 </script>
 
 <style scoped>
-    /* 可以在这里添加样式微调 */
 </style>

+ 26 - 6
src/views/mallOrder/all/components/refund-dialog.vue

@@ -138,11 +138,28 @@
         selectedRows.value = val;
     };
 
+    const isAllSelected = computed(() => {
+        if (!order.value?.detailList) return false;
+        const totalItems = order.value.detailList.reduce((sum, item) => sum + item.num, 0);
+        const selectedItems = selectedRows.value.reduce((sum, item) => sum + (item.refundQty || 0), 0);
+        return totalItems > 0 && totalItems === selectedItems;
+    });
+
     // Computed
     const productRefundAmount = computed(() => {
-        return selectedRows.value.reduce((sum, item) => {
-            return sum + item.price * (item.refundQty || 0);
+        if (isAllSelected.value) {
+            // 如果全部退款,商品退款金额 = 订单实付金额 - 订单运费
+            // 避免因单价精度导致的 1 分钱差值
+            const originalProductTotal = originalTotal.value - maxShippingFee.value;
+            return originalProductTotal > 0 ? originalProductTotal : 0;
+        }
+
+        const totalCents = selectedRows.value.reduce((sum, item) => {
+            const price = parseFloat(item.payPrice || item.price) || 0;
+            const amountCents = Math.round(price * (item.refundQty || 0) * 100);
+            return sum + amountCents;
         }, 0);
+        return totalCents / 100;
     });
 
     const selectedCount = computed(() => {
@@ -152,8 +169,9 @@
     });
 
     const totalRefundAmount = computed(() => {
-        const shipping = parseFloat(shippingRefund.value) || 0;
-        return productRefundAmount.value + shipping;
+        const shippingCents = Math.round((parseFloat(shippingRefund.value) || 0) * 100);
+        const productCents = Math.round(productRefundAmount.value * 100);
+        return (productCents + shippingCents) / 100;
     });
 
     const originalTotal = computed(() => {
@@ -161,8 +179,10 @@
     });
 
     const newTotal = computed(() => {
-        const val = originalTotal.value - totalRefundAmount.value;
-        return val > 0 ? val : 0;
+        const originalCents = Math.round(originalTotal.value * 100);
+        const refundCents = Math.round(totalRefundAmount.value * 100);
+        const newCents = originalCents - refundCents;
+        return newCents > 0 ? newCents / 100 : 0;
     });
 
     const handleSubmit = () => {

+ 27 - 165
src/views/mallOrder/refund/components/push-sms-dialog.vue

@@ -1,105 +1,44 @@
 <template>
     <ele-modal
-        form
         :width="800"
         v-model="visible"
-        title="推送短信"
+        title="短信记录"
         @open="handleOpen"
     >
-        <el-form
-            ref="formRef"
-            :model="form"
-            :rules="rules"
-            label-width="80px"
-            @submit.prevent=""
-        >
-            <el-form-item label="短信类型" prop="type">
-                <el-radio-group v-model="form.type" @change="handleChangeType">
-                    <el-radio
-                        :value="item.type"
-                        v-for="item in smsContentList"
-                        :key="item.type"
-                        >{{ item.typeName }}</el-radio
-                    >
-                </el-radio-group>
-            </el-form-item>
-            <el-form-item label="短信预览" prop="remark">
-                <el-input
-                    :rows="4"
-                    type="textarea"
-                    v-model="form.remark"
-                    disabled
-                    placeholder="请输入短信预览"
-                />
-            </el-form-item>
-            <el-form-item label="推送历史" prop="records">
-                <ele-data-table
-                    row-key="id"
-                    :columns="columns"
-                    :data="smsRecords"
-                    height="200px"
-                    :show-overflow-tooltip="true"
-                />
-            </el-form-item>
-        </el-form>
+        <common-table
+            ref="tableRef"
+            row-key="id"
+            :columns="columns"
+            :page-config="pageConfig"
+            height="400px"
+            :show-overflow-tooltip="true"
+            :tools="false"
+            :flex-table="false"
+        />
 
         <template #footer>
             <el-button @click="handleCancel">关闭</el-button>
-            <el-button type="primary" @click="handleSubmit">确定</el-button>
         </template>
     </ele-modal>
 </template>
 
 <script setup>
-    import { ref, reactive, getCurrentInstance } from 'vue';
+    import { ref, reactive, nextTick } from 'vue';
     import { EleMessage } from 'ele-admin-plus/es';
+    import CommonTable from '@/components/CommonPage/CommonTable.vue';
+    import request from '@/utils/request';
 
-    const { proxy } = getCurrentInstance();
     const emit = defineEmits(['success']);
 
     /** 弹窗是否打开 */
     const visible = defineModel({ type: Boolean });
+    const tableRef = ref(null);
+    const currentOrderId = ref(null);
 
-    /** 表单引用 */
-    const formRef = ref();
-
-    /** SMS记录数据 */
-    const smsRecords = ref([]);
-
-    /** 短信内容列表 */
-    const smsContentList = ref([]);
-
-    const form = reactive({
-        orderId: null,
-        type: '',
-        remark: ''
-    });
-
-    /** 短信类型变化 */
-    const handleChangeType = (val) => {
-        const found = smsContentList.value.find((item) => item.type === val);
-        if (found) {
-            form.remark = found.smsContent;
-        }
-    };
-
-    /** 表单验证规则 */
-    const rules = reactive({
-        type: [
-            {
-                required: true,
-                message: '请选择短信类型',
-                trigger: 'change'
-            }
-        ],
-        remark: [
-            {
-                required: true,
-                message: '请输入短信预览',
-                type: 'string',
-                trigger: 'blur'
-            }
-        ]
+    const pageConfig = reactive({
+        pageUrl: '', // Will be set dynamically
+        cacheKey: 'sms-log-table-refund',
+        params: {}
     });
 
     // 表格列配置
@@ -124,95 +63,19 @@
     /** 关闭弹窗 */
     const handleCancel = () => {
         visible.value = false;
-        resetForm();
-    };
-
-    /** 重置表单 */
-    const resetForm = () => {
-        form.orderId = null;
-        form.type = '';
-        form.remark = '';
-        formRef.value?.resetFields();
-        smsRecords.value = [];
     };
 
     /** 弹窗打开事件 */
     const handleOpen = (row) => {
-        resetForm();
-        // 模拟获取数据,实际开发中可以使用 row.orderId 调用接口
-        if (row) {
-            form.orderId = row.orderId || 123;
-            getSmsLogInfo(form.orderId);
-        } else {
-            // 如果没有 row 传入,也可以默认加载 mock 数据方便预览
-            getSmsLogInfo(123);
+        if (row && row.orderId) {
+            currentOrderId.value = row.orderId;
+            pageConfig.pageUrl = `/shop/shopOrderSmsLog/orderSmsLogList/${row.orderId}`;
         }
         visible.value = true;
-    };
-
-    /** 获取短信记录信息 (Mock) */
-    const getSmsLogInfo = (orderId) => {
-        // 模拟 API 请求延迟
-        setTimeout(() => {
-            // Mock data
-            smsContentList.value = [
-                {
-                    type: 'urge',
-                    typeName: '催发货提醒',
-                    smsContent: '亲,您的订单已发货,请注意查收。'
-                },
-                {
-                    type: 'receive',
-                    typeName: '收货提醒',
-                    smsContent: '亲,您的宝贝已送达,请确认收货。'
-                },
-                {
-                    type: 'good_review',
-                    typeName: '好评提醒',
-                    smsContent: '亲,如果您对宝贝满意,请给个好评哦~'
-                }
-            ];
-
-            smsRecords.value = [
-                {
-                    id: 1,
-                    createName: '管理员',
-                    smsContent: '亲,您的订单已发货,请注意查收。',
-                    createTime: '2023-10-27 10:00:00',
-                    status: 1
-                },
-                {
-                    id: 2,
-                    createName: '客服小美',
-                    smsContent: '亲,您的宝贝已送达,请确认收货。',
-                    createTime: '2023-10-28 14:30:00',
-                    status: 1
-                }
-            ];
-        }, 100);
-    };
-
-    /** 提交表单 */
-    const handleSubmit = () => {
-        formRef.value?.validate(async (valid) => {
-            if (!valid) return;
-
-            // 模拟提交
-            setTimeout(() => {
-                EleMessage.success('短信发送成功');
-                // 添加一条记录到 mock 列表,模拟实时更新
-                smsRecords.value.unshift({
-                    id: Date.now(),
-                    createName: '当前用户',
-                    smsContent: form.remark,
-                    createTime: new Date().toLocaleString(),
-                    status: 1
-                });
-                // 这里的业务逻辑是发送后不一定马上关闭,或者可以关闭
-                // 参考 send-SMS.vue 是关闭的
-                handleCancel();
-                emit('success');
-            }, 500);
+        nextTick(() => {
+            if (tableRef.value) {
+                tableRef.value.reload({ page: 1 });
+            }
         });
     };
 
@@ -222,5 +85,4 @@
 </script>
 
 <style scoped>
-    /* 可以在这里添加样式微调 */
 </style>

+ 1 - 1
src/views/mallOrder/refund/components/refund-item.vue

@@ -153,7 +153,7 @@
                 <div
                     class="action-btn text-green-500"
                     @click="$emit('push-sms', item)"
-                    >[推送短信]</div
+                    >[短信记录]</div
                 >
                 <div
                     class="action-btn text-orange-500"