订单列表:自定义列抽离封装为组件

pull/284/head
puhui999 2023-10-18 17:20:13 +08:00
parent d1a3fe5d5a
commit 04d88ce1a6
4 changed files with 282 additions and 249 deletions

View File

@ -26,7 +26,7 @@ export const getDeliveryPickUpStore = async (id: number) => {
} }
// 查询自提门店精简列表 // 查询自提门店精简列表
export const getListAllSimple = async () => { export const getListAllSimple = async (): Promise<DeliveryPickUpStoreVO[]> => {
return await request.get({ url: '/trade/delivery/pick-up-store/list-all-simple' }) return await request.get({ url: '/trade/delivery/pick-up-store/list-all-simple' })
} }

View File

@ -0,0 +1,222 @@
<template>
<el-table-column class-name="order-table-col">
<template #header>
<!-- TODO @puhui999小屏幕下会有偏移后续看看 -->
<div class="flex items-center" style="width: 100%">
<div class="ml-100px mr-200px">商品信息</div>
<div class="mr-60px">单价()/数量</div>
<div class="mr-60px">售后状态</div>
<div class="mr-60px">实付金额()</div>
<div class="mr-60px">买家/收货人</div>
<div class="mr-60px">配送方式</div>
<div class="mr-60px">订单状态</div>
<div class="mr-60px">操作</div>
</div>
</template>
<template #default="scope">
<el-table
:border="true"
:data="scope.row.items"
:header-cell-style="headerStyle"
:span-method="spanMethod"
style="width: 100%"
>
<el-table-column class-name="table-col-1" min-width="300" prop="spuName">
<template #header>
<div
class="flex items-center"
style="width: 100%; height: 35px; background-color: #f7f7f7"
>
<span class="mr-20px">订单号{{ scope.row.no }} </span>
<span class="mr-20px">下单时间{{ formatDate(scope.row.createTime) }}</span>
<span>订单来源</span>
<dict-tag :type="DICT_TYPE.TERMINAL" :value="scope.row.terminal" class="mr-20px" />
<span>支付方式</span>
<dict-tag
v-if="scope.row.payChannelCode"
:type="DICT_TYPE.PAY_CHANNEL_CODE"
:value="scope.row.payChannelCode"
class="mr-20px"
/>
<span v-else class="mr-20px">未支付</span>
<span v-if="scope.row.payTime" class="mr-20px">
支付时间{{ formatDate(scope.row.payTime) }}
</span>
<span>订单类型</span>
<dict-tag :type="DICT_TYPE.TRADE_ORDER_TYPE" :value="scope.row.type" />
</div>
</template>
<template #default="{ row }">
<div class="flex items-center">
<el-image
:src="row.picUrl"
class="mr-10px h-30px w-30px"
@click="imagePreview(row.picUrl)"
/>
<span class="mr-10px">{{ row.spuName }}</span>
<el-tag v-for="property in row.properties" :key="property.propertyId" class="mr-10px">
{{ property.propertyName }}: {{ property.valueName }}
</el-tag>
</div>
</template>
</el-table-column>
<el-table-column class-name="table-col-2" label="商品原价*数量" prop="price" width="150">
<template #default="{ row }">
{{ floatToFixed2(row.price) }} / {{ row.count }}
</template>
</el-table-column>
<el-table-column
class-name="table-col-3"
label="售后状态"
prop="afterSaleStatus"
width="120"
>
<template #default="{ row }">
<dict-tag
:type="DICT_TYPE.TRADE_ORDER_ITEM_AFTER_SALE_STATUS"
:value="row.afterSaleStatus"
/>
</template>
</el-table-column>
<el-table-column
align="center"
class-name="table-col-4"
label="实际支付"
min-width="120"
prop="payPrice"
>
<template #default>
{{ floatToFixed2(scope.row.payPrice) + '元' }}
</template>
</el-table-column>
<el-table-column class-name="table-col-5" label="买家/收货人" min-width="160">
<template #default>
<!-- 快递发货 -->
<div
v-if="scope.row.deliveryType === DeliveryTypeEnum.EXPRESS.type"
class="flex flex-col"
>
<span>买家{{ scope.row.user.nickname }}</span>
<span>
收货人{{ scope.row.receiverName }} {{ scope.row.receiverMobile }}
{{ scope.row.receiverAreaName }} {{ scope.row.receiverDetailAddress }}
</span>
</div>
<!-- 自提 -->
<div
v-if="scope.row.deliveryType === DeliveryTypeEnum.PICK_UP.type"
class="flex flex-col"
>
<span>
门店名称
{{ pickUpStoreList.find((p) => p.id === scope.row.pickUpStoreId)?.name }}
</span>
<span>
门店手机
{{ pickUpStoreList.find((p) => p.id === scope.row.pickUpStoreId)?.phone }}
</span>
<span>
自提门店:
{{ pickUpStoreList.find((p) => p.id === scope.row.pickUpStoreId)?.detailAddress }}
</span>
</div>
</template>
</el-table-column>
<el-table-column align="center" class-name="table-col-6" label="配送方式" width="120">
<template #default>
<dict-tag :type="DICT_TYPE.TRADE_DELIVERY_TYPE" :value="scope.row.deliveryType" />
</template>
</el-table-column>
<el-table-column align="center" class-name="table-col-7" label="订单状态" width="120">
<template #default>
<dict-tag :type="DICT_TYPE.TRADE_ORDER_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column
align="center"
class-name="table-col-8"
fixed="right"
label="操作"
width="160"
>
<template #default>
<slot :row="scope.row"></slot>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
</template>
<script lang="ts" setup>
import { DICT_TYPE } from '@/utils/dict'
import { DeliveryTypeEnum } from '@/utils/constants'
import { formatDate } from '@/utils/formatTime'
import { floatToFixed2 } from '@/utils'
import * as TradeOrderApi from '@/api/mall/trade/order'
import { OrderVO } from '@/api/mall/trade/order'
import { TableColumnCtx } from 'element-plus'
import { createImageViewer } from '@/components/ImageViewer'
import type { DeliveryPickUpStoreVO } from '@/api/mall/trade/delivery/pickUpStore'
defineOptions({ name: 'OrderTableColumn' })
const props = defineProps<{
list: OrderVO[]
pickUpStoreList: DeliveryPickUpStoreVO[]
}>()
const headerStyle = ({ row, columnIndex }: any) => {
// 8
if (columnIndex === 0) {
row[columnIndex].colSpan = 8
} else {
//
row[columnIndex].colSpan = 0
return {
display: 'none'
}
}
}
interface SpanMethodProps {
row: TradeOrderApi.OrderItemRespVO
column: TableColumnCtx<TradeOrderApi.OrderItemRespVO>
rowIndex: number
columnIndex: number
}
type spanMethodResp = number[] | { rowspan: number; colspan: number } | undefined
const spanMethod = ({ row, rowIndex, columnIndex }: SpanMethodProps): spanMethodResp => {
const len = props.list.find(
(order) => order.items?.findIndex((item) => item.id === row.id) !== -1
)?.items?.length
//
const colIndex = [3, 4, 5, 6, 7]
if (colIndex.includes(columnIndex)) {
//
if (rowIndex !== 0) {
return {
rowspan: 0,
colspan: 0
}
}
//
return {
rowspan: len!,
colspan: 1
}
}
}
/** 商品图预览 */
const imagePreview = (imgUrl: string) => {
createImageViewer({
urlList: [imgUrl]
})
}
</script>
<style lang="scss" scoped>
:deep(.order-table-col > .cell) {
padding: 0;
}
</style>

View File

@ -0,0 +1,3 @@
import OrderTableColumn from './OrderTableColumn.vue'
export { OrderTableColumn }

View File

@ -163,177 +163,42 @@
<!-- 列表 --> <!-- 列表 -->
<ContentWrap> <ContentWrap>
<el-table v-loading="loading" :data="list"> <el-table v-loading="loading" :data="list">
<el-table-column class-name="order-table-col"> <OrderTableColumn :list="list" :pick-up-store-list="pickUpStoreList">
<template #header> <template #default="{ row }">
<!-- TODO @puhui999小屏幕下会有偏移后续看看 --> <!-- TODO 权限后续补齐 -->
<div class="flex items-center" style="width: 100%"> <div class="flex items-center justify-center">
<div class="ml-100px mr-200px">商品信息</div> <el-button link type="primary" @click="openDetail(row.id)">
<div class="mr-60px">单价()/数量</div> <Icon icon="ep:notification" />
<div class="mr-60px">售后状态</div> 详情
<div class="mr-60px">实付金额()</div> </el-button>
<div class="mr-60px">买家/收货人</div> <el-dropdown @command="(command) => handleCommand(command, row)">
<div class="mr-60px">配送方式</div> <el-button link type="primary">
<div class="mr-60px">订单状态</div> <Icon icon="ep:d-arrow-right" />
<div class="mr-60px">操作</div> 更多
</el-button>
<template #dropdown>
<el-dropdown-menu>
<!-- 如果是快递并且未发货则展示发货按钮 -->
<el-dropdown-item
v-if="
row.deliveryType === DeliveryTypeEnum.EXPRESS.type &&
row.status === TradeOrderStatusEnum.UNDELIVERED.status
"
command="delivery"
>
<Icon icon="ep:takeaway-box" />
发货
</el-dropdown-item>
<el-dropdown-item command="remark">
<Icon icon="ep:chat-line-square" />
备注
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div> </div>
</template> </template>
<template #default="scope"> </OrderTableColumn>
<el-table
:border="true"
:data="scope.row.items"
:header-cell-style="headerStyle"
:span-method="spanMethod"
style="width: 100%"
>
<el-table-column min-width="300" prop="spuName">
<template #header>
<div
class="flex items-center"
style="width: 100%; height: 35px; background-color: #f7f7f7"
>
<span class="mr-20px">订单号{{ scope.row.no }} </span>
<span class="mr-20px">下单时间{{ formatDate(scope.row.createTime) }}</span>
<span>订单来源</span>
<dict-tag
:type="DICT_TYPE.TERMINAL"
:value="scope.row.terminal"
class="mr-20px"
/>
<span>支付方式</span>
<dict-tag
v-if="scope.row.payChannelCode"
:type="DICT_TYPE.PAY_CHANNEL_CODE"
:value="scope.row.payChannelCode"
class="mr-20px"
/>
<v-else v-else class="mr-20px">未支付</v-else>
<span v-if="scope.row.payTime" class="mr-20px">
支付时间{{ formatDate(scope.row.payTime) }}
</span>
<span>订单类型</span>
<dict-tag :type="DICT_TYPE.TRADE_ORDER_TYPE" :value="scope.row.type" />
</div>
</template>
<template #default="{ row }">
<div class="flex items-center">
<el-image
:src="row.picUrl"
class="mr-10px h-30px w-30px"
@click="imagePreview(row.picUrl)"
/>
<span class="mr-10px">{{ row.spuName }}</span>
<el-tag
v-for="property in row.properties"
:key="property.propertyId"
class="mr-10px"
>
{{ property.propertyName }}: {{ property.valueName }}
</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="商品原价*数量" prop="price" width="150">
<template #default="{ row }">
{{ floatToFixed2(row.price) }} / {{ row.count }}
</template>
</el-table-column>
<el-table-column label="售后状态" prop="afterSaleStatus" width="120">
<template #default="{ row }">
<dict-tag
:type="DICT_TYPE.TRADE_ORDER_ITEM_AFTER_SALE_STATUS"
:value="row.afterSaleStatus"
/>
</template>
</el-table-column>
<el-table-column align="center" label="实际支付" min-width="120" prop="payPrice">
<template #default>
{{ floatToFixed2(scope.row.payPrice) + '元' }}
</template>
</el-table-column>
<el-table-column label="买家/收货人" min-width="160">
<template #default>
<!-- 快递发货 -->
<div
v-if="scope.row.deliveryType === DeliveryTypeEnum.EXPRESS.type"
class="flex flex-col"
>
<span>买家{{ scope.row.user.nickname }}</span>
<span>
收货人{{ scope.row.receiverName }} {{ scope.row.receiverMobile }}
{{ scope.row.receiverAreaName }} {{ scope.row.receiverDetailAddress }}
</span>
</div>
<!-- 自提 -->
<div
v-if="scope.row.deliveryType === DeliveryTypeEnum.PICK_UP.type"
class="flex flex-col"
>
<span>
门店名称
{{ pickUpStoreList.find((p) => p.id === scope.row.pickUpStoreId)?.name }}
</span>
<span>
门店手机
{{ pickUpStoreList.find((p) => p.id === scope.row.pickUpStoreId)?.phone }}
</span>
<span>
自提门店:
{{
pickUpStoreList.find((p) => p.id === scope.row.pickUpStoreId)?.detailAddress
}}
</span>
</div>
</template>
</el-table-column>
<el-table-column align="center" label="配送方式" width="120">
<template #default>
<dict-tag :type="DICT_TYPE.TRADE_DELIVERY_TYPE" :value="scope.row.deliveryType" />
</template>
</el-table-column>
<el-table-column align="center" label="订单状态" width="120">
<template #default>
<dict-tag :type="DICT_TYPE.TRADE_ORDER_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="160">
<template #default>
<!-- TODO 权限后续补齐 -->
<div class="flex items-center justify-center">
<el-button link type="primary" @click="openDetail(scope.row.id)">
<Icon icon="ep:notification" />
详情
</el-button>
<el-dropdown @command="(command) => handleCommand(command, scope.row)">
<el-button link type="primary">
<Icon icon="ep:d-arrow-right" />
更多
</el-button>
<template #dropdown>
<el-dropdown-menu>
<!-- 如果是快递并且未发货则展示发货按钮 -->
<el-dropdown-item
v-if="
scope.row.deliveryType === DeliveryTypeEnum.EXPRESS.type &&
scope.row.status === TradeOrderStatusEnum.UNDELIVERED.status
"
command="delivery"
>
<Icon icon="ep:takeaway-box" />
发货
</el-dropdown-item>
<el-dropdown-item command="remark">
<Icon icon="ep:chat-line-square" />
备注
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
</el-table> </el-table>
<!-- 分页 --> <!-- 分页 -->
<Pagination <Pagination
@ -350,22 +215,19 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import type { FormInstance, TableColumnCtx } from 'element-plus' import type { FormInstance } from 'element-plus'
import OrderDeliveryForm from '@/views/mall/trade/order/form/OrderDeliveryForm.vue' import OrderDeliveryForm from '@/views/mall/trade/order/form/OrderDeliveryForm.vue'
import OrderUpdateRemarkForm from '@/views/mall/trade/order/form/OrderUpdateRemarkForm.vue' import OrderUpdateRemarkForm from '@/views/mall/trade/order/form/OrderUpdateRemarkForm.vue'
import * as TradeOrderApi from '@/api/mall/trade/order' import * as TradeOrderApi from '@/api/mall/trade/order'
import * as PickUpStoreApi from '@/api/mall/trade/delivery/pickUpStore' import * as PickUpStoreApi from '@/api/mall/trade/delivery/pickUpStore'
import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import { floatToFixed2 } from '@/utils'
import { createImageViewer } from '@/components/ImageViewer'
import * as DeliveryExpressApi from '@/api/mall/trade/delivery/express' import * as DeliveryExpressApi from '@/api/mall/trade/delivery/express'
import { DeliveryTypeEnum, TradeOrderStatusEnum } from '@/utils/constants' import { DeliveryTypeEnum, TradeOrderStatusEnum } from '@/utils/constants'
import { OrderTableColumn } from './components'
defineOptions({ name: 'TradeOrder' }) defineOptions({ name: 'TradeOrder' })
const { currentRoute, push } = useRouter() // const { currentRoute, push } = useRouter() //
const loading = ref(true) // const loading = ref(true) //
const total = ref(2) // const total = ref(2) //
const list = ref<TradeOrderApi.OrderVO[]>([]) // const list = ref<TradeOrderApi.OrderVO[]>([]) //
@ -374,15 +236,15 @@ const queryFormRef = ref<FormInstance>() // 搜索的表单
const queryParams = ref({ const queryParams = ref({
pageNo: 1, // pageNo: 1, //
pageSize: 10, // pageSize: 10, //
status: null, // status: undefined, //
payChannelCode: null, // payChannelCode: undefined, //
createTime: null, // createTime: undefined, //
terminal: null, // terminal: undefined, //
type: null, // type: undefined, //
deliveryType: null, // deliveryType: undefined, //
logisticsId: null, // logisticsId: undefined, //
pickUpStoreId: null, // pickUpStoreId: undefined, //
pickUpVerifyCode: null // pickUpVerifyCode: undefined //
}) })
const queryType = reactive({ queryParam: '' }) // queryParam const queryType = reactive({ queryParam: '' }) // queryParam
@ -408,48 +270,6 @@ const inputChangeSelect = (val: string) => {
}) })
} }
const headerStyle = ({ row, columnIndex }: any) => {
// 8
if (columnIndex === 0) {
row[columnIndex].colSpan = 8
} else {
//
row[columnIndex].colSpan = 0
return {
display: 'none'
}
}
}
interface SpanMethodProps {
row: TradeOrderApi.OrderItemRespVO
column: TableColumnCtx<TradeOrderApi.OrderItemRespVO>
rowIndex: number
columnIndex: number
}
const spanMethod = ({ row, rowIndex, columnIndex }: SpanMethodProps) => {
const len = list.value.find(
(order) => order.items?.findIndex((item) => item.id === row.id) !== -1
)?.items?.length
//
const colIndex = [3, 4, 5, 6, 7]
if (colIndex.includes(columnIndex)) {
//
if (rowIndex !== 0) {
return {
rowspan: 0,
colspan: 0
}
}
//
return {
rowspan: len,
colspan: 1
}
}
}
/** 查询列表 */ /** 查询列表 */
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
@ -472,28 +292,21 @@ const handleQuery = async () => {
const resetQuery = () => { const resetQuery = () => {
queryFormRef.value?.resetFields() queryFormRef.value?.resetFields()
queryParams.value = { queryParams.value = {
pickUpVerifyCode: null, //
pageNo: 1, // pageNo: 1, //
pageSize: 10, // pageSize: 10, //
status: null, // status: undefined, //
payChannelCode: null, // payChannelCode: undefined, //
createTime: null, // createTime: undefined, //
terminal: null, // terminal: undefined, //
type: null, // type: undefined, //
deliveryType: null, // deliveryType: undefined, //
logisticsId: null, // logisticsId: undefined, //
pickUpStoreId: null // pickUpStoreId: undefined, //
pickUpVerifyCode: undefined //
} }
handleQuery() handleQuery()
} }
/** 商品图预览 */
const imagePreview = (imgUrl: string) => {
createImageViewer({
urlList: [imgUrl]
})
}
/** 查看订单详情 */ /** 查看订单详情 */
const openDetail = (id: number) => { const openDetail = (id: number) => {
push({ name: 'TradeOrderDetail', params: { id } }) push({ name: 'TradeOrderDetail', params: { id } })
@ -521,8 +334,8 @@ watch(
} }
) )
const pickUpStoreList = ref([]) // const pickUpStoreList = ref<PickUpStoreApi.DeliveryPickUpStoreVO[]>([]) //
const deliveryExpressList = ref([]) // const deliveryExpressList = ref<DeliveryExpressApi.DeliveryExpressVO[]>([]) //
/** 初始化 **/ /** 初始化 **/
onMounted(async () => { onMounted(async () => {
await getList() await getList()
@ -530,8 +343,3 @@ onMounted(async () => {
deliveryExpressList.value = await DeliveryExpressApi.getSimpleDeliveryExpressList() deliveryExpressList.value = await DeliveryExpressApi.getSimpleDeliveryExpressList()
}) })
</script> </script>
<style lang="scss" scoped>
:deep(.order-table-col > .cell) {
padding: 0;
}
</style>