Files
ruoyi-vue/src/views/system/jdorder/orderList.vue
2025-11-03 10:43:48 +08:00

421 lines
15 KiB
Vue

<template>
<div>
<list-layout>
<!-- 搜索区域 -->
<template #search>
<el-form :inline="true" :model="queryParams" label-width="80px">
<el-form-item label="备注">
<el-input v-model="queryParams.remark" placeholder="单据备注" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="分销标记">
<el-input v-model="queryParams.distributionMark" placeholder="分销标记" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="型号">
<el-input v-model="queryParams.modelNumber" placeholder="型号" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="订单号">
<el-input v-model="queryParams.orderId" placeholder="订单号" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="下单人">
<el-input v-model="queryParams.buyer" placeholder="下单人" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="地址">
<el-input v-model="queryParams.address" placeholder="收货地址" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="状态">
<el-input v-model="queryParams.status" placeholder="备注/状态" clearable size="small" @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="下单时间">
<el-date-picker
v-model="dateRange"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
size="small"
range-separator=""
@change="handleDateRangeChange"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" size="small" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button size="small" icon="el-icon-refresh" @click="resetQuery">重置</el-button>
<el-button type="warning" size="small" icon="el-icon-download" @click="handleExport" v-hasPermi="['system:jdorder:export']">导出</el-button>
</el-form-item>
</el-form>
</template>
<!-- 表格区域 -->
<template #table>
<el-table :data="list" v-loading="loading" border stripe :default-sort="{prop: 'createTime', order: 'descending'}" @sort-change="handleSortChange">
<el-table-column label="ID" prop="id" width="80" />
<el-table-column label="内部单号" prop="remark" width="160" sortable/>
<el-table-column label="订单号" prop="orderId" width="200">
<template slot-scope="scope">
<div>
<span style="margin-right: 8px;">{{ scope.row.orderId }}</span>
<el-button
type="text"
size="mini"
icon="el-icon-copy-document"
@click="copyToClipboard(scope.row.orderId)"
title="复制订单号"
>
复制
</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="标记" prop="distributionMark" width="80"/>
<el-table-column label="型号" prop="modelNumber" width="180"/>
<el-table-column label="地址" prop="address" min-width="320">
<template slot-scope="scope">
<div style="display: flex; align-items: center;">
<span class="ellipsis" style="flex:1; margin-right: 8px;" :title="scope.row.address">{{ scope.row.address }}</span>
<el-button
type="text"
size="mini"
icon="el-icon-copy-document"
@click="copyToClipboard(scope.row.address)"
title="复制地址"
>
复制
</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="付款金额" prop="paymentAmount" width="120">
<template slot-scope="scope">{{ toYuan(scope.row.paymentAmount) }}</template>
</el-table-column>
<el-table-column label="后返金额" prop="rebateAmount" width="120">
<template slot-scope="scope">{{ toYuan(scope.row.rebateAmount) }}</template>
</el-table-column>
<el-table-column label="下单人" prop="buyer" width="140"/>
<el-table-column label="备注/状态" prop="status" min-width="160"/>
<el-table-column label="参与统计" prop="isCountEnabled" width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.isCountEnabled"
:active-value="1"
:inactive-value="0"
@change="handleCountEnabledChange(scope.row)"
active-text=""
inactive-text="">
</el-switch>
</template>
</el-table-column>
<el-table-column label="物流链接" prop="logisticsLink" width="200">
<template slot-scope="scope">
<div v-if="scope.row.logisticsLink">
<a :href="scope.row.logisticsLink" target="_blank" style="margin-right: 8px;">查看物流</a>
<el-button
type="text"
size="mini"
icon="el-icon-copy-document"
@click="copyToClipboard(scope.row.logisticsLink)"
title="复制链接"
>
复制
</el-button>
</div>
</template>
</el-table-column>
<el-table-column label="赔付金额" prop="proPriceAmount" width="140"/>
<el-table-column label="创建时间" prop="createTime" width="160" sortable="custom">
<template slot-scope="scope">{{ parseTime(scope.row.createTime) }}</template>
</el-table-column>
<el-table-column label="完成时间" prop="finishTime" width="160">
<template slot-scope="scope">{{ parseTime(scope.row.finishTime) }}</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="120">
<template slot-scope="scope">
<el-button type="text" size="mini" style="color: #f56c6c;" @click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</template>
<!-- 分页区域 -->
<template #pagination>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</template>
</list-layout>
</div>
</template>
<script>
import { listJDOrders, updateJDOrder, delJDOrder } from '@/api/system/jdorder'
import ListLayout from '@/components/ListLayout'
export default {
name: 'JDOrderList',
components: {
ListLayout
},
data() {
return {
loading: false,
list: [],
total: 0,
dateRange: [],
queryParams: {
pageNum: 1,
pageSize: 50,
remark: undefined,
distributionMark: undefined,
modelNumber: undefined,
link: undefined,
orderId: undefined,
buyer: undefined,
address: undefined,
status: undefined,
beginTime: null,
endTime: null,
orderBy: 'create_time',
isAsc: 'desc'
}
}
},
created() {
// 设置默认日期为今天
this.setDefaultDateRange()
this.getListWithFallback()
},
methods: {
/** 设置默认日期范围为今天 */
setDefaultDateRange() {
const today = new Date()
const todayStr = this.formatDate(today)
this.dateRange = [todayStr, todayStr]
this.queryParams.beginTime = todayStr
this.queryParams.endTime = todayStr
},
/** 格式化日期为 yyyy-MM-dd 格式 */
formatDate(date) {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
},
getList() {
this.loading = true
listJDOrders(this.queryParams).then(res => {
this.list = (res.rows || res.data || [])
this.total = res.total || 0
this.loading = false
}).catch(() => { this.loading = false })
},
/** 智能查询列表,如果今天数据为空则查询昨天 */
async getListWithFallback() {
this.loading = true
try {
const res = await listJDOrders(this.queryParams)
this.list = (res.rows || res.data || [])
this.total = res.total || 0
// 如果今天的数据为空,且是默认查询(没有手动选择日期),则尝试查询昨天
if (this.list.length === 0 && this.isDefaultQuery()) {
this.$message.info('今天暂无慢单数据,正在查询昨天的数据...')
// 获取昨天的日期
const yesterday = new Date()
yesterday.setDate(yesterday.getDate() - 1)
const yesterdayStr = this.formatDate(yesterday)
// 更新查询参数为昨天
this.queryParams.beginTime = yesterdayStr
this.queryParams.endTime = yesterdayStr
this.dateRange = [yesterdayStr, yesterdayStr]
// 查询昨天的数据
const yesterdayRes = await listJDOrders(this.queryParams)
this.list = (yesterdayRes.rows || yesterdayRes.data || [])
this.total = yesterdayRes.total || 0
if (this.list.length > 0) {
this.$message.success(`已查询到昨天(${yesterdayStr})的慢单数据`)
} else {
this.$message.warning('昨天也没有慢单数据')
}
}
this.loading = false
} catch (error) {
this.loading = false
this.$message.error('查询失败,请稍后重试')
}
},
/** 判断是否为默认查询(今天的数据) */
isDefaultQuery() {
const today = new Date()
const todayStr = this.formatDate(today)
return this.queryParams.beginTime === todayStr && this.queryParams.endTime === todayStr
},
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 50,
remark: undefined,
distributionMark: undefined,
modelNumber: undefined,
link: undefined,
orderId: undefined,
buyer: undefined,
address: undefined,
status: undefined,
beginTime: null,
endTime: null
}
// 重置排序为默认降序
this.queryParams.orderBy = 'create_time'
this.queryParams.isAsc = 'desc'
// 重置后重新设置默认日期为今天
this.setDefaultDateRange()
this.getListWithFallback()
},
/** 日期范围变化处理 */
handleDateRangeChange(dates) {
if (dates && dates.length === 2) {
this.queryParams.beginTime = dates[0]
this.queryParams.endTime = dates[1]
} else {
this.queryParams.beginTime = null
this.queryParams.endTime = null
}
},
/** 表格排序变化处理 */
handleSortChange(sortInfo) {
if (sortInfo && sortInfo.prop === 'createTime') {
if (sortInfo.order === 'ascending') {
this.queryParams.orderBy = 'create_time'
this.queryParams.isAsc = 'asc'
} else if (sortInfo.order === 'descending') {
this.queryParams.orderBy = 'create_time'
this.queryParams.isAsc = 'desc'
} else {
// 取消排序,恢复默认
this.queryParams.orderBy = 'create_time'
this.queryParams.isAsc = 'desc'
}
// 重新查询数据
this.queryParams.pageNum = 1
this.getList()
}
},
toYuan(n) {
if (n == null || n === '') return ''
const num = Number(n)
if (Number.isNaN(num)) return n
return num.toFixed(2)
},
/** 导出按钮操作 */
handleExport() {
this.download('/system/jdorder/export', this.queryParams, `京东订单数据_${new Date().getTime()}.xlsx`)
},
/** 复制到剪贴板 */
copyToClipboard(text) {
if (navigator.clipboard && window.isSecureContext) {
// 使用现代 Clipboard API
navigator.clipboard.writeText(text).then(() => {
this.$message.success('已复制到剪贴板')
}).catch(() => {
this.fallbackCopyTextToClipboard(text)
})
} else {
// 降级方案
this.fallbackCopyTextToClipboard(text)
}
},
/** 降级复制方案 */
fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea')
textArea.value = text
textArea.style.position = 'fixed'
textArea.style.left = '-999999px'
textArea.style.top = '-999999px'
document.body.appendChild(textArea)
textArea.focus()
textArea.select()
try {
const successful = document.execCommand('copy')
if (successful) {
this.$message.success('已复制到剪贴板')
} else {
this.$message.error('复制失败,请手动复制')
}
} catch (err) {
this.$message.error('复制失败,请手动复制')
}
document.body.removeChild(textArea)
},
/** 处理统计开关变化 */
handleCountEnabledChange(row) {
// 调用后端API更新数据库
updateJDOrder(row).then(() => {
this.$message.success(`订单 ${row.remark} 的统计状态已更新为:${row.isCountEnabled ? '参与统计' : '不参与统计'}`)
}).catch(() => {
this.$message.error('更新失败,请稍后重试')
// 恢复原状态
row.isCountEnabled = row.isCountEnabled ? 0 : 1
})
},
/** 删除单条记录(需输入随机确认码) */
async handleDelete(row) {
const code = String(Math.floor(100000 + Math.random() * 900000))
try {
await this.$prompt(`请输入确认码以删除该订单:${code}`, '删除确认', {
confirmButtonText: '删除',
cancelButtonText: '取消',
inputPlaceholder: '请输入上方确认码',
inputValidator: (value) => {
if (value === code) return true
return '确认码不匹配,请重新输入'
},
inputErrorMessage: '确认码不匹配',
type: 'warning',
dangerouslyUseHTMLString: false
})
} catch (e) {
return
}
this.loading = true
try {
await delJDOrder(row.id)
this.$message.success('删除成功')
this.getList()
} catch (e) {
this.$message.error('删除失败,请稍后重试')
} finally {
this.loading = false
}
}
}
}
</script>
<style scoped>
</style>