初始化项目

This commit is contained in:
2026-09-01 22:15:50 +08:00
commit b5a26a8848
11217 changed files with 1710987 additions and 0 deletions
+652
View File
@@ -0,0 +1,652 @@
<template>
<a-card :bordered="false">
<a-spin :spinning="isLoading">
<div class="card-title">{{ $route.meta.title }}</div>
<div class="table-operator">
<!-- 搜索板块 -->
<a-row class="row-item-search">
<a-form class="search-form" :form="searchForm" layout="inline" @submit="handleSearch">
<a-form-item label="关键词">
<a-input style="width: 342px" placeholder="请输入关键词" v-decorator="['searchValue']">
<a-select
slot="addonBefore"
v-decorator="['searchType', { initialValue: 10 }]"
style="width: 100px"
>
<a-select-option
v-for="(item, index) in SearchTypeEnum"
:key="index"
:value="item.value"
>{{ item.name }}</a-select-option>
</a-select>
</a-input>
</a-form-item>
<a-form-item label="订单来源">
<a-select v-decorator="['orderSource', { initialValue: -1 }]">
<a-select-option :value="-1">全部</a-select-option>
<a-select-option
v-for="(item, index) in OrderSourceEnum.data"
:key="index"
:value="item.value"
>{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="支付方式">
<a-select v-decorator="['payType', { initialValue: -1 }]">
<a-select-option :value="-1">全部</a-select-option>
<a-select-option
v-for="(item, index) in PayTypeEnum.data"
:key="index"
:value="item.value"
>{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="一级代理商">
<a-select v-decorator="['spread_uid', { initialValue: -1 }]">
<a-select-option :value="-1">全部</a-select-option>
<a-select-option
v-for="(item, index) in merchantListData"
:key="index"
:value="item.merchant_id"
>{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="支付状态">
<a-select v-decorator="['pay_status', { initialValue: -1 }]">
<a-select-option :value="-1">全部</a-select-option>
<a-select-option
v-for="(item, index) in PayStatusEnum.data"
:key="index"
:value="item.value"
>{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="分油状态">
<a-select v-decorator="['oil_status', { initialValue: -1 }]">
<a-select-option :value="-1">全部</a-select-option>
<a-select-option
v-for="(item, index) in OilStatusEnum.data"
:key="index"
:value="item.value"
>{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="使用状态">
<a-select v-decorator="['use_status', { initialValue: -1 }]">
<a-select-option :value="-1">全部</a-select-option>
<a-select-option
v-for="(item, index) in UseStatusEnum.data"
:key="index"
:value="item.value"
>{{ item.name }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="商品编码">
<a-input v-decorator="['goods_no']" placeholder="商品编码" />
</a-form-item>
<a-form-item label="油卡编号">
<a-input v-decorator="['oilCardNo']" placeholder="油卡编号" />
</a-form-item>
<a-form-item label="分油记录编号">
<a-input v-decorator="['shareNo']" placeholder="分油记录编号" />
</a-form-item>
<template>
<a-config-provider :locale="zhCN">
<a-form-item label="下单时间">
<a-range-picker format="YYYY-MM-DD" v-decorator="['betweenTime']" />
</a-form-item>
</a-config-provider>
</template>
<a-form-item class="search-btn">
<a-button type="primary" icon="search" html-type="submit">搜索</a-button>
</a-form-item>
<a-form-item class="search-btn">
<a-button @click="handleReset">重置</a-button>
</a-form-item>
</a-form>
</a-row>
<div class="row-item-tab clearfix">
<span class="form-total">实付款:¥{{ total_money }}</span>
</div>
<!-- 操作板块 -->
<!-- <div class="row-item-tab clearfix">
<a-button icon="download">订单导出</a-button>
<a-button icon="upload">批量发货</a-button>
</div>-->
</div>
<!-- 列表内容 -->
<div class="ant-table ant-table-scroll-position-left ant-table-default ant-table-bordered">
<div class="ant-table-content">
<div class="ant-table-body">
<table>
<thead class="ant-table-thead">
<tr>
<th v-for="(item, index) in columns" :key="index">
<span class="ant-table-header-column">
<div>
<span class="ant-table-column-title">{{ item.title }}</span>
</div>
</span>
</th>
</tr>
</thead>
<tbody class="ant-table-tbody">
<template v-for="(item) in orderList.data">
<tr class="order-empty" :key="`order_${item.order_id}_1`">
<td colspan="15"></td>
</tr>
<tr :key="`order_${item.order_id}_2`">
<td colspan="15">
<span class="mr-20">{{ item.create_time }}</span>
<span class="mr-20">订单号:{{ item.order_no }}</span>
<platform-icon :name="item.platform" :showTips="true" />
</td>
</tr>
<tr
v-for="(goodsItm, goodsIdx) in item.goods"
:key="`orderGoods_${item.order_id}_${goodsIdx}`"
>
<td>
<GoodsItem
:data="{
image: goodsItm.goods_image,
imageAlt: '商品图片',
title: goodsItm.goods_name,
goods_no: goodsItm.goods_no,
goodsProps: goodsItm.goods_props
}"
/>
</td>
<td>
<p>¥{{ goodsItm.goods_price }}</p>
<p>×{{ goodsItm.total_num }}</p>
</td>
<td>
<div class="actions">
<!--<router-link
v-if="$auth('/order/detail')"
:to="{ path: '/order/detail', query: { orderId: item.order_id } }"
>详情</router-link>
<a
v-action:deliver
v-if="(
item.pay_status == PayStatusEnum.SUCCESS.value
&& item.delivery_type == DeliveryTypeEnum.EXPRESS.value
&& item.delivery_status == DeliveryStatusEnum.NOT_DELIVERED.value
&& !inArray(item.order_status, [OrderStatusEnum.CANCELLED.value, OrderStatusEnum.APPLY_CANCEL.value])
)"
@click="handleDelivery(item)"
>发货</a>
<a
v-action:cancel
v-if="item.order_status == OrderStatusEnum.APPLY_CANCEL.value"
@click="handleCancel(item)"
>审核取消</a>
<a v-action:delete @click="handleDelete(item)">删除</a>
<a
v-if="$auth('/order/cancelshare') && (goodsItm.oilCardType !== 'zsy_ticket') && (
inArray(item.order_status, [OrderStatusEnum.COMPLETED.value])
)"
@click="handleCancelShare(goodsItm)"
>分油撤销</a>-->
<!--有付款权限,订单状态为进行中,已支付,并且未使用-->
<a
v-if="$auth('/order/pay') && (
inArray(item.order_status, [OrderStatusEnum.NORMAL.value])
) && inArray(item.pay_status, [PayStatusEnum.SUCCESS.value]) && goodsItm.use_status === 0 && goodsItm.oil_status === 1 && goodsItm.oilCardType === 'zsy_ticket'"
@click="handlePay(goodsItm)"
>付款码</a>
<a
v-if="$auth('/order/pay') && (
inArray(item.order_status, [OrderStatusEnum.NORMAL.value])
) && inArray(item.pay_status, [PayStatusEnum.SUCCESS.value]) && goodsItm.oil_status === 0 && goodsItm.oilCardType === 'zsy_ticket'"
@click="handleShare(goodsItm)"
>手动分油</a>
</div>
</td>
<template v-if="goodsIdx===0">
<td :rowspan="item.goods.length">
<p>¥{{ item.pay_price }}</p>
<p class="c-muted-1">(含运费:¥{{ item.express_price }})</p>
</td>
<td :rowspan="item.goods.length">
<UserItem :user="item.user" />
</td>
<td :rowspan="item.goods.length">
<a-tag>{{ OrderSourceEnum[item.order_source].name }}</a-tag>
</td>
<td :rowspan="item.goods.length">
<a-tag>{{ PayTypeEnum[item.pay_type].name }}</a-tag>
</td>
<td :rowspan="item.goods.length">
<p>{{ item.spreadOne ? item.spreadOne.name : '' }}</p>
</td>
<td :rowspan="item.goods.length">
<p>{{ goodsItm.province }}</p>
</td>
<td :rowspan="item.goods.length">
<p>{{ OilCardTypeEnum[goodsItm.oilCardType].name }}</p>
</td>
<td :rowspan="item.goods.length">
<p>{{ goodsItm.oilCardNo }}</p>
</td>
<td :rowspan="item.goods.length">
<p>{{ goodsItm.shareNo }}</p>
</td>
<td :rowspan="item.goods.length">
<p class="mtb-2">
<span class="f-13">付款状态:</span>
<a-tag
:color="item.pay_status == PayStatusEnum.SUCCESS.value ? 'green' : ''"
>{{ PayStatusEnum[item.pay_status].name }}</a-tag>
</p>
<p class="mtb-2">
<span class="f-13">分油状态:</span>
<a-tag
:color="goodsItm.oil_status == OilStatusEnum.OIL.value ? 'green' : ''"
>{{ OilStatusEnum[goodsItm.oil_status].name }}</a-tag>
</p>
<p class="mtb-2">
<span class="f-13">使用状态:</span>
<a-tag
:color="goodsItm.use_status == UseStatusEnum.USE.value ? 'green' : ''"
>{{ UseStatusEnum[goodsItm.use_status].name }}</a-tag>
</p>
<p
v-if="[OrderStatusEnum.CANCELLED.value,OrderStatusEnum.APPLY_CANCEL.value].includes(item.order_status)"
class="mtb-2"
>
<span class="f-13">订单状态:</span>
<a-tag
:color="renderOrderStatusColor(item.order_status)"
>{{ OrderStatusEnum[item.order_status].name }}</a-tag>
</p>
</td>
</template>
</tr>
</template>
</tbody>
</table>
</div>
<!-- 空状态 -->
<a-empty v-if="!orderList.data.length" :image="simpleImage" />
</div>
</div>
<!-- 分页器 -->
<div v-if="orderList.data.length" class="pagination">
<a-pagination
:current="page"
:pageSize="orderList.per_page"
:total="orderList.total"
@change="onChangePage"
/>
</div>
<DeliveryForm ref="DeliveryForm" @handleSubmit="handleRefresh" />
<CancelForm ref="CancelForm" @handleSubmit="handleRefresh" />
<CancelShareForm ref="CancelShareForm" @handleSubmit="handleRefresh" />
<ShareForm ref="ShareForm" @handleSubmit="handleRefresh" />
<PayForm ref="PayForm" @handleSubmit="handleRefresh" />
</a-spin>
</a-card>
</template>
<script>
import { Empty } from 'ant-design-vue'
import { inArray, assignment } from '@/utils/util'
import * as Api from '@/api/order'
import * as EventApi from '@/api/order/event'
import PlatformIcon from '@/components/PlatformIcon'
import { GoodsItem, UserItem } from '@/components/Table'
import * as MerchantApi from '@/api/merchant'
import zhCN from 'ant-design-vue/es/locale/zh_CN'
import {
DeliveryStatusEnum,
DeliveryTypeEnum,
OrderSourceEnum,
OrderStatusEnum,
PayStatusEnum,
PayTypeEnum,
ReceiptStatusEnum,
OilCardTypeEnum,
OilStatusEnum,
UseStatusEnum
} from '@/common/enum/order'
import { DeliveryForm, CancelForm, CancelShareForm, ShareForm, PayForm } from './modules'
// 表格字段
const columns = [
{
title: '商品信息',
align: 'center',
dataIndex: 'goods',
scopedSlots: { customRender: 'goods' }
},
{
title: '单价/数量',
align: 'center',
scopedSlots: { customRender: 'unit_price' }
},
{
title: '操作',
dataIndex: 'action',
width: '180px',
scopedSlots: { customRender: 'action' }
},
{
title: '实付款',
align: 'center',
dataIndex: 'pay_price',
scopedSlots: { customRender: 'pay_price' }
},
{
title: '买家',
dataIndex: 'user',
scopedSlots: { customRender: 'user' }
},
{
title: '订单来源',
dataIndex: 'order_source',
scopedSlots: { customRender: 'order_source' }
},
{
title: '支付方式',
dataIndex: 'pay_type',
scopedSlots: { customRender: 'pay_type' }
},
{
title: '一级代理商',
dataIndex: 'spreadOne',
scopedSlots: { customRender: 'spreadOne' }
},
{
title: '省份',
align: 'center',
dataIndex: 'province',
scopedSlots: { customRender: 'province' }
},
{
title: '卡券类型',
align: 'center',
dataIndex: 'oilCardType',
scopedSlots: { customRender: 'oilCardType' }
},
{
title: '油卡编号',
dataIndex: 'oilCardNo',
scopedSlots: { customRender: 'oilCardNo' }
},
{
title: '分油记录编号',
dataIndex: 'shareNo',
scopedSlots: { customRender: 'shareNo' }
},
{
title: '交易状态',
dataIndex: 'status',
scopedSlots: { customRender: 'status' }
}
]
// 搜索关键词类型枚举
const SearchTypeEnum = [
{ name: '订单号', value: 10 },
{ name: '会员昵称', value: 20 },
{ name: '会员ID', value: 30 },
{ name: '收货人姓名', value: 40 },
{ name: '收货人电话', value: 50 }
]
export default {
name: 'Index',
components: {
PlatformIcon,
GoodsItem,
UserItem,
DeliveryForm,
CancelForm,
CancelShareForm,
ShareForm,
PayForm
},
data () {
return {
// 订单类型
dataType: this.getDataType(),
// 当前表单元素
searchForm: this.$form.createForm(this),
// 查询参数
queryParam: {},
// 正在加载
isLoading: false,
// 表格字段
columns,
// 当前页码
page: 1,
// 列表数据
orderList: { data: [], total: 0, per_page: 10 },
// 代理商列表
merchantListData: [],
total_money: 0,
zhCN
}
},
beforeCreate () {
// 批量给当前实例赋值
assignment(this, {
inArray,
DeliveryStatusEnum,
DeliveryTypeEnum,
OrderSourceEnum,
OrderStatusEnum,
PayStatusEnum,
PayTypeEnum,
ReceiptStatusEnum,
SearchTypeEnum,
OilCardTypeEnum,
OilStatusEnum,
UseStatusEnum,
simpleImage: Empty.PRESENTED_IMAGE_SIMPLE
})
},
created () {
// 初始化页面
this.init()
},
watch: {
// 监听路由变化
$route () {
this.init()
}
},
methods: {
// 初始化页面
init () {
this.dataType = this.getDataType()
this.searchForm.resetFields()
this.queryParam = {}
this.handleRefresh(true)
},
// 获取当前标签
getDataType () {
return this.$route.path.split('/')[3]
},
// 获取列表数据
getList () {
const { dataType, queryParam, page } = this
this.isLoading = true
return Api.list({ dataType, ...queryParam, page })
.then(response => {
this.orderList = response.data.list
this.total_money = response.data.total_money
})
.finally(() => {
this.isLoading = false
})
},
// 渲染订单状态标签颜色
renderOrderStatusColor (orderStatus) {
const { OrderStatusEnum } = this
const ColorEnum = {
[OrderStatusEnum.NORMAL.value]: '',
[OrderStatusEnum.CANCELLED.value]: 'red',
[OrderStatusEnum.APPLY_CANCEL.value]: 'red',
[OrderStatusEnum.COMPLETED.value]: 'green'
}
return ColorEnum[orderStatus]
},
/**
* 刷新列表
* @param Boolean bool 强制刷新到第一页
*/
handleRefresh (bool = false) {
bool && (this.page = 1)
this.getMerchantList()
this.getList()
},
// 确认搜索
handleSearch (e) {
e.preventDefault()
this.searchForm.validateFields((error, values) => {
if (!error) {
this.queryParam = { ...this.queryParam, ...values }
this.handleRefresh(true)
}
})
},
// 重置搜索表单
handleReset () {
this.searchForm.resetFields()
},
// 翻页事件
onChangePage (current) {
this.page = current
this.handleRefresh()
},
// 删除记录
handleDelete (item) {
const app = this
const modal = app.$confirm({
title: '您确定要删除该订单记录吗?',
content: '删除后不可恢复,请谨慎操作',
onOk () {
return EventApi.deleted(item.order_id)
.then((result) => {
app.$message.success(result.message, 1.5)
app.handleRefresh()
})
.finally(result => {
modal.destroy()
})
}
})
},
// 订单发货
handleDelivery (record) {
this.$refs.DeliveryForm.show(record)
},
// 审核取消订单
handleCancel (record) {
this.$refs.CancelForm.show(record)
},
// 分油撤销
handleCancelShare (record) {
this.$refs.CancelShareForm.show(record)
},
// 手动分油
handleShare (record) {
this.$refs.ShareForm.show(record)
},
// 付款码
handlePay (record) {
this.$refs.PayForm.show(record)
},
formatTime (timestamp) {
const date = new Date(timestamp)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0') // 月份是从0开始的
const day = String(date.getDate()).padStart(2, '0')
const hour = String(date.getHours()).padStart(2, '0')
const minute = String(date.getMinutes()).padStart(2, '0')
const second = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
},
/**
* 获取代理商列表
*/
getMerchantList () {
this.isLoading = true
MerchantApi.all()
.then(result => {
this.merchantListData = result.data.list
})
.finally(() => {
this.isLoading = false
})
}
}
}
</script>
<style lang="less" scoped>
// 分页器
.pagination {
margin-top: 16px;
.ant-pagination {
float: right;
}
}
.ant-table {
table {
border: none;
border-collapse: collapse;
}
.ant-table-thead > tr {
border: 1px solid #e8e8e8;
}
tr.order-empty {
height: 15px;
border: 1px solid #fff;
td {
padding: 0;
border-right: none;
border-left: none;
background: none !important;
}
}
}
.ant-table-thead > tr > th {
border-right: none;
border-bottom: none;
padding: 12px 12px;
font-weight: bold;
}
.ant-table-tbody > tr > td {
border-right: 1px solid #e8e8e8;
border-left: 1px solid #e8e8e8;
padding: 12px 12px;
// text-align: center;
}
.form-total{
color: #1890ff;
margin-right: 10px;
font-size: 20px;
font-weight: 500;
}
</style>