Browse Source

订单列表:列表重构 ①

puhui999 1 year ago
parent
commit
2eb740765e

+ 110 - 12
src/api/mall/trade/order/index.ts

@@ -1,12 +1,110 @@
-import request from '@/config/axios'
-
-// 获得交易订单分页
-// TODO @xiaobai:改成 getOrderPage
-export const getOrderList = (params: PageParam) => {
-  return request.get({ url: '/trade/order/page', params })
-}
-
-// 获得交易订单详情
-export const getOrderDetail = (id: number) => {
-  return request.get({ url: '/trade/order/get-detail?id=' + id })
-}
+import request from '@/config/axios'
+
+export interface OrderVO {
+  id?: number // 订单编号
+  no?: string // 订单流水号
+  createTime?: Date // 下单时间
+  type?: number // 订单类型
+  terminal?: number // 订单来源
+  userId?: number // 用户编号
+  userIp?: string // 用户 IP
+  userRemark?: string // 用户备注
+  status?: number // 订单状态
+  productCount?: number // 购买的商品数量
+  finishTime?: Date // 订单完成时间
+  cancelTime?: Date // 订单取消时间
+  cancelType?: number // 取消类型
+  remark?: string // 商家备注
+  payOrderId: number // 支付订单编号
+  payed?: boolean // 是否已支付
+  payTime?: Date // 付款时间
+  payChannelCode?: string // 支付渠道
+  originalPrice?: number // 商品原价(总)
+  orderPrice?: number // 订单原价(总)
+  discountPrice?: number // 订单优惠(总)
+  deliveryPrice?: number // 运费金额
+  adjustPrice?: number // 订单调价(总)
+  payPrice?: number // 应付金额(总)
+  deliveryType?: number // 发货方式
+  deliveryTemplateId?: number // 配送模板编号
+  logisticsId?: number // 发货物流公司编号
+  logisticsNo?: string // 发货物流单号
+  deliveryStatus?: number // 发货状态
+  deliveryTime?: Date // 发货时间
+  receiveTime?: Date // 收货时间
+  receiverName?: string // 收件人名称
+  receiverMobile?: string // 收件人手机
+  receiverAreaId?: number // 收件人地区编号
+  receiverPostCode?: number // 收件人邮编
+  receiverDetailAddress?: string // 收件人详细地址
+  afterSaleStatus?: number // 售后状态
+  refundPrice?: number // 退款金额
+  couponId?: number // 优惠劵编号
+  couponPrice?: number // 优惠劵减免金额
+  pointPrice?: number // 积分抵扣的金额
+  receiverAreaName?: string //收件人地区名字
+  items?: OrderItemRespVO[] // 订单项列表
+  //用户信息
+  user?: {
+    id?: number
+    nickname?: string
+    avatar?: string
+  }
+}
+
+export interface OrderItemRespVO {
+  // ========== 订单项基本信息 ==========
+  id?: number // 编号
+  userId?: number // 用户编号
+  orderId?: number // 订单编号
+  // ========== 商品基本信息 ==========
+  spuId?: number // 商品 SPU 编号
+  spuName?: string //商品 SPU 名称
+  skuId?: number // 商品 SKU 编号
+  picUrl?: string //商品图片
+  count?: number //购买数量
+  // ========== 价格 + 支付基本信息 ==========
+  originalPrice?: number //商品原价(总)
+  originalUnitPrice?: number //商品原价(单)
+  discountPrice?: number //商品优惠(总)
+  payPrice?: number //商品实付金额(总)
+  orderPartPrice?: number //子订单分摊金额(总)
+  orderDividePrice?: number //分摊后子订单实付金额(总)
+  // ========== 营销基本信息 ==========
+  // TODO 芋艿:在捉摸一下
+  // ========== 售后基本信息 ==========
+  afterSaleStatus?: number // 售后状态
+  properties?: ProductPropertiesVO[] //属性数组
+}
+
+export interface ProductPropertiesVO {
+  propertyId?: number // 属性的编号
+  propertyName?: string // 属性的名称
+  valueId?: number //属性值的编号
+  valueName?: string // 属性值的名称
+}
+
+// 查询交易订单列表
+export const getOrderPage = async (params) => {
+  return await request.get({ url: `/trade/order/page`, params })
+}
+
+// 查询交易订单详情
+export const getOrder = async (id: number) => {
+  return await request.get({ url: `/trade/order/get?id=` + id })
+}
+
+// 新增交易订单
+export const createOrder = async (data: OrderVO) => {
+  return await request.post({ url: `/trade/order/create`, data })
+}
+
+// 修改交易订单
+export const updateOrder = async (data: OrderVO) => {
+  return await request.put({ url: `/trade/order/update`, data })
+}
+
+// 删除交易订单
+export const deleteOrder = async (id: number) => {
+  return await request.delete({ url: `/trade/order/delete?id=` + id })
+}

+ 0 - 228
src/api/mall/trade/order/type/orderType.ts

@@ -1,228 +0,0 @@
-// TODO @xiaobai:这个放到 order/index.ts  里哈
-// TODO @xiaobai:注释放到变量后面,这样简洁一点
-// TODO @xiaobai:这个改成 TradeOrderRespVO
-export interface TradeOrderPageItemRespVO {
-  // 订单编号
-  id?: number
-  // 订单流水号
-  no?: string
-  // 下单时间
-  createTime?: Date
-  // 订单类型
-  type?: number
-  // 订单来源
-  terminal?: number
-  // 用户编号
-  userId?: number
-  // 用户 IP
-  userIp?: string
-  // 用户备注
-  userRemark?: string
-  // 订单状态
-  status?: number
-  // 购买的商品数量
-  productCount?: number
-  // 订单完成时间
-  finishTime?: Date
-  // 订单取消时间
-  cancelTime?: Date
-  // 取消类型
-  cancelType?: number
-  // 商家备注
-  remark?: string
-  // 支付订单编号
-  payOrderId: number
-  // 是否已支付
-  payed?: boolean
-  // 付款时间
-  payTime?: Date
-  // 支付渠道
-  payChannelCode?: string
-  // 商品原价(总)
-  originalPrice?: number
-  // 订单原价(总)
-  orderPrice?: number
-  // 订单优惠(总)
-  discountPrice?: number
-  // 运费金额
-  deliveryPrice?: number
-  // 订单调价(总)
-  adjustPrice?: number
-  // 应付金额(总)
-  payPrice?: number
-  // 配送模板编号
-  deliveryTemplateId?: number
-  // 发货物流公司编号
-  logisticsId?: number
-  // 发货物流单号
-  logisticsNo?: string
-  // 发货状态
-  deliveryStatus?: number
-  // 发货时间
-  deliveryTime?: Date
-  // 收货时间
-  receiveTime?: Date
-  // 收件人名称
-  receiverName?: string
-  // 收件人手机
-  receiverMobile?: string
-  // 收件人地区编号
-  receiverAreaId?: number
-  // 收件人邮编
-  receiverPostCode?: number
-  // 收件人详细地址
-  receiverDetailAddress?: string
-  // 售后状态
-  afterSaleStatus?: number
-  // 退款金额
-  refundPrice?: number
-  // 优惠劵编号
-  couponId?: number
-  // 优惠劵减免金额
-  couponPrice?: number
-  // 积分抵扣的金额
-  pointPrice?: number
-  //收件人地区名字
-  receiverAreaName?: string
-  // 订单项列表
-  items?: TradeOrderItemBaseVO[]
-  //用户信息
-  user?: MemberUserRespDTO
-}
-
-// TODO @xiaobai:这个改成 TradeOrderItemRespVO
-/**
- * 交易订单项 Base VO,提供给添加、修改、详细的子 VO 使用
- * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
- */
-export interface TradeOrderItemBaseVO {
-  // ========== 订单项基本信息 ==========
-  /**
-   * 编号
-   */
-  id?: number
-  /**
-   * 用户编号
-   */
-  userId?: number
-  /**
-   * 订单编号
-   */
-  orderId?: number
-  // ========== 商品基本信息 ==========
-  /**
-   * 商品 SPU 编号
-   */
-  spuId?: number
-  /**
-   * 商品 SPU 名称
-   */
-  spuName?: string
-  /**
-   * 商品 SKU 编号
-   */
-  skuId?: number
-  /**
-   * 商品图片
-   */
-  picUrl?: string
-  /**
-   * 购买数量
-   */
-  count?: number
-  // ========== 价格 + 支付基本信息 ==========
-  /**
-   * 商品原价(总)
-   */
-  originalPrice?: number
-  /**
-   * 商品原价(单)
-   */
-  originalUnitPrice?: number
-  /**
-   * 商品优惠(总)
-   */
-  discountPrice?: number
-  /**
-   * 商品实付金额(总)
-   */
-  payPrice?: number
-  /**
-   * 子订单分摊金额(总)
-   */
-  orderPartPrice?: number
-  /**
-   * 分摊后子订单实付金额(总)
-   */
-  orderDividePrice?: number
-  // ========== 营销基本信息 ==========
-  // TODO 芋艿:在捉摸一下
-  // ========== 售后基本信息 ==========
-  /**
-   * 售后状态
-   */
-  afterSaleStatus?: number
-  //属性数组
-  properties?: ProductPropertyValueDetailRespVO[]
-}
-
-/**
- * 管理后台 - 商品属性值的明细 Response VO
- */
-export interface ProductPropertyValueDetailRespVO {
-  /**
-   * 属性的编号
-   */
-  propertyId?: number
-  /**
-   * 属性的名称
-   */
-  propertyName?: string
-  /**
-   * 属性值的编号
-   */
-  valueId?: number
-  /**
-   * 属性值的名称
-   */
-  valueName?: string
-}
-
-/**
- * 订单详情查询 请求
- */
-export interface TradeOrderPageReqVO {
-  pageNo: number
-  pageSize: number
-  no?: string
-  userId?: string
-  userNickname?: string
-  userMobile?: string
-  receiverName?: string
-  receiverMobile?: string
-  terminal?: string
-  type?: number
-  status?: number
-  payChannelCode?: string
-  createTime?: [Date, Date]
-  spuName?: string
-  itemCount?: string
-  all?: string
-}
-
-//用户信息
-export interface MemberUserRespDTO {
-  id?: number
-  nickname?: string
-  status?: number
-  avatar?: string
-  mobile?: string
-}
-//订单详情选中type
-export interface SelectType {
-  queryParams: TradeOrderPageReqVO
-  selectTotal: number //选中的数量
-  selectAllFlag: boolean //全选标识
-  selectData: Map<number, Set<string>> //存放涉及选中得页面以及每页选中得数据订单号  全选时根据条件查询 排除取消的list订单
-  unSelectList: Set<string> //登记取消的list 全选标识为true 时登记单独取消的list,再次选中时排除, 全选标识为false 时清空list
-}

+ 4 - 4
src/views/Login/components/LoginForm.vue

@@ -21,8 +21,8 @@
             v-model="loginData.loginForm.tenantName"
             :placeholder="t('login.tenantNamePlaceholder')"
             :prefix-icon="iconHouse"
-            type="primary"
             link
+            type="primary"
           />
         </el-form-item>
       </el-col>
@@ -148,8 +148,8 @@ import { ElLoading } from 'element-plus'
 import LoginFormTitle from './LoginFormTitle.vue'
 import type { RouteLocationNormalizedLoaded } from 'vue-router'
 
-import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
-const { wsCache } = useCache()
+// import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+// const { wsCache } = useCache()
 import { useIcon } from '@/hooks/web/useIcon'
 
 import * as authUtil from '@/utils/auth'
@@ -246,7 +246,7 @@ const handleLogin = async (params) => {
     if (!res) {
       return
     }
-    wsCache.delete(CACHE_KEY.USER) // 清除上次登录用户信息
+    // wsCache.delete(CACHE_KEY.USER) // 清除上次登录用户信息
     ElLoading.service({
       lock: true,
       text: '正在加载系统中...',

+ 367 - 0
src/views/mall/trade/order/detail/index.vue

@@ -0,0 +1,367 @@
+<template>
+  <Dialog v-model="dialogVisible" :scroll="true" :title="dialogTitle" width="65%">
+    <ContentWrap>
+      <!-- 订单信息 -->
+      <el-descriptions title="订单信息">
+        <el-descriptions-item label="订单号: ">{{ order.no }}</el-descriptions-item>
+        <el-descriptions-item label="配送方式: ">物流配送</el-descriptions-item>
+        <!-- TODO 芋艿:待实现 -->
+        <el-descriptions-item label="营销活动: ">物流配送</el-descriptions-item>
+        <!-- TODO 芋艿:待实现 -->
+        <el-descriptions-item label="订单类型: ">
+          <dict-tag :type="DICT_TYPE.TRADE_ORDER_TYPE" :value="order.type" />
+        </el-descriptions-item>
+        <el-descriptions-item label="收货人: ">{{ order.receiverName }}</el-descriptions-item>
+        <el-descriptions-item label="买家留言: ">{{ order.userRemark }}</el-descriptions-item>
+        <el-descriptions-item label="订单来源: ">
+          <dict-tag :type="DICT_TYPE.TERMINAL" :value="order.terminal" />
+        </el-descriptions-item>
+        <el-descriptions-item label="联系电话: ">{{ order.receiverMobile }}</el-descriptions-item>
+        <el-descriptions-item label="商家备注: ">{{ order.remark }}</el-descriptions-item>
+        <el-descriptions-item label="支付单号: ">{{ order.payOrderId }}</el-descriptions-item>
+        <el-descriptions-item label="付款方式: ">
+          <dict-tag :type="DICT_TYPE.PAY_CHANNEL_CODE_TYPE" :value="order.payChannelCode" />
+        </el-descriptions-item>
+        <!-- <el-descriptions-item label="买家: ">{{ order.user.nickname }}</el-descriptions-item> -->
+        <!-- TODO 芋艿:待实现:跳转会员 -->
+        <el-descriptions-item label="收货地址: ">
+          {{ order.receiverAreaName }} {{ order.receiverDetailAddress }}
+          <el-link
+            v-clipboard:copy="order.receiverAreaName + ' ' + order.receiverDetailAddress"
+            v-clipboard:success="clipboardSuccess"
+            icon="ep:document-copy"
+            type="primary"
+          />
+        </el-descriptions-item>
+      </el-descriptions>
+
+      <!-- 订单状态 -->
+      <el-descriptions :column="1" title="订单状态">
+        <el-descriptions-item label="订单状态: ">
+          <!-- TODO xiaobai:status 一定有值哈,不用判断 -->
+          <dict-tag
+            v-if="order.status !== ''"
+            :type="DICT_TYPE.TRADE_ORDER_STATUS"
+            :value="order.status"
+          />
+        </el-descriptions-item>
+        <el-descriptions-item label-class-name="no-colon">
+          <el-button size="small" type="primary">调整价格</el-button>
+          <!-- TODO 芋艿:待实现 -->
+          <el-button size="small" type="primary">备注</el-button>
+          <!-- TODO 芋艿:待实现 -->
+          <el-button size="small" type="primary">发货</el-button>
+          <!-- TODO 芋艿:待实现 -->
+          <el-button size="small" type="primary">关闭订单</el-button>
+          <!-- TODO 芋艿:待实现 -->
+          <el-button size="small" type="primary">修改地址</el-button>
+          <!-- TODO 芋艿:待实现 -->
+          <el-button size="small" type="primary">打印电子面单</el-button>
+          <!-- TODO 芋艿:待实现 -->
+          <el-button size="small" type="primary">打印发货单</el-button>
+          <!-- TODO 芋艿:待实现 -->
+          <el-button size="small" type="primary">确认收货</el-button>
+          <!-- TODO 芋艿:待实现 -->
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label><span style="color: red">提醒: </span></template>
+          买家付款成功后,货款将直接进入您的商户号(微信、支付宝)<br />
+          请及时关注你发出的包裹状态,确保可以配送至买家手中 <br />
+          如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商
+        </el-descriptions-item>
+      </el-descriptions>
+
+      <!-- 物流信息 TODO -->
+
+      <!-- 商品信息 -->
+      <el-descriptions title="商品信息">
+        <el-descriptions-item labelClassName="no-colon">
+          <el-row :gutter="20">
+            <el-col :span="15">
+              <el-table :data="order.items" border>
+                <el-table-column label="商品" prop="spuName" width="auto">
+                  <template #default="{ row }">
+                    {{ row.spuName }}
+                    <el-tag v-for="property in row.properties" :key="property.propertyId">
+                      {{ property.propertyName }}: {{ property.valueName }}
+                    </el-tag>
+                  </template>
+                </el-table-column>
+                <el-table-column label="商品原价(元)" prop="price" width="150">
+                  <template #default="{ row }">{{ formatToFraction(row.price) }}</template>
+                </el-table-column>
+                <el-table-column label="数量" prop="count" width="100" />
+                <el-table-column label="合计(元)" prop="payPrice" width="150">
+                  <template #default="{ row }">{{ formatToFraction(row.payPrice) }}</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>
+            </el-col>
+            <el-col :span="10" />
+          </el-row>
+        </el-descriptions-item>
+        <!-- 占位 -->
+        <!-- <el-descriptions-item v-for="item in 5" label-class-name="no-colon" :key="item" /> -->
+      </el-descriptions>
+      <el-descriptions column="6">
+        <el-descriptions-item label="商品总额: ">
+          {{ formatToFraction(order.totalPrice) }}元
+        </el-descriptions-item>
+        <el-descriptions-item label="运费金额: ">
+          {{ formatToFraction(order.deliveryPrice) }}元
+        </el-descriptions-item>
+        <el-descriptions-item label="订单调价: ">
+          {{ formatToFraction(order.adjustPrice) }}元
+        </el-descriptions-item>
+
+        <el-descriptions-item>
+          <template #label><span style="color: red">商品优惠: </span></template>
+          <!-- 没理解TODO  order.totalPrice - order.totalPrice -->
+          {{ formatToFraction(order.totalPrice - order.totalPrice) }}元
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label><span style="color: red">订单优惠: </span></template>
+          {{ formatToFraction(order.discountPrice) }}元
+        </el-descriptions-item>
+        <el-descriptions-item>
+          <template #label><span style="color: red">积分抵扣: </span></template>
+          {{ formatToFraction(order.pointPrice) }}元
+        </el-descriptions-item>
+
+        <el-descriptions-item v-for="item in 5" :key="item" label-class-name="no-colon" />
+        <!-- 占位 -->
+        <el-descriptions-item label="应付金额: ">
+          {{ formatToFraction(order.payPrice) }}元
+        </el-descriptions-item>
+      </el-descriptions>
+
+      <!-- TODO 芋艿:需要改改 -->
+      <div v-for="group in detailGroups" :key="group.title">
+        <el-descriptions :title="group.title" v-bind="group.groupProps">
+          <!-- 订单操作日志 -->
+          <el-descriptions-item v-if="group.key === 'orderLog'" labelClassName="no-colon">
+            <el-timeline>
+              <el-timeline-item
+                v-for="activity in detailInfo[group.key]"
+                :key="activity.timestamp"
+                :timestamp="activity.timestamp"
+              >
+                {{ activity.content }}
+              </el-timeline-item>
+            </el-timeline>
+          </el-descriptions-item>
+
+          <!-- 物流信息 -->
+          <!-- TODO @xiaobai:改成一个包裹哈;目前只允许发货一次 -->
+          <el-descriptions-item v-if="group.key === 'expressInfo'" labelClassName="no-colon">
+            <!-- 循环包裹物流信息 -->
+            <div v-show="(pkgInfo = detailInfo[group.key]) !== null" style="border: 1px dashed">
+              <!-- 包裹详情 -->
+              <el-descriptions class="m-5">
+                <el-descriptions-item
+                  v-for="(pkgChild, pkgCIdx) in group.children"
+                  :key="`pkgChild_${pkgCIdx}`"
+                  :label="pkgChild.label"
+                  v-bind="pkgChild.childProps"
+                >
+                  <!-- 包裹商品列表 -->
+                  <template v-if="pkgChild.valueKey === 'goodsList' && pkgInfo[pkgChild.valueKey]">
+                    <div
+                      v-for="(goodInfo, goodInfoIdx) in pkgInfo[pkgChild.valueKey]"
+                      :key="`goodInfo_${goodInfoIdx}`"
+                      style="display: flex"
+                    >
+                      <el-image
+                        :src="goodInfo.imgUrl"
+                        style="width: 100px; height: 100px; flex: none"
+                      />
+                      <el-descriptions :column="1">
+                        <el-descriptions-item labelClassName="no-colon"
+                          >{{ goodInfo.name }}
+                        </el-descriptions-item>
+                        <el-descriptions-item label="数量"
+                          >{{ goodInfo.count }}
+                        </el-descriptions-item>
+                      </el-descriptions>
+                    </div>
+                  </template>
+
+                  <!-- 包裹物流详情 -->
+                  <template v-else-if="pkgChild.valueKey === 'wlxq'">
+                    <el-row :gutter="10">
+                      <el-col :offset="1" :span="6">
+                        <el-timeline>
+                          <el-timeline-item
+                            v-for="(activity, index) in pkgInfo[pkgChild.valueKey]"
+                            :key="index"
+                            :timestamp="activity.timestamp"
+                          >
+                            {{ activity.content }}
+                          </el-timeline-item>
+                        </el-timeline>
+                      </el-col>
+                    </el-row>
+                  </template>
+                  <template v-else>
+                    {{ pkgInfo[pkgChild.valueKey] }}
+                  </template>
+                </el-descriptions-item>
+              </el-descriptions>
+            </div>
+          </el-descriptions-item>
+        </el-descriptions>
+      </div>
+    </ContentWrap>
+  </Dialog>
+</template>
+<script lang="ts" setup>
+import { formatToFraction } from '@/utils'
+import { DICT_TYPE } from '@/utils/dict'
+
+defineOptions({ name: 'TradeOrderDetailForm' })
+
+const message = useMessage() // 消息弹窗
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('订单详情') // 弹窗的标题
+
+const open = () => {
+  dialogVisible.value = true
+}
+defineExpose({ open })
+
+const { query } = useRoute()
+const queryParams = reactive({
+  id: query.id
+})
+
+const loading = ref(false)
+const order = ref<any>({
+  items: [],
+  user: {}
+}) // 详情数据
+
+const detailGroups = ref([
+  {
+    title: '物流信息',
+    key: 'expressInfo',
+    children: [
+      { label: '发货时间: ', valueKey: 'fhsj' },
+      { label: '物流公司: ', valueKey: 'wlgs' },
+      { label: '运单号: ', valueKey: 'ydh' },
+      { label: '物流状态: ', valueKey: 'wlzt', childProps: { span: 3 } },
+      { label: '物流详情: ', valueKey: 'wlxq' }
+    ]
+  },
+  {
+    title: '订单操作日志',
+    key: 'orderLog'
+  }
+])
+
+const detailInfo = ref({
+  expressInfo:
+    // 物流信息
+    {
+      label: '包裹1',
+      name: 'bg1',
+      fhsj: '2022-11-03 16:50:45',
+      wlgs: '极兔',
+      ydh: '2132123',
+      wlzt: '不支持此快递公司',
+      wlxq: [
+        {
+          content: '正在派送途中,请您准备签收(派件人:王涛,电话:13854563814)',
+          timestamp: '2018-04-15 15:00:16'
+        },
+        {
+          content: '快件到达 【烟台龙口东江村委营业点】',
+          timestamp: '2018-04-13 14:54:19'
+        },
+        {
+          content: '快件已发车',
+          timestamp: '2018-04-11 12:55:52'
+        },
+        {
+          content: '快件已发车',
+          timestamp: '2018-04-11 12:55:52'
+        },
+        {
+          content: '快件已发车',
+          timestamp: '2018-04-11 12:55:52'
+        }
+      ]
+    },
+  orderLog: [
+    // 订单操作日志
+    {
+      content: '买家【乌鸦】关闭了订单',
+      timestamp: '2018-04-15 15:00:16'
+    },
+    {
+      content: '买家【乌鸦】下单了',
+      timestamp: '2018-04-15 15:00:16'
+    }
+  ],
+  goodsInfo: [] // 商品详情tableData
+})
+// 暂考虑一次性加载详情页面所有数据 TODO
+const getlist = async () => {
+  // dialogVisible.value = true
+  // loading.value = true
+  // try {
+  //   const res = await TradeOrderApi.getOrderDetail(queryParams.id as unknown as number)
+  //   order.value = res
+  //   console.log(order)
+  // } catch {
+  //   message.error('获取详情数据失败')
+  // } finally {
+  //   loading.value = false
+  // }
+}
+onMounted(async () => {
+  await getlist()
+})
+const clipboardSuccess = () => {
+  message.success('复制成功')
+}
+</script>
+<style lang="scss" scoped>
+:deep(.el-descriptions) {
+  &:not(:nth-child(1)) {
+    margin-top: 20px;
+  }
+
+  .el-descriptions__title {
+    display: flex;
+    align-items: center;
+
+    &::before {
+      display: inline-block;
+      width: 3px;
+      height: 20px;
+      margin-right: 10px;
+      background-color: #409eff;
+      content: '';
+    }
+  }
+
+  .el-descriptions-item__container {
+    margin: 0 10px;
+
+    .no-colon {
+      margin: 0;
+
+      &::after {
+        content: '';
+      }
+    }
+  }
+}
+</style>

+ 376 - 572
src/views/mall/trade/order/index.vue

@@ -1,572 +1,376 @@
-<template>
-  <!-- 搜索 -->
-  <ContentWrap>
-    <el-form
-      ref="queryFormRef"
-      :model="queryParams"
-      class="-mb-15px"
-      label-width="68px"
-      :inline="true"
-    >
-      <el-form-item label="订单状态" prop="status">
-        <el-select class="!w-280px" v-model="queryParams.status" clearable placeholder="全部">
-          <el-option
-            v-for="dict in getStrDictOptions(DICT_TYPE.TRADE_ORDER_STATUS)"
-            :key="dict.value as string"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="支付方式" prop="payChannelCode">
-        <el-select
-          v-model="queryParams.payChannelCode"
-          class="!w-280px"
-          clearable
-          placeholder="全部"
-        >
-          <el-option
-            v-for="dict in getStrDictOptions(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)"
-            :key="dict.value as string"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="创建时间" prop="createTime">
-        <el-date-picker
-          v-model="queryParams.createTime"
-          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-280px"
-          start-placeholder="自定义时间"
-          end-placeholder="自定义时间"
-          type="daterange"
-          value-format="YYYY-MM-DD HH:mm:ss"
-        />
-      </el-form-item>
-      <el-form-item label="订单来源" prop="terminal">
-        <el-select class="!w-280px" v-model="queryParams.terminal" clearable placeholder="全部">
-          <el-option
-            v-for="dict in getStrDictOptions(DICT_TYPE.TERMINAL)"
-            :key="dict.value as string"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="订单类型" prop="type">
-        <el-select class="!w-280px" v-model="queryParams.type" clearable placeholder="全部">
-          <el-option
-            v-for="dict in getStrDictOptions(DICT_TYPE.TRADE_ORDER_TYPE)"
-            :key="dict.value as string"
-            :label="dict.label"
-            :value="dict.value"
-          />
-        </el-select>
-      </el-form-item>
-
-      <el-form-item label="订单搜索">
-        <el-input
-          v-show="true"
-          class="!w-280px"
-          v-model="queryType.v"
-          clearable
-          placeholder="请输入"
-        >
-          <template #prepend>
-            <el-select style="width: 110px" v-model="queryType.k" clearable placeholder="全部">
-              <el-option
-                v-for="dict in searchList"
-                :key="dict.value"
-                :label="dict.label"
-                :value="dict.value"
-              />
-            </el-select>
-          </template>
-        </el-input>
-      </el-form-item>
-      <el-form-item>
-        <el-button @click="handleQuery" v-hasPermi="['trade:order:query']">
-          <Icon class="mr-5px" icon="ep:search" />
-          搜索
-        </el-button>
-        <el-button @click="resetQuery" v-hasPermi="['trade:order:query']">
-          <Icon class="mr-5px" icon="ep:refresh" />
-          重置
-        </el-button>
-        <el-button type="success" plain @click="handleExport" :loading="exportLoading">
-          <!--           v-hasPermi="['trade:order:export']"        -->
-          <Icon icon="ep:download" class="mr-5px" /> 导出TODO
-        </el-button>
-      </el-form-item>
-    </el-form>
-  </ContentWrap>
-  <!-- 表格 -->
-  <ContentWrap>
-    <!-- 表单 -->
-    <el-table v-loading="loading" :data="list">
-      <el-table-column type="expand" fixed="left">
-        <template #default="scope">
-          <el-descriptions class="mx-40">
-            <el-descriptions-item label="商品原价(总): ">{{
-              '¥ ' +
-              parseFloat((scope.row.originalPrice / 100) as unknown as string).toFixed(2) +
-              ' 元'
-            }}</el-descriptions-item>
-            <el-descriptions-item label="下单时间: ">
-              {{ formatDate(scope.row.createTime) }}</el-descriptions-item
-            >
-            <el-descriptions-item label="推广人: ">TODO</el-descriptions-item>
-            <el-descriptions-item label="用户备注: ">{{
-              scope.row.userRemark
-            }}</el-descriptions-item>
-            <el-descriptions-item label="商家备注: ">{{ scope.row.remark }}</el-descriptions-item>
-          </el-descriptions>
-        </template>
-      </el-table-column>
-      <el-table-column width="100" fixed="left">
-        <template #header>
-          <el-dropdown icon="eq:search" @command="handleDropType">
-            <el-button link type="primary">全选({{ orderSelect.selectTotal }}) </el-button>
-
-            <template #dropdown>
-              <el-dropdown-menu>
-                <el-dropdown-item command="1">当前页</el-dropdown-item>
-                <el-dropdown-item command="2">所有页</el-dropdown-item>
-              </el-dropdown-menu>
-            </template>
-          </el-dropdown>
-        </template>
-        <template #default="scope">
-          <el-checkbox v-model="scope.row.itemSelect" @change="handcheckclick(scope.row)" />
-        </template>
-      </el-table-column>
-
-      <el-table-column label="订单号" align="center" min-width="110">
-        <template #default="scope">
-          <el-button link type="primary" @click="showOrderDetail(scope.row)">{{
-            scope.row.no
-          }}</el-button>
-        </template>
-      </el-table-column>
-      <el-table-column label="订单类型" align="center" min-width="100">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.TRADE_ORDER_TYPE" :value="scope.row.type" />
-        </template>
-      </el-table-column>
-      <el-table-column label="用户信息" align="center" min-width="100">
-        <template #default="scope">
-          <el-button link type="primary" @click="goUserDetail(scope.row)"
-            >{{ scope.row.userId }}{{ '[' + scope.row.user.nickname + ']' }}</el-button
-          >
-        </template>
-      </el-table-column>
-      <el-table-column
-        :formatter="dateFormatter"
-        align="center"
-        label="创建时间"
-        prop="createTime"
-        min-width="180"
-      />
-      <el-table-column label="订单来源" align="center" min-width="100">
-        <template #default="scope">
-          <dict-tag
-            v-if="scope.row.terminal"
-            :type="DICT_TYPE.TERMINAL"
-            :value="scope.row.terminal"
-          />
-          <span v-else>{{ scope.terminal }}</span>
-        </template>
-      </el-table-column>
-
-      <el-table-column label="商品信息" align="left" min-width="200" prop="items">
-        <template #default="scope">
-          <el-popover
-            ref="popover"
-            placement="bottom"
-            :title="'订单:' + scope.row.no"
-            :width="400"
-            trigger="hover"
-          >
-            <template #reference>
-              <div>
-                <div v-for="item in scope.row.items" :key="item">
-                  <el-image
-                    style="width: 36px; height: 36px"
-                    :src="item.picUrl"
-                    :preview-src-list="[item.picUrl]"
-                    fit="cover"
-                    @click="imagePreview(item.picUrl)"
-                  />
-                  <span class="m-2">{{ item.spuName }}</span>
-                </div>
-              </div>
-            </template>
-            <div v-for="item in scope.row.items" :key="item">
-              <div>
-                <p>{{ item.spuName }}</p>
-                <!-- TODO xiaobai: 是不是 (item.payPrice / 100.0).toFixed(2) -->
-                <p>{{
-                  '¥ ' +
-                  parseFloat((item.payPrice / 100) as unknown as string).toFixed(2) +
-                  '元 x ' +
-                  item.count
-                }}</p>
-              </div>
-            </div>
-          </el-popover>
-        </template>
-      </el-table-column>
-      <el-table-column label="实际支付(元)" align="center" prop="payPrice" min-width="100">
-        <template #default="scope">
-          {{ '¥ ' + parseFloat((scope.row.payPrice / 100) as unknown as string).toFixed(2) }}
-        </template>
-      </el-table-column>
-      <el-table-column
-        :formatter="dateFormatter"
-        align="center"
-        label="支付时间"
-        prop="payTime"
-        min-width="180"
-      />
-      <el-table-column label="支付类型" align="center" min-width="100" prop="payChannelCode">
-        <template #default="scope">
-          <dict-tag
-            v-if="scope.row.payChannelCode"
-            :type="DICT_TYPE.PAY_CHANNEL_CODE_TYPE"
-            :value="scope.row.payChannelCode"
-          />
-        </template>
-      </el-table-column>
-      <el-table-column label="订单状态" align="center" prop="status" min-width="100">
-        <template #default="scope">
-          <dict-tag
-            v-if="scope.row.status !== ''"
-            :type="DICT_TYPE.TRADE_ORDER_STATUS"
-            :value="scope.row.status"
-          />
-          <span v-else>{{ scope.status }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" align="center" fixed="right" min-width="150">
-        <template #default="scope">
-          <!-- <el-button v-if="scope.row.status == '0'" link type="primary" @click="sendXX(scope.row)"
-            >待支付</el-button> -->
-          <el-button v-if="scope.row.status == '10'" link type="primary" @click="sendXX(scope.row)"
-            >发货</el-button
-          >
-          <el-button link type="primary" @click="showOrderDetail(scope.row)">详情</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-
-    <!-- 分页 -->
-    <Pagination
-      v-model:limit="queryParams.pageSize"
-      v-model:page="queryParams.pageNo"
-      :total="total"
-      @pagination="getList"
-    />
-  </ContentWrap>
-  <el-image-viewer
-    v-if="imgViewVisible"
-    :url-list="imageViewerList"
-    @close="imgViewVisible = false"
-  />
-</template>
-<script setup lang="ts" name="OrderList">
-import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
-import * as TradeOrderApi from '@/api/mall/trade/order'
-import {
-  TradeOrderPageReqVO,
-  SelectType,
-  TradeOrderPageItemRespVO
-} from '@/api/mall/trade/order/type/orderType'
-import { dateFormatter, formatDate } from '@/utils/formatTime'
-import download from '@/utils/download'
-
-const message = useMessage()
-const { push } = useRouter()
-const imgViewVisible = ref(false) // 商品图预览
-const imageViewerList = ref<string[]>([]) // 商品图预览列表
-const queryFormRef = ref()
-const loading = ref(false)
-const exportLoading = ref(false)
-const total = ref(0) // 总记录数
-const list = ref<Array<TradeOrderPageItemRespVO | any>>([]) //表数据
-
-// 选中状态选中处理
-const orderSelect: SelectType = reactive({
-  queryParams: {} as TradeOrderPageReqVO,
-  selectTotal: 0,
-  selectAllFlag: false,
-  selectData: new Map<number, Set<string>>(),
-  unSelectList: new Set<string>()
-})
-
-//表单搜索
-const queryParams: TradeOrderPageReqVO = reactive({
-  pageNo: 1, //首页
-  pageSize: 10 //页面大小
-})
-
-const queryType = reactive({ k: '', v: '' }) // 订单搜索类型kv
-
-/*
- * 订单搜索
- * 商品名称  商品件数 全部  需要后端支持TODO
- */
-const searchList = ref([
-  { value: 'no', label: '订单号' },
-  { value: 'userId', label: '用户UID' },
-  { value: 'userNickname', label: '用户昵称' },
-  { value: 'userMobile', label: '用户电话' },
-  { value: 'spuName', label: '商品名称TODO' },
-  { value: 'itemCount', label: '商品件数TODO' }
-])
-
-/**
-
- 当前页/? 如果pageNo存在,则将但前数据全部按照单个选中模式取消 ,不存在,则新增全页 增加 Map.pageNo Map.roderNoList
- 单个选中  如果pagelist存在,订单号选中状态取反,并对总数按选中状态加减。如果pagelist不存在,订单号选中状态取反,并对总数按选中状态加减,增加 Map.pageNo,
- 如果当前Map.pageNo 所对应list 为空 ,清除pageNo
- * @param command ===1 当前页 选中 ===2 所有页面选中
- */
-const handleDropType = (command: string) => {
-  let i = 0
-  //当前页按钮
-  if (command === '1') {
-    //如果该页面有选中数据 则选中事件触发时 取消该页面
-    if (orderSelect.selectData && orderSelect.selectData.has(queryParams.pageNo)) {
-      for (i = 0; i < list.value.length; i++) {
-        if (orderSelect.selectData.get(queryParams.pageNo)!.has(list.value[i].id)) {
-          //选中数量减少
-          orderSelect.selectTotal -= 1
-          //考虑全选中,针对某一页面选中当前页时 会将所有数据中去掉该页面, 需要登记到 orderSelect.unSelectList
-          unSelectListRecord(list.value[i].id, 'add')
-        }
-        list.value[i]['itemSelect'] = false
-      }
-      orderSelect.selectData.delete(queryParams.pageNo) //移除该页面
-    } else {
-      //当前页选中状态中 默认全选中
-      orderSelect.selectData.set(queryParams.pageNo, new Set<string>())
-      for (i = 0; i < list.value.length; i++) {
-        list.value[i]['itemSelect'] = true
-        orderSelect.selectData.get(queryParams.pageNo)!.add(list.value[i].id)
-        //选中数量增加
-        orderSelect.selectTotal += 1
-        //对于登记过取消状态中的数据排除
-        unSelectListRecord(list.value[i].id, 'del')
-      }
-    }
-  }
-  //所有页按钮
-  if (command === '2') {
-    orderSelect.selectAllFlag = !orderSelect.selectAllFlag
-
-    if (orderSelect.selectAllFlag) {
-      //打勾勾 //全选
-      orderSelect.selectData?.set(queryParams.pageNo, new Set<string>())
-      for (i = 0; i < list.value.length; i++) {
-        list.value[i]['itemSelect'] = true
-        orderSelect.selectData?.get(queryParams.pageNo)?.add(list.value[i].id) //id是主键不重复
-      }
-      orderSelect.selectTotal = total.value
-    } else {
-      //取消勾勾
-      for (i; i < list.value.length; i++) {
-        list.value[i]['itemSelect'] = false
-      }
-      initSelect() //重置之前选中的类容清空
-    }
-  }
-}
-
-//对全选状态中的 单选或者当前页面单选时登记取消的数据
-const unSelectListRecord = (id: string, op: string) => {
-  if (!orderSelect.selectAllFlag) {
-    return
-  }
-  if (op == 'add') {
-    orderSelect.unSelectList.add(id)
-  } else {
-    orderSelect.unSelectList.delete(id)
-  }
-}
-/***复选框选中 */
-const handcheckclick = (row: any) => {
-  if (row.itemSelect) {
-    orderSelect.selectTotal += 1
-    if (!orderSelect.selectData.has(queryParams.pageNo)) {
-      orderSelect.selectData?.set(queryParams.pageNo, new Set<string>())
-    }
-    orderSelect.selectData?.get(queryParams.pageNo)?.add(row.id)
-    unSelectListRecord(row.id, 'del')
-  } else {
-    orderSelect.selectTotal -= 1
-    orderSelect.selectData.get(queryParams.pageNo)?.delete(row.id)
-    unSelectListRecord(row.id, 'add')
-  }
-}
-/**
- * 导出数据
- */
-
-const handleExport = async () => {
-  try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    //增加查询条件 用于全选时后台查询数据
-    orderSelect.queryParams = queryParams
-
-    // 发起导出
-    exportLoading.value = true
-    //全选时 根据上送的条件查询所有数据,在排除unseleectList 数据,
-    //非全选时, 根据上送的selectData 直接查询数据 后台实现导出数据接口即可
-    console.log(orderSelect)
-    download.excel(orderSelect as any, '订单信息.xls') //?
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
-  //TODO
-  exportLoading.value = false
-}
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  getList()
-}
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value.resetFields()
-  queryType.v = '' //重置
-  queryType.k = ''
-  //休眠0.1s 等待watch响应
-  setTimeout(() => {
-    initSelect() //重置对选中设置恢复初始状态
-    handleQuery()
-  }, 100)
-}
-
-/**选中状态初始化**/
-const initSelect = () => {
-  orderSelect.queryParams = {} as TradeOrderPageReqVO
-  orderSelect.selectTotal = 0
-  orderSelect.selectAllFlag = false
-  orderSelect.selectData?.clear()
-  orderSelect.unSelectList?.clear()
-}
-
-const getList = async () => {
-  loading.value = true
-  try {
-    const data = await TradeOrderApi.getOrderList(queryParams)
-    list.value = data.list
-    total.value = data.total
-    let i = 0
-    if (orderSelect.selectData && orderSelect.selectData.has(queryParams.pageNo)) {
-      //该页面已经加载过了。直接按照之前状态设置选中状态值
-      for (i = 0; i < list.value.length; i++) {
-        if (orderSelect.selectData.get(queryParams.pageNo)!.has(list.value[i].id)) {
-          list.value[i]['itemSelect'] = true //之前已经选取过了
-        } else {
-          list.value[i]['itemSelect'] = false
-        }
-      }
-    } else if (orderSelect.selectAllFlag) {
-      //全选状态中 首次加载页面 默认全部选中
-      orderSelect.selectData.set(queryParams.pageNo, new Set<string>())
-      for (i = 0; i < list.value.length; i++) {
-        list.value[i]['itemSelect'] = true
-        orderSelect.selectData.get(queryParams.pageNo)!.add(list.value[i].id)
-      }
-    } else {
-      //非全选状态中  首次加载默认非选中状态
-      for (i; i < list.value.length; i++) {
-        list.value[i]['itemSelect'] = false //设置状态为未选中状态
-      }
-    }
-  } finally {
-    loading.value = false
-  }
-}
-
-/**
- * 跳转订单详情
- */
-const showOrderDetail = (row: any) => {
-  push({ name: 'TradeOrderDetail', query: { id: row.id } })
-}
-
-/**
- * 跳转用户详情
- */
-const goUserDetail = (row: any) => {
-  console.log('TODO User Detail: ' + row.userId)
-}
-/**
- * 发货
- */
-const sendXX = (row: any) => {
-  console.log('TODO Send XX: ' + row.no)
-}
-
-/**
- * 商品图预览
- * @param imgUrl
- */
-const imagePreview = (imgUrl: string) => {
-  imageViewerList.value = [imgUrl]
-  imgViewVisible.value = true
-}
-
-//针对订单搜索类型和值进行调整 使用监听器
-watch(
-  () => [queryType.k, queryType.v],
-  ([newK, newV], [oldK]) => {
-    //重置oldK对应得value
-    if (oldK != newK) {
-      if (oldK == 'no' && queryParams.no != '') {
-        queryParams.no = ''
-      } else if (oldK == 'userId' && queryParams.userId != '') {
-        queryParams.userId = ''
-      } else if (oldK == 'userNickname' && queryParams.userNickname != '') {
-        queryParams.userNickname = ''
-      } else if (oldK == 'userMobile' && queryParams.userMobile !== '') {
-        queryParams.userMobile = ''
-      } else if (oldK == 'spuName' && queryParams.spuName !== '') {
-        queryParams.spuName = ''
-      } else if (oldK == 'itemCount' && queryParams.itemCount !== '') {
-        queryParams.itemCount = ''
-      } else if (oldK == '' && queryParams.all !== '') {
-        queryParams.all = ''
-      }
-    }
-    // 根据选中得k设置Value
-    if (newK == 'no') {
-      queryParams.no = newV
-    } else if (newK == 'userId') {
-      queryParams.userId = newV
-    } else if (newK == 'userNickname') {
-      queryParams.userNickname = newV
-    } else if (newK == 'userMobile') {
-      queryParams.userMobile = newV
-    } else if (newK == 'spuName') {
-      queryParams.spuName = newV
-    } else if (newK == 'itemCount') {
-      queryParams.itemCount = newV
-    } else if (newK == '') {
-      queryParams.all = newV
-    }
-  }
-)
-
-/** 初始化 **/
-onMounted(() => {
-  initSelect()
-  getList()
-})
-</script>
+<template>
+  <!-- 搜索 -->
+  <ContentWrap>
+    <el-form
+      ref="queryFormRef"
+      :inline="true"
+      :model="queryParams"
+      class="-mb-15px"
+      label-width="68px"
+    >
+      <el-form-item label="订单状态" prop="status">
+        <el-select v-model="queryParams.status" class="!w-280px" clearable placeholder="全部">
+          <el-option
+            v-for="dict in getStrDictOptions(DICT_TYPE.TRADE_ORDER_STATUS)"
+            :key="dict.value as string"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="支付方式" prop="payChannelCode">
+        <el-select
+          v-model="queryParams.payChannelCode"
+          class="!w-280px"
+          clearable
+          placeholder="全部"
+        >
+          <el-option
+            v-for="dict in getStrDictOptions(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)"
+            :key="dict.value as string"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+          v-model="queryParams.createTime"
+          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+          class="!w-280px"
+          end-placeholder="自定义时间"
+          start-placeholder="自定义时间"
+          type="daterange"
+          value-format="YYYY-MM-DD HH:mm:ss"
+        />
+      </el-form-item>
+      <el-form-item label="订单来源" prop="terminal">
+        <el-select v-model="queryParams.terminal" class="!w-280px" clearable placeholder="全部">
+          <el-option
+            v-for="dict in getStrDictOptions(DICT_TYPE.TERMINAL)"
+            :key="dict.value as string"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="订单类型" prop="type">
+        <el-select v-model="queryParams.type" class="!w-280px" clearable placeholder="全部">
+          <el-option
+            v-for="dict in getStrDictOptions(DICT_TYPE.TRADE_ORDER_TYPE)"
+            :key="dict.value as string"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="订单搜索">
+        <el-input
+          v-show="true"
+          v-model="queryType.v"
+          class="!w-280px"
+          clearable
+          placeholder="请输入"
+        >
+          <template #prepend>
+            <el-select v-model="queryType.k" clearable placeholder="全部" style="width: 110px">
+              <el-option
+                v-for="dict in searchList"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+              />
+            </el-select>
+          </template>
+        </el-input>
+      </el-form-item>
+      <el-form-item>
+        <!-- TODO 订单按钮相关权限等订单完善后补齐 -->
+        <el-button @click="handleQuery">
+          <Icon class="mr-5px" icon="ep:search" />
+          搜索
+        </el-button>
+        <el-button @click="resetQuery">
+          <Icon class="mr-5px" icon="ep:refresh" />
+          重置
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table
+      v-loading="loading"
+      :data="list"
+      :show-overflow-tooltip="true"
+      :stripe="true"
+      default-expand-all
+    >
+      <el-table-column fixed="left" type="expand">
+        <template #default="scope">
+          <el-table :data="scope.row.items" :span-method="spanMethod" border style="width: 100%">
+            <el-table-column label="商品" prop="spuName">
+              <template #default="{ row }">
+                {{ row.spuName }}
+                <el-tag v-for="property in row.properties" :key="property.propertyId">
+                  {{ property.propertyName }}: {{ property.valueName }}
+                </el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column label="商品原价(元)" prop="price" width="150">
+              <template #default="{ row }">{{ formatToFraction(row.price) }}</template>
+            </el-table-column>
+            <el-table-column label="数量" prop="count" width="100" />
+            <el-table-column label="合计(元)" prop="payPrice" width="150">
+              <template #default="{ row }">{{ formatToFraction(row.payPrice) }}</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>
+                {{ formatToFraction(scope.row.payPrice) + '元' }}
+              </template>
+            </el-table-column>
+            <el-table-column align="center" label="配送方式" prop="deliveryType" width="120">
+              <template #default> 快递</template>
+            </el-table-column>
+            <el-table-column align="center" fixed="right" label="操作" width="160">
+              <template #default="{ row }">
+                <div class="flex justify-center items-center">
+                  <el-button link type="primary" @click="openForm">
+                    <Icon icon="ep:notification" />
+                    详情
+                  </el-button>
+                  <el-dropdown @command="(command) => handleCommand(command, row)">
+                    <el-button link type="primary">
+                      <Icon icon="ep:d-arrow-right" />
+                      更多
+                    </el-button>
+                    <template #dropdown>
+                      <el-dropdown-menu>
+                        <el-dropdown-item command="orderRemarks">
+                          <Icon icon="ep:chat-line-square" />
+                          订单备注
+                        </el-dropdown-item>
+                        <el-dropdown-item command="refund">
+                          <Icon icon="ep:credit-card" />
+                          立即退款
+                        </el-dropdown-item>
+                        <el-dropdown-item command="printReceipt">
+                          <Icon icon="ep:takeaway-box" />
+                          打印小票
+                        </el-dropdown-item>
+                        <el-dropdown-item command="printInvoice">
+                          <Icon icon="ep:takeaway-box" />
+                          打印配货单
+                        </el-dropdown-item>
+                      </el-dropdown-menu>
+                    </template>
+                  </el-dropdown>
+                </div>
+              </template>
+            </el-table-column>
+          </el-table>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" label="订单号" min-width="110" prop="no" />
+      <el-table-column align="center" label="订单类型" min-width="100">
+        <template #default="{ row }">
+          <dict-tag :type="DICT_TYPE.TRADE_ORDER_TYPE" :value="row.type" />
+        </template>
+      </el-table-column>
+      <el-table-column align="center" label="用户信息" min-width="100">
+        <template #default="{ row }">
+          <el-button link type="primary">
+            {{ row.userId }}{{ '[' + row.user.nickname + ']' }}
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" label="订单来源" min-width="145">
+        <template #default="{ row }">
+          <dict-tag v-if="row.terminal" :type="DICT_TYPE.TERMINAL" :value="row.terminal" />
+          <span v-else>{{ row.terminal }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        :formatter="dateFormatter"
+        align="center"
+        label="支付时间"
+        min-width="180"
+        prop="payTime"
+      />
+      <el-table-column align="center" label="支付类型" min-width="100" prop="payChannelCode">
+        <template #default="{ row }">
+          <dict-tag
+            v-if="row.payChannelCode"
+            :type="DICT_TYPE.PAY_CHANNEL_CODE_TYPE"
+            :value="row.payChannelCode"
+          />
+        </template>
+      </el-table-column>
+      <el-table-column align="center" label="订单状态" min-width="100" prop="status">
+        <template #default="{ row }">
+          <dict-tag
+            v-if="row.status !== ''"
+            :type="DICT_TYPE.TRADE_ORDER_STATUS"
+            :value="row.status"
+          />
+          <span v-else>{{ row.status }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        :formatter="dateFormatter"
+        align="center"
+        label="创建时间"
+        min-width="180"
+        prop="createTime"
+      />
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      v-model:limit="queryParams.pageSize"
+      v-model:page="queryParams.pageNo"
+      :total="total"
+      @pagination="getList"
+    />
+  </ContentWrap>
+  <TradeOrderDetailForm ref="tradeOrderDetailFormRef" />
+</template>
+
+<script lang="ts" name="Order" setup>
+import TradeOrderDetailForm from './detail/index.vue'
+import type { FormInstance, TableColumnCtx } from 'element-plus'
+import { dateFormatter } from '@/utils/formatTime'
+import { OrderItemRespVO, OrderVO } from '@/api/mall/trade/order'
+import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
+import { formatToFraction } from '@/utils'
+import { testData } from './testData'
+import { createImageViewer } from '@/components/ImageViewer'
+
+// const message = useMessage() // 消息弹窗
+// const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const total = ref(2) // 列表的总页数
+const list = ref<OrderVO[]>([]) // 列表的数据
+const tradeOrderDetailFormRef = ref<InstanceType<typeof TradeOrderDetailForm>>()
+const openForm = () => {
+  tradeOrderDetailFormRef.value?.open()
+}
+/** 商品图预览 */
+const imagePreview = (imgUrl: string) => {
+  createImageViewer({
+    urlList: [imgUrl]
+  })
+}
+
+interface SpanMethodProps {
+  row: OrderItemRespVO
+  column: TableColumnCtx<OrderItemRespVO>
+  rowIndex: number
+  columnIndex: number
+}
+
+const spanMethod = ({ rowIndex, columnIndex }: SpanMethodProps) => {
+  const colIndex = [5, 6, 7]
+  // 处理列
+  if (colIndex.includes(columnIndex)) {
+    // 处理被合并的行
+    if (rowIndex !== 0) {
+      return {
+        rowspan: 0,
+        colspan: 0
+      }
+    }
+    return {
+      rowspan: 2,
+      colspan: 1
+    }
+  }
+}
+/** 操作分发 */
+const handleCommand = (command: string, row: OrderVO) => {
+  console.log(row)
+  switch (command) {
+    case 'orderRemarks':
+      break
+    case 'refund':
+      break
+    case 'printReceipt':
+      break
+    case 'printInvoice':
+      break
+    default:
+      break
+  }
+}
+const queryFormRef = ref<FormInstance>() // 搜索的表单
+//表单搜索
+const queryParams = reactive({
+  pageNo: 1, //首页
+  pageSize: 10, //页面大小
+  no: '',
+  userId: '',
+  userNickname: '',
+  userMobile: '',
+  receiverName: '',
+  receiverMobile: '',
+  terminal: '',
+  type: null,
+  status: null,
+  payChannelCode: '',
+  createTime: [],
+  spuName: '',
+  itemCount: '',
+  all: ''
+})
+
+const queryType = reactive({ k: '', v: '' }) // 订单搜索类型kv
+/*
+ * 订单聚合搜索
+ * 商品名称  商品件数 全部  需要后端支持TODO
+ */
+const searchList = ref([
+  { value: 'no', label: '订单号' },
+  { value: 'userId', label: '用户UID' },
+  { value: 'userNickname', label: '用户昵称' },
+  { value: 'userMobile', label: '用户电话' }
+])
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    // const data = await TradeOrderApi.getOrderPage(queryParams)
+    // list.value = data.list
+    // total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value?.resetFields()
+  handleQuery()
+}
+
+/** 初始化 **/
+onMounted(() => {
+  list.value = testData
+  getList()
+})
+</script>

+ 167 - 0
src/views/mall/trade/order/testData.ts

@@ -0,0 +1,167 @@
+import { OrderVO } from '@/api/mall/trade/order'
+
+export const testData: OrderVO = [
+  {
+    id: 2,
+    no: '20230817002',
+    createTime: new Date('2023-08-17T11:30:00'),
+    type: 2,
+    terminal: 10,
+    userId: 1002,
+    userIp: '192.168.1.2',
+    userRemark: 'Urgent delivery required',
+    status: 20,
+    productCount: 2,
+    finishTime: null,
+    cancelTime: null,
+    cancelType: null,
+    remark: '',
+    payOrderId: 10002,
+    payed: false,
+    payTime: null,
+    payChannelCode: 'wx_app',
+    originalPrice: 80,
+    orderPrice: 80,
+    discountPrice: 0,
+    deliveryPrice: 5,
+    adjustPrice: 0,
+    payPrice: 85,
+    deliveryTemplateId: 2002,
+    logisticsId: null,
+    logisticsNo: '',
+    deliveryStatus: 0,
+    deliveryTime: null,
+    receiveTime: null,
+    receiverName: 'Jane Smith',
+    receiverMobile: '987-654-3210',
+    receiverAreaId: 4002,
+    receiverPostCode: 54321,
+    receiverDetailAddress: '456 Elm St, Apt 2C',
+    afterSaleStatus: 0,
+    refundPrice: 0,
+    couponId: null,
+    couponPrice: 0,
+    pointPrice: 0,
+    receiverAreaName: 'Townsville',
+    items: [
+      {
+        id: 103,
+        userId: 1002,
+        orderId: 2,
+        spuId: 5003,
+        spuName: 'Widget C',
+        skuId: 6003,
+        picUrl: 'https://example.com/images/widget_c.jpg',
+        count: 1,
+        originalPrice: 40,
+        originalUnitPrice: 40,
+        discountPrice: 0,
+        payPrice: 40,
+        orderPartPrice: 40,
+        orderDividePrice: 40,
+        afterSaleStatus: 0,
+        properties: [
+          { propertyId: 7001, propertyName: 'Color', valueId: 8004, valueName: 'Green' },
+          { propertyId: 7002, propertyName: 'Size', valueId: 8002, valueName: 'Medium' }
+        ]
+      },
+      {
+        id: 104,
+        userId: 1002,
+        orderId: 2,
+        spuId: 5004,
+        spuName: 'Widget D',
+        skuId: 6004,
+        picUrl: 'https://example.com/images/widget_d.jpg',
+        count: 1,
+        originalPrice: 40,
+        originalUnitPrice: 40,
+        discountPrice: 0,
+        payPrice: 40,
+        orderPartPrice: 40,
+        orderDividePrice: 40,
+        afterSaleStatus: 0,
+        properties: [
+          { propertyId: 7003, propertyName: 'Color', valueId: 8005, valueName: 'Yellow' },
+          { propertyId: 7002, propertyName: 'Size', valueId: 8002, valueName: 'Medium' }
+        ]
+      }
+    ],
+    user: {
+      id: 1002,
+      nickname: 'janesmith',
+      avatar: 'https://example.com/images/avatar.jpg'
+    }
+  },
+  {
+    id: 3,
+    no: '20230817003',
+    createTime: new Date('2023-08-17T12:00:00'),
+    type: 1,
+    terminal: 10,
+    userId: 1003,
+    userIp: '192.168.1.3',
+    userRemark: '',
+    status: 10,
+    productCount: 1,
+    finishTime: new Date('2023-08-18T09:15:00'),
+    cancelTime: null,
+    cancelType: null,
+    remark: '',
+    payOrderId: 10003,
+    payed: true,
+    payTime: new Date('2023-08-17T12:30:00'),
+    payChannelCode: 'alipay_app',
+    originalPrice: 25,
+    orderPrice: 20,
+    discountPrice: 5,
+    deliveryPrice: 5,
+    adjustPrice: 0,
+    payPrice: 20,
+    deliveryTemplateId: 2001,
+    logisticsId: 3002,
+    logisticsNo: 'DEF987654',
+    deliveryStatus: 2,
+    deliveryTime: new Date('2023-08-18T10:30:00'),
+    receiveTime: new Date('2023-08-19T11:30:00'),
+    receiverName: 'Sarah Johnson',
+    receiverMobile: '555-123-4567',
+    receiverAreaId: 4003,
+    receiverPostCode: 67890,
+    receiverDetailAddress: '789 Oak Ave',
+    afterSaleStatus: 0,
+    refundPrice: 0,
+    couponId: 2001,
+    couponPrice: 5,
+    pointPrice: 0,
+    receiverAreaName: 'Villageville',
+    items: [
+      {
+        id: 105,
+        userId: 1003,
+        orderId: 3,
+        spuId: 5005,
+        spuName: 'Widget E',
+        skuId: 6005,
+        picUrl: 'https://example.com/images/widget_e.jpg',
+        count: 1,
+        originalPrice: 20,
+        originalUnitPrice: 20,
+        discountPrice: 5,
+        payPrice: 15,
+        orderPartPrice: 15,
+        orderDividePrice: 15,
+        afterSaleStatus: 0,
+        properties: [
+          { propertyId: 7001, propertyName: 'Color', valueId: 8006, valueName: 'Black' },
+          { propertyId: 7002, propertyName: 'Size', valueId: 8002, valueName: 'Medium' }
+        ]
+      }
+    ],
+    user: {
+      id: 1003,
+      nickname: 'sarahjohnson',
+      avatar: 'https://example.com/images/avatar.jpg'
+    }
+  }
+]

+ 0 - 365
src/views/mall/trade/order/tradeOrderDetail.vue

@@ -1,365 +0,0 @@
-<template>
-  <ContentWrap>
-    <!-- 订单信息 -->
-    <el-descriptions title="订单信息">
-      <el-descriptions-item label="订单号: ">{{ order.no }}</el-descriptions-item>
-      <el-descriptions-item label="配送方式: ">物流配送</el-descriptions-item>
-      <!-- TODO 芋艿:待实现 -->
-      <el-descriptions-item label="营销活动: ">物流配送</el-descriptions-item>
-      <!-- TODO 芋艿:待实现 -->
-      <el-descriptions-item label="订单类型: ">
-        <dict-tag :type="DICT_TYPE.TRADE_ORDER_TYPE" :value="order.type" />
-      </el-descriptions-item>
-      <el-descriptions-item label="收货人: ">{{ order.receiverName }}</el-descriptions-item>
-      <el-descriptions-item label="买家留言: ">{{ order.userRemark }}</el-descriptions-item>
-      <el-descriptions-item label="订单来源: ">
-        <dict-tag :type="DICT_TYPE.TERMINAL" :value="order.terminal" />
-      </el-descriptions-item>
-      <el-descriptions-item label="联系电话: ">{{ order.receiverMobile }}</el-descriptions-item>
-      <el-descriptions-item label="商家备注: ">{{ order.remark }}</el-descriptions-item>
-      <el-descriptions-item label="支付单号: ">{{ order.payOrderId }}</el-descriptions-item>
-      <el-descriptions-item label="付款方式: ">
-        <dict-tag :type="DICT_TYPE.PAY_CHANNEL_CODE_TYPE" :value="order.payChannelCode" />
-      </el-descriptions-item>
-      <!-- <el-descriptions-item label="买家: ">{{ order.user.nickname }}</el-descriptions-item> -->
-      <!-- TODO 芋艿:待实现:跳转会员 -->
-      <el-descriptions-item label="收货地址: ">
-        {{ order.receiverAreaName }} {{ order.receiverDetailAddress }}
-        <el-link
-          v-clipboard:copy="order.receiverAreaName + ' ' + order.receiverDetailAddress"
-          v-clipboard:success="clipboardSuccess"
-          icon="ep:document-copy"
-          type="primary"
-        />
-      </el-descriptions-item>
-    </el-descriptions>
-
-    <!-- 订单状态 -->
-    <el-descriptions title="订单状态" :column="1">
-      <el-descriptions-item label="订单状态: ">
-        <!-- TODO xiaobai:status 一定有值哈,不用判断 -->
-        <dict-tag
-          v-if="order.status !== ''"
-          :type="DICT_TYPE.TRADE_ORDER_STATUS"
-          :value="order.status"
-        />
-      </el-descriptions-item>
-      <el-descriptions-item label-class-name="no-colon">
-        <el-button type="primary" size="small">调整价格</el-button>
-        <!-- TODO 芋艿:待实现 -->
-        <el-button type="primary" size="small">备注</el-button>
-        <!-- TODO 芋艿:待实现 -->
-        <el-button type="primary" size="small">发货</el-button>
-        <!-- TODO 芋艿:待实现 -->
-        <el-button type="primary" size="small">关闭订单</el-button>
-        <!-- TODO 芋艿:待实现 -->
-        <el-button type="primary" size="small">修改地址</el-button>
-        <!-- TODO 芋艿:待实现 -->
-        <el-button type="primary" size="small">打印电子面单</el-button>
-        <!-- TODO 芋艿:待实现 -->
-        <el-button type="primary" size="small">打印发货单</el-button>
-        <!-- TODO 芋艿:待实现 -->
-        <el-button type="primary" size="small">确认收货</el-button>
-        <!-- TODO 芋艿:待实现 -->
-      </el-descriptions-item>
-      <el-descriptions-item>
-        <template #label><span style="color: red">提醒: </span></template>
-        买家付款成功后,货款将直接进入您的商户号(微信、支付宝)<br />
-        请及时关注你发出的包裹状态,确保可以配送至买家手中 <br />
-        如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商
-      </el-descriptions-item>
-    </el-descriptions>
-
-    <!-- 物流信息 TODO -->
-
-    <!-- 商品信息 -->
-    <el-descriptions title="商品信息">
-      <el-descriptions-item labelClassName="no-colon">
-        <el-row :gutter="20">
-          <el-col :span="15">
-            <el-table :data="order.items" border>
-              <el-table-column prop="spuName" label="商品" width="auto">
-                <template #default="{ row }">
-                  {{ row.spuName }}
-                  <el-tag
-                    size="medium"
-                    v-for="property in row.properties"
-                    :key="property.propertyId"
-                  >
-                    {{ property.propertyName }}: {{ property.valueName }}</el-tag
-                  >
-                </template>
-              </el-table-column>
-              <el-table-column prop="price" label="商品原价(元)" width="150">
-                <template #default="{ row }"> ¥{{ (row.price / 100.0).toFixed(2) }} </template>
-              </el-table-column>
-              <el-table-column prop="count" label="数量" width="100" />
-              <el-table-column prop="payPrice" label="合计(元)" width="150">
-                <template #default="{ row }"> ¥{{ (row.payPrice / 100.0).toFixed(2) }} </template>
-              </el-table-column>
-              <el-table-column prop="afterSaleStatus" label="售后状态" width="auto">
-                <template #default="{ row }">
-                  <dict-tag
-                    :type="DICT_TYPE.TRADE_ORDER_ITEM_AFTER_SALE_STATUS"
-                    :value="row.afterSaleStatus"
-                  />
-                </template>
-              </el-table-column>
-            </el-table>
-          </el-col>
-          <el-col :span="10" />
-        </el-row>
-      </el-descriptions-item>
-      <!-- 占位 -->
-      <!-- <el-descriptions-item v-for="item in 5" label-class-name="no-colon" :key="item" /> -->
-    </el-descriptions>
-    <el-descriptions column="6">
-      <el-descriptions-item label="商品总额: ">
-        <!-- TODO xiaobai: 是不是 (item.payPrice / 100.0).toFixed(2) -->
-        ¥{{ parseFloat((order.totalPrice / 100.0) as unknown as string).toFixed(2) }}
-      </el-descriptions-item>
-      <el-descriptions-item label="运费金额: ">
-        ¥{{ parseFloat((order.deliveryPrice / 100.0) as unknown as string).toFixed(2) }}
-      </el-descriptions-item>
-      <el-descriptions-item label="订单调价: ">
-        ¥{{
-          parseFloat((order.adjustPrice / 100.0) as unknown as string).toFixed(2)
-        }}</el-descriptions-item
-      >
-
-      <el-descriptions-item>
-        <template #label><span style="color: red">商品优惠: </span></template>
-        <!-- 没理解TODO  order.totalPrice - order.totalPrice -->
-        ¥{{
-          parseFloat(((order.totalPrice - order.totalPrice) / 100.0) as unknown as string).toFixed(
-            2
-          )
-        }}
-      </el-descriptions-item>
-      <el-descriptions-item>
-        <template #label><span style="color: red">订单优惠: </span></template>
-        ¥{{ parseFloat((order.discountPrice / 100.0) as unknown as string).toFixed(2) }}
-      </el-descriptions-item>
-      <el-descriptions-item>
-        <template #label><span style="color: red">积分抵扣: </span></template>
-        ¥{{ parseFloat((order.pointPrice / 100.0) as unknown as string).toFixed(2) }}
-      </el-descriptions-item>
-
-      <el-descriptions-item v-for="item in 5" label-class-name="no-colon" :key="item" />
-      <!-- 占位 -->
-      <el-descriptions-item label="应付金额: ">
-        ¥{{ (order.payPrice / 100.0).toFixed(2) }}
-      </el-descriptions-item>
-    </el-descriptions>
-
-    <!-- TODO 芋艿:需要改改 -->
-    <div v-for="group in detailGroups" :key="group.title">
-      <el-descriptions v-bind="group.groupProps" :title="group.title">
-        <!-- 订单操作日志 -->
-        <el-descriptions-item v-if="group.key === 'orderLog'" labelClassName="no-colon">
-          <el-timeline>
-            <el-timeline-item
-              v-for="activity in detailInfo[group.key]"
-              :key="activity.timestamp"
-              :timestamp="activity.timestamp"
-            >
-              {{ activity.content }}
-            </el-timeline-item>
-          </el-timeline>
-        </el-descriptions-item>
-
-        <!-- 物流信息 -->
-        <!-- TODO @xiaobai:改成一个包裹哈;目前只允许发货一次 -->
-        <el-descriptions-item v-if="group.key === 'expressInfo'" labelClassName="no-colon">
-          <!-- 循环包裹物流信息 -->
-          <div v-show="(pkgInfo = detailInfo[group.key]) !== null" style="border: 1px dashed">
-            <!-- 包裹详情 -->
-            <el-descriptions class="m-5">
-              <el-descriptions-item
-                v-for="(pkgChild, pkgCIdx) in group.children"
-                v-bind="pkgChild.childProps"
-                :key="`pkgChild_${pkgCIdx}`"
-                :label="pkgChild.label"
-              >
-                <!-- 包裹商品列表 -->
-                <template v-if="pkgChild.valueKey === 'goodsList' && pkgInfo[pkgChild.valueKey]">
-                  <div
-                    v-for="(goodInfo, goodInfoIdx) in pkgInfo[pkgChild.valueKey]"
-                    :key="`goodInfo_${goodInfoIdx}`"
-                    style="display: flex"
-                  >
-                    <el-image
-                      style="width: 100px; height: 100px; flex: none"
-                      :src="goodInfo.imgUrl"
-                    />
-                    <el-descriptions :column="1">
-                      <el-descriptions-item labelClassName="no-colon">{{
-                        goodInfo.name
-                      }}</el-descriptions-item>
-                      <el-descriptions-item label="数量">{{ goodInfo.count }}</el-descriptions-item>
-                    </el-descriptions>
-                  </div>
-                </template>
-
-                <!-- 包裹物流详情 -->
-                <template v-else-if="pkgChild.valueKey === 'wlxq'">
-                  <el-row :gutter="10">
-                    <el-col :span="6" :offset="1">
-                      <el-timeline>
-                        <el-timeline-item
-                          v-for="(activity, index) in pkgInfo[pkgChild.valueKey]"
-                          :key="index"
-                          :timestamp="activity.timestamp"
-                        >
-                          {{ activity.content }}
-                        </el-timeline-item>
-                      </el-timeline>
-                    </el-col>
-                  </el-row>
-                </template>
-                <template v-else>
-                  {{ pkgInfo[pkgChild.valueKey] }}
-                </template>
-              </el-descriptions-item>
-            </el-descriptions>
-          </div>
-        </el-descriptions-item>
-      </el-descriptions>
-    </div>
-  </ContentWrap>
-</template>
-<script lang="ts" name="TradeOrderDetail" setup>
-// TODO @xiaobai:在 order 下创建一个 order/detail,然后改名为 index.vue
-import { DICT_TYPE } from '@/utils/dict'
-import * as TradeOrderApi from '@/api/mall/trade/order'
-const message = useMessage() // 消息弹窗
-
-const { query } = useRoute()
-const queryParams = reactive({
-  id: query.id
-})
-const dialogVisible = ref(false)
-const loading = ref(false)
-const order = ref<any>({
-  items: [],
-  user: {}
-}) // 详情数据
-
-const detailGroups = ref([
-  {
-    title: '物流信息',
-    key: 'expressInfo',
-    children: [
-      { label: '发货时间: ', valueKey: 'fhsj' },
-      { label: '物流公司: ', valueKey: 'wlgs' },
-      { label: '运单号: ', valueKey: 'ydh' },
-      { label: '物流状态: ', valueKey: 'wlzt', childProps: { span: 3 } },
-      { label: '物流详情: ', valueKey: 'wlxq' }
-    ]
-  },
-  {
-    title: '订单操作日志',
-    key: 'orderLog'
-  }
-])
-
-const detailInfo = ref({
-  expressInfo:
-    // 物流信息
-    {
-      label: '包裹1',
-      name: 'bg1',
-      fhsj: '2022-11-03 16:50:45',
-      wlgs: '极兔',
-      ydh: '2132123',
-      wlzt: '不支持此快递公司',
-      wlxq: [
-        {
-          content: '正在派送途中,请您准备签收(派件人:王涛,电话:13854563814)',
-          timestamp: '2018-04-15 15:00:16'
-        },
-        {
-          content: '快件到达 【烟台龙口东江村委营业点】',
-          timestamp: '2018-04-13 14:54:19'
-        },
-        {
-          content: '快件已发车',
-          timestamp: '2018-04-11 12:55:52'
-        },
-        {
-          content: '快件已发车',
-          timestamp: '2018-04-11 12:55:52'
-        },
-        {
-          content: '快件已发车',
-          timestamp: '2018-04-11 12:55:52'
-        }
-      ]
-    },
-  orderLog: [
-    // 订单操作日志
-    {
-      content: '买家【乌鸦】关闭了订单',
-      timestamp: '2018-04-15 15:00:16'
-    },
-    {
-      content: '买家【乌鸦】下单了',
-      timestamp: '2018-04-15 15:00:16'
-    }
-  ],
-  goodsInfo: [] // 商品详情tableData
-})
-// 暂考虑一次性加载详情页面所有数据 TODO
-const getlist = async () => {
-  dialogVisible.value = true
-  loading.value = true
-  try {
-    const res = await TradeOrderApi.getOrderDetail(queryParams.id as unknown as number)
-    order.value = res
-    console.log(order)
-  } catch {
-    message.error('获取详情数据失败')
-  } finally {
-    loading.value = false
-  }
-}
-onMounted(async () => {
-  await getlist()
-})
-const clipboardSuccess = () => {
-  message.success('复制成功')
-}
-</script>
-<style lang="scss" scoped>
-:deep(.el-descriptions) {
-  &:not(:nth-child(1)) {
-    margin-top: 20px;
-  }
-
-  .el-descriptions__title {
-    display: flex;
-    align-items: center;
-
-    &::before {
-      display: inline-block;
-      width: 3px;
-      height: 20px;
-      margin-right: 10px;
-      background-color: #409eff;
-      content: '';
-    }
-  }
-
-  .el-descriptions-item__container {
-    margin: 0 10px;
-
-    .no-colon {
-      margin: 0;
-
-      &::after {
-        content: '';
-      }
-    }
-  }
-}
-</style>