Kaynağa Gözat

订单列表:列表重构 ② and 完善订单详情

puhui999 1 yıl önce
ebeveyn
işleme
345c09ee6c

+ 50 - 50
src/api/mall/trade/order/index.ts

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

+ 33 - 17
src/router/modules/remaining.ts

@@ -5,32 +5,32 @@ const { t } = useI18n()
  * redirect: noredirect        当设置 noredirect 的时候该路由在面包屑导航中不可被点击
  * name:'router-name'          设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
  * meta : {
-    hidden: true              当设置 true 的时候该路由不会再侧边栏出现 如404,login等页面(默认 false)
+ hidden: true              当设置 true 的时候该路由不会再侧边栏出现 如404,login等页面(默认 false)
 
-    alwaysShow: true          当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式,
-                              只有一个时,会将那个子路由当做根路由显示在侧边栏,
-                              若你想不管路由下面的 children 声明的个数都显示你的根路由,
-                              你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,
-                              一直显示根路由(默认 false)
+ alwaysShow: true          当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式,
+ 只有一个时,会将那个子路由当做根路由显示在侧边栏,
+ 若你想不管路由下面的 children 声明的个数都显示你的根路由,
+ 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,
+ 一直显示根路由(默认 false)
 
-    title: 'title'            设置该路由在侧边栏和面包屑中展示的名字
+ title: 'title'            设置该路由在侧边栏和面包屑中展示的名字
 
-    icon: 'svg-name'          设置该路由的图标
+ icon: 'svg-name'          设置该路由的图标
 
-    noCache: true             如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
+ noCache: true             如果设置为true,则不会被 <keep-alive> 缓存(默认 false)
 
-    breadcrumb: false         如果设置为false,则不会在breadcrumb面包屑中显示(默认 true)
+ breadcrumb: false         如果设置为false,则不会在breadcrumb面包屑中显示(默认 true)
 
-    affix: true               如果设置为true,则会一直固定在tag项中(默认 false)
+ affix: true               如果设置为true,则会一直固定在tag项中(默认 false)
 
-    noTagsView: true          如果设置为true,则不会出现在tag中(默认 false)
+ noTagsView: true          如果设置为true,则不会出现在tag中(默认 false)
 
-    activeMenu: '/dashboard'  显示高亮的路由路径
+ activeMenu: '/dashboard'  显示高亮的路由路径
 
-    followAuth: '/dashboard'  跟随哪个路由进行权限过滤
+ followAuth: '/dashboard'  跟随哪个路由进行权限过滤
 
-    canTo: true               设置为true即使hidden为true,也依然可以进行路由跳转(默认 false)
-  }
+ canTo: true               设置为true即使hidden为true,也依然可以进行路由跳转(默认 false)
+ }
  **/
 const remainingRouter: AppRouteRecordRaw[] = [
   {
@@ -349,7 +349,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
   {
     path: '/property',
     component: Layout,
-    name: 'property',
+    name: 'Property',
     meta: {
       hidden: true
     },
@@ -411,6 +411,22 @@ const remainingRouter: AppRouteRecordRaw[] = [
       }
     ]
   },
+  {
+    path: '/trade/order',
+    component: Layout,
+    name: 'Detail',
+    meta: {
+      hidden: true
+    },
+    children: [
+      {
+        path: 'detail/:orderId(\\d+)',
+        component: () => import('@/views/mall/trade/order/detail/index.vue'),
+        name: 'TradeOrderDetailForm',
+        meta: { title: '订单详情', icon: '', activeMenu: '/trade/trade/order' }
+      }
+    ]
+  },
   {
     path: '/pay',
     component: Layout,

+ 1 - 1
src/utils/dict.ts

@@ -130,7 +130,7 @@ export enum DICT_TYPE {
   BPM_OA_LEAVE_TYPE = 'bpm_oa_leave_type',
 
   // ========== PAY 模块 ==========
-  PAY_CHANNEL_CODE = 'pay_channel_code', // 支付渠道编码类型
+  PAY_CHANNEL_CODE_TYPE = 'pay_channel_code_type', // 支付渠道编码类型
   PAY_ORDER_STATUS = 'pay_order_status', // 商户支付订单状态
   PAY_REFUND_STATUS = 'pay_refund_status', // 退款订单状态
   PAY_NOTIFY_STATUS = 'pay_notify_status', // 商户支付回调状态

+ 262 - 240
src/views/mall/trade/order/detail/index.vue

@@ -1,251 +1,271 @@
 <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>
+  <ContentWrap>
+    <!-- 订单信息 -->
+    <el-descriptions title="订单信息">
+      <el-descriptions-item label="订单号: ">{{ orderInfo.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="orderInfo.type" />
+      </el-descriptions-item>
+      <el-descriptions-item label="收货人: ">{{ orderInfo.receiverName }}</el-descriptions-item>
+      <el-descriptions-item label="买家留言: ">{{ orderInfo.userRemark }}</el-descriptions-item>
+      <el-descriptions-item label="订单来源: ">
+        <dict-tag :type="DICT_TYPE.TERMINAL" :value="orderInfo.terminal" />
+      </el-descriptions-item>
+      <el-descriptions-item label="联系电话: ">{{ orderInfo.receiverMobile }}</el-descriptions-item>
+      <el-descriptions-item label="商家备注: ">{{ orderInfo.remark }}</el-descriptions-item>
+      <el-descriptions-item label="支付单号: ">{{ orderInfo.payOrderId }}</el-descriptions-item>
+      <el-descriptions-item label="付款方式: ">
+        <dict-tag :type="DICT_TYPE.PAY_CHANNEL_CODE_TYPE" :value="orderInfo.payChannelCode" />
+      </el-descriptions-item>
+      <!-- <el-descriptions-item label="买家: ">{{ orderInfo.user.nickname }}</el-descriptions-item> -->
+      <!-- TODO 芋艿:待实现:跳转会员 -->
+      <el-descriptions-item label="收货地址: ">
+        {{ orderInfo.receiverAreaName }} {{ orderInfo.receiverDetailAddress }}
+        <el-link
+          v-clipboard:copy="orderInfo.receiverAreaName + ' ' + orderInfo.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="orderInfo.status !== ''"
+          :type="DICT_TYPE.TRADE_ORDER_STATUS"
+          :value="orderInfo.status"
+        />
+      </el-descriptions-item>
+      <el-descriptions-item label-class-name="no-colon">
+        <el-button size="small" type="primary">调整价格</el-button>
         <!-- TODO 芋艿:待实现 -->
-        <el-descriptions-item label="营销活动: ">物流配送</el-descriptions-item>
+        <el-button size="small" type="primary">备注</el-button>
         <!-- 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-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>
 
-      <!-- 订单状态 -->
-      <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 -->
 
-      <!-- 物流信息 TODO -->
+    <!-- 商品信息 -->
+    <el-descriptions title="商品信息">
+      <el-descriptions-item labelClassName="no-colon">
+        <el-row :gutter="20">
+          <el-col :span="15">
+            <el-table :data="orderInfo.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(orderInfo.totalPrice) }}元
+      </el-descriptions-item>
+      <el-descriptions-item label="运费金额: ">
+        {{ formatToFraction(orderInfo.deliveryPrice) }}元
+      </el-descriptions-item>
+      <el-descriptions-item label="订单调价: ">
+        {{ formatToFraction(orderInfo.adjustPrice) }}元
+      </el-descriptions-item>
 
-      <!-- 商品信息 -->
-      <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  orderInfo.totalPrice - orderInfo.totalPrice -->
+        {{ formatToFraction(orderInfo.totalPrice - orderInfo.totalPrice) }}元
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template #label><span style="color: red">订单优惠: </span></template>
+        {{ formatToFraction(orderInfo.discountPrice) }}元
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template #label><span style="color: red">积分抵扣: </span></template>
+        {{ formatToFraction(orderInfo.pointPrice) }}元
+      </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(orderInfo.payPrice) }}元
+      </el-descriptions-item>
+    </el-descriptions>
 
-        <el-descriptions-item v-for="item in 5" :key="item" label-class-name="no-colon" />
-        <!-- 占位 -->
-        <el-descriptions-item label="应付金额: ">
-          {{ formatToFraction(order.payPrice) }}元
+    <!-- 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>
-      </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"
+        <!-- 物流信息 -->
+        <!-- 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"
               >
-                {{ 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-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 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>
 </template>
 <script lang="ts" setup>
+import * as TradeOrderApi from '@/api/mall/trade/order'
 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>({
+const { params } = useRoute() // 查询参数
+// const loading = ref(false)
+const orderInfo = ref<TradeOrderApi.OrderVO>({
+  no: '',
+  createTime: null,
+  type: null,
+  terminal: null,
+  userId: null,
+  userIp: '',
+  userRemark: '',
+  status: null,
+  productCount: null,
+  finishTime: null,
+  cancelTime: null,
+  cancelType: null,
+  remark: '',
+  payOrderId: null,
+  payed: false,
+  payTime: null,
+  payChannelCode: '',
+  originalPrice: null,
+  orderPrice: null,
+  discountPrice: null,
+  deliveryPrice: null,
+  adjustPrice: null,
+  payPrice: null,
+  deliveryTemplateId: null,
+  logisticsId: null,
+  logisticsNo: '',
+  deliveryStatus: null,
+  deliveryTime: null,
+  receiveTime: null,
+  receiverName: '',
+  receiverMobile: '',
+  receiverAreaId: null,
+  receiverPostCode: null,
+  receiverDetailAddress: '',
+  afterSaleStatus: null,
+  refundPrice: null,
+  couponPrice: null,
+  pointPrice: null,
+  receiverAreaName: '',
   items: [],
   user: {}
-}) // 详情数据
+})
 
 const detailGroups = ref([
   {
@@ -311,23 +331,25 @@ const detailInfo = ref({
   ],
   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
-  // }
+
+/** 获得详情 */
+const getDetail = async () => {
+  const id = params.orderId as unknown as number
+  if (id) {
+    const res = (await TradeOrderApi.getOrder(id)) as TradeOrderApi.OrderVO
+    // TODO 测试使用
+    res.user = {
+      id: 247,
+      nickname: '小妮子'
+    }
+    orderInfo.value = res
+  }
 }
+
 onMounted(async () => {
-  await getlist()
+  await getDetail()
 })
+
 const clipboardSuccess = () => {
   message.success('复制成功')
 }

+ 61 - 31
src/views/mall/trade/order/index.vue

@@ -111,20 +111,31 @@
       <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">
+            <el-table-column label="商品信息" min-width="300" prop="spuName">
               <template #default="{ row }">
-                {{ row.spuName }}
-                <el-tag v-for="property in row.properties" :key="property.propertyId">
-                  {{ property.propertyName }}: {{ property.valueName }}
-                </el-tag>
+                <div class="flex items-center">
+                  <el-image
+                    :src="row.picUrl"
+                    class="w-30px h-30px mr-10px"
+                    @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 }">{{ formatToFraction(row.price) }}</template>
+            <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 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 }">
@@ -134,22 +145,33 @@
                 />
               </template>
             </el-table-column>
-            <el-table-column align="center" label="实际支付(元)" min-width="120" prop="payPrice">
+            <el-table-column align="center" label="实际支付" min-width="120" prop="payPrice">
               <template #default>
                 {{ formatToFraction(scope.row.payPrice) + '元' }}
               </template>
             </el-table-column>
+            <el-table-column label="买家/收货人" min-width="120">
+              <template #default>
+                <div 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>
+              </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 }">
+              <template #default>
                 <div class="flex justify-center items-center">
-                  <el-button link type="primary" @click="openForm">
+                  <el-button link type="primary" @click="openForm(scope.row.id)">
                     <Icon icon="ep:notification" />
                     详情
                   </el-button>
-                  <el-dropdown @command="(command) => handleCommand(command, row)">
+                  <el-dropdown @command="(command) => handleCommand(command, scope.row)">
                     <el-button link type="primary">
                       <Icon icon="ep:d-arrow-right" />
                       更多
@@ -187,13 +209,6 @@
           <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" />
@@ -242,28 +257,26 @@
       @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 * as TradeOrderApi from '@/api/mall/trade/order'
 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 { currentRoute, push } = useRouter() // 路由跳转
 
 const loading = ref(true) // 列表的加载中
 const total = ref(2) // 列表的总页数
 const list = ref<OrderVO[]>([]) // 列表的数据
-const tradeOrderDetailFormRef = ref<InstanceType<typeof TradeOrderDetailForm>>()
-const openForm = () => {
-  tradeOrderDetailFormRef.value?.open()
+const openForm = (id) => {
+  push('/trade/order/detail/' + id)
 }
 /** 商品图预览 */
 const imagePreview = (imgUrl: string) => {
@@ -280,7 +293,7 @@ interface SpanMethodProps {
 }
 
 const spanMethod = ({ rowIndex, columnIndex }: SpanMethodProps) => {
-  const colIndex = [5, 6, 7]
+  const colIndex = [5, 6, 7, 8]
   // 处理列
   if (colIndex.includes(columnIndex)) {
     // 处理被合并的行
@@ -348,9 +361,18 @@ const searchList = ref([
 const getList = async () => {
   loading.value = true
   try {
-    // const data = await TradeOrderApi.getOrderPage(queryParams)
-    // list.value = data.list
-    // total.value = data.total
+    const data = await TradeOrderApi.getOrderPage(queryParams)
+    const list_ = data.list as OrderVO[]
+    // TODO 测试使用
+    list_.forEach((item) => {
+      item.user = {
+        id: 247,
+        nickname: '小妮子'
+      }
+    })
+
+    list.value = list_
+    total.value = data.total
   } finally {
     loading.value = false
   }
@@ -368,9 +390,17 @@ const resetQuery = () => {
   handleQuery()
 }
 
+// 监听路由变化更新列表,解决商品保存后,列表不刷新的问题。
+watch(
+  () => currentRoute.value,
+  () => {
+    getList()
+  }
+)
+
 /** 初始化 **/
 onMounted(() => {
-  list.value = testData
+  // list.value = testData
   getList()
 })
 </script>

+ 25 - 23
src/views/mall/trade/order/testData.ts

@@ -18,7 +18,7 @@ export const testData: OrderVO = [
     remark: '',
     payOrderId: 10002,
     payed: false,
-    payTime: null,
+    payTime: new Date('2023-08-17T12:30:00'),
     payChannelCode: 'wx_app',
     originalPrice: 80,
     orderPrice: 80,
@@ -32,26 +32,27 @@ export const testData: OrderVO = [
     deliveryStatus: 0,
     deliveryTime: null,
     receiveTime: null,
-    receiverName: 'Jane Smith',
-    receiverMobile: '987-654-3210',
+    receiverName: '李四',
+    receiverMobile: '19855568989',
     receiverAreaId: 4002,
     receiverPostCode: 54321,
-    receiverDetailAddress: '456 Elm St, Apt 2C',
+    receiverDetailAddress: '翻斗花园',
     afterSaleStatus: 0,
     refundPrice: 0,
     couponId: null,
     couponPrice: 0,
     pointPrice: 0,
-    receiverAreaName: 'Townsville',
+    receiverAreaName: '北京市朝阳区',
     items: [
       {
         id: 103,
         userId: 1002,
         orderId: 2,
         spuId: 5003,
-        spuName: 'Widget C',
+        spuName: '毛绒鸭子',
         skuId: 6003,
-        picUrl: 'https://example.com/images/widget_c.jpg',
+        picUrl:
+          'http://127.0.0.1:48080/admin-api/infra/file/5/get/20220723041544165856414464011_BIG.jpg',
         count: 1,
         originalPrice: 40,
         originalUnitPrice: 40,
@@ -61,8 +62,8 @@ export const testData: OrderVO = [
         orderDividePrice: 40,
         afterSaleStatus: 0,
         properties: [
-          { propertyId: 7001, propertyName: 'Color', valueId: 8004, valueName: 'Green' },
-          { propertyId: 7002, propertyName: 'Size', valueId: 8002, valueName: 'Medium' }
+          { propertyId: 7001, propertyName: '颜色', valueId: 8004, valueName: '黄色' },
+          { propertyId: 7002, propertyName: '尺寸', valueId: 8002, valueName: '小鸭子' }
         ]
       },
       {
@@ -70,9 +71,10 @@ export const testData: OrderVO = [
         userId: 1002,
         orderId: 2,
         spuId: 5004,
-        spuName: 'Widget D',
+        spuName: '毛绒鸭子',
         skuId: 6004,
-        picUrl: 'https://example.com/images/widget_d.jpg',
+        picUrl:
+          'http://127.0.0.1:48080/admin-api/infra/file/5/get/20220723041544165856414464011_BIG.jpg',
         count: 1,
         originalPrice: 40,
         originalUnitPrice: 40,
@@ -82,14 +84,14 @@ export const testData: OrderVO = [
         orderDividePrice: 40,
         afterSaleStatus: 0,
         properties: [
-          { propertyId: 7003, propertyName: 'Color', valueId: 8005, valueName: 'Yellow' },
-          { propertyId: 7002, propertyName: 'Size', valueId: 8002, valueName: 'Medium' }
+          { propertyId: 7001, propertyName: '颜色', valueId: 8004, valueName: '黄色' },
+          { propertyId: 7002, propertyName: '尺寸', valueId: 8002, valueName: '大鸭子' }
         ]
       }
     ],
     user: {
       id: 1002,
-      nickname: 'janesmith',
+      nickname: '小妮子',
       avatar: 'https://example.com/images/avatar.jpg'
     }
   },
@@ -124,26 +126,26 @@ export const testData: OrderVO = [
     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',
+    receiverName: '张三',
+    receiverMobile: '13988886656',
     receiverAreaId: 4003,
     receiverPostCode: 67890,
-    receiverDetailAddress: '789 Oak Ave',
+    receiverDetailAddress: '成华大道',
     afterSaleStatus: 0,
     refundPrice: 0,
     couponId: 2001,
     couponPrice: 5,
     pointPrice: 0,
-    receiverAreaName: 'Villageville',
+    receiverAreaName: '四川省成都市',
     items: [
       {
         id: 105,
         userId: 1003,
         orderId: 3,
         spuId: 5005,
-        spuName: 'Widget E',
+        spuName: '华为',
         skuId: 6005,
-        picUrl: 'https://example.com/images/widget_e.jpg',
+        picUrl: 'http://127.0.0.1:48080/admin-api/infra/file/5/get/sj.jpg',
         count: 1,
         originalPrice: 20,
         originalUnitPrice: 20,
@@ -153,14 +155,14 @@ export const testData: OrderVO = [
         orderDividePrice: 15,
         afterSaleStatus: 0,
         properties: [
-          { propertyId: 7001, propertyName: 'Color', valueId: 8006, valueName: 'Black' },
-          { propertyId: 7002, propertyName: 'Size', valueId: 8002, valueName: 'Medium' }
+          { propertyId: 7001, propertyName: '颜色', valueId: 8006, valueName: '紫色' },
+          { propertyId: 7002, propertyName: '选配', valueId: 8002, valueName: '标配' }
         ]
       }
     ],
     user: {
       id: 1003,
-      nickname: 'sarahjohnson',
+      nickname: '无敌最俊朗',
       avatar: 'https://example.com/images/avatar.jpg'
     }
   }