Browse Source

商城订单放到 个人中心-交易订单

Xiao_123 4 months ago
parent
commit
72b07c3274

+ 14 - 0
src/router/modules/recruit.js

@@ -150,6 +150,20 @@ const recruit = [
       },
       },
     ]
     ]
   },
   },
+  {
+    path: '/mall/order/detail/:id',
+    component: Layout,
+    children: [
+      {
+        path: '/mall/order/detail/:id',
+        component: () => import('@/views/recruit/personal/PersonalCenter/tradeOrder/components/detail.vue'),
+        name: 'mallOrderDetail',
+        meta: {
+          title: '商城订单详情'
+        }
+      }
+    ]
+  },
   {
   {
     path: '/pointsExchange',
     path: '/pointsExchange',
     component: Layout,
     component: Layout,

+ 1 - 0
src/utils/date.js

@@ -89,6 +89,7 @@ export const  convertTimestampsToDayRange = (timestamps) => {
  * @description format 季度 + 星期 + 几周:"YYYY-mm-dd HH:MM:SS WWW QQQQ ZZZ"
  * @description format 季度 + 星期 + 几周:"YYYY-mm-dd HH:MM:SS WWW QQQQ ZZZ"
  * @returns {string} 返回拼接后的时间字符串
  * @returns {string} 返回拼接后的时间字符串
  */
  */
+import dayjs from 'dayjs';
 export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
 export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
   // 日期不存在,则返回空
   // 日期不存在,则返回空
   if (!date) {
   if (!date) {

+ 0 - 1
src/views/mall/user/order/index.vue

@@ -102,7 +102,6 @@ const handleChangePage = (e) => {
 
 
 // 查看详情
 // 查看详情
 const handleDetail = ({ id }) => {
 const handleDetail = ({ id }) => {
-  // router.push(`/mall/user/order/detail/${id}`)
   window.open(`/mall/user/order/detail/${id}`)
   window.open(`/mall/user/order/detail/${id}`)
 }
 }
 
 

+ 52 - 0
src/views/recruit/personal/PersonalCenter/tradeOrder/components/commentForm.vue

@@ -0,0 +1,52 @@
+<template>
+  <div v-for="(val, index) in orderList" :key="val.id">
+    <GoodsItem :item="val" :showHover="false" :showLine="false" />
+    <div class="d-flex align-center my-3">
+      <span>商品质量</span>
+      <v-rating :length="5" :size="34" v-model="commentList[index].descriptionScores" color="warning" active-color="warning" />
+    </div>
+    <div class="d-flex align-center my-3">
+      <span>服务态度</span>
+      <v-rating :length="5" :size="34" v-model="commentList[index].benefitScores" color="warning" active-color="warning" />
+    </div>
+    <v-textarea v-model="commentList[index].content" rows="3" color="primary" clearable counter label="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~" />
+    <Imgs v-model="commentList[index].picUrls" limit="9"></Imgs>
+    <v-checkbox v-model="commentList[index].anonymous" color="primary" hide-details label="匿名评论"></v-checkbox>
+    <v-divider v-if="index !== orderList.length - 1" color="error" class="my-3"></v-divider>
+  </div>
+</template>
+
+<script setup>
+defineOptions({ name: 'mall-user-order-commentForm' })
+import { ref, onMounted } from 'vue'
+import { getMallOrderDetail } from '@/api/mall/user'
+import Snackbar from '@/plugins/snackbar'
+import GoodsItem from '../../components/GoodsItem/index.vue'
+
+const props = defineProps({ orderId: [String, Number] })
+
+const commentList = ref([])
+const orderList = ref([])
+
+onMounted(async () => {
+  if (!props.orderId) return Snackbar.warning('请重新选择订单')
+  const data = await getMallOrderDetail(props.orderId)
+  orderList.value = data.items
+  commentList.value = data.items.map(e => {
+    return {
+      orderItemId: e.id,
+      anonymous: false,
+      benefitScores: 5,
+      descriptionScores: 5,
+      picUrls: [],
+      content: ''
+    }
+  })
+})
+
+defineExpose({ commentList })
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 100 - 0
src/views/recruit/personal/PersonalCenter/tradeOrder/components/detail.vue

@@ -0,0 +1,100 @@
+<template>
+  <div class="mt-16">
+    <div class="default-width pb-5">
+      <v-banner color="primary" :text="formatOrderStatusDescription(order)" style="background-color: #00897B; color: #fff;"></v-banner>
+
+      <v-row no-gutters class="mt-3">
+        <v-col span="6">
+          <!-- 订单信息 -->
+          <v-card class="pa-5">
+            <h3>订单信息</h3>
+            <v-divider class="my-3"></v-divider>
+            <div class="font-size-15 color-666">
+              <p>订单编号:{{ order.no }}</p>
+              <p class="my-3">下单时间:{{ timesTampChange(order.createTime) }}</p>
+              <p>支付时间:{{ timesTampChange(order.payTime) }}</p>
+              <p class="mt-3">支付方式:{{ order.payChannelName }}</p>
+              <p class="mt-3">订单备注:{{ order.userRemark }}</p>
+            </div>
+          </v-card>
+        </v-col>
+        <v-col span="6" class="ml-3">
+          <!-- 物流信息 -->
+          <v-card class="pa-5" style="height: 100%">
+            <h3>物流信息</h3>
+            <v-divider class="my-3"></v-divider>
+            <div class="font-size-15 color-666">
+              <p>收货地址:{{ order.receiverName }},{{ order.receiverMobile }},{{ order.receiverAreaName }} {{ order.receiverDetailAddress }}</p>
+              <p class="my-3">物流公司:{{ order.logisticsName }}</p>
+              <p>运单号:{{ order.logisticsNo }}</p>
+            </div>
+          </v-card>
+        </v-col>
+      </v-row>
+
+      <!-- 商品列表 -->
+      <v-card class="my-3 pa-5">
+        <h3 class="mb-3">商品列表</h3>
+        <v-divider></v-divider>
+
+        <CtTable
+          class="mt-3"
+          :items="order.items"
+          :headers="headers"
+          :loading="false"
+          :elevation="0"
+          :isTools="false"
+          :showPage="false"
+          itemKey="id"
+        >
+          <template #picUrl="{ item }">
+            <v-img :src="item.picUrl" width="90" height="90"></v-img>
+          </template>
+          <template #spuName="{ item }">
+            <span class="color-primary cursor-pointer" @click="handleToGoodsDetail(item)">{{ item.spuName }}</span>
+          </template>
+        </CtTable>
+        <div class="text-end color-primary mr-3 mt-5 font-size-20">
+          共{{ order.productCount }}件商品,合计:¥{{ fen2yuan(order.payPrice) }}
+        </div>
+      </v-card>
+    </div>
+  </div>
+</template>
+
+<script setup>
+defineOptions({ name: 'mall-user-order-detail'})
+import { ref, onMounted } from 'vue'
+import { useRouter } from 'vue-router'
+import { getMallOrderDetail } from '@/api/mall/user'
+import Snackbar from '@/plugins/snackbar'
+import { timesTampChange } from '@/utils/date'
+import { fen2yuan, formatOrderStatusDescription } from '@/hooks/web/useGoods'
+
+const router = useRouter()
+const { id } = router.currentRoute.value.params
+const order = ref({})
+
+const headers = [
+  { title: '', key: 'picUrl', sortable: false },
+  { title: '商品名称', key: 'spuName', sortable: false },
+  { title: '规格', key: 'contactAddress', sortable: false, value: item => item.properties.map((property) => property.valueName).join(' ') },
+  { title: '单价', key: 'price', sortable: false, value: item => '¥' + fen2yuan(item.price) },
+  { title: '数量', key: 'count', sortable: false }
+]
+
+onMounted(async () =>{
+  if (!id) return Snackbar.error('订单不存在')
+  const data = await getMallOrderDetail(id)
+  order.value = data
+})
+
+// 跳转商品详情
+const handleToGoodsDetail = (item) => {
+  window.open(`/mall/goodsDetail/${item.spuId}`)
+}
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 200 - 0
src/views/recruit/personal/PersonalCenter/tradeOrder/dynamic/mallOrder.vue

@@ -0,0 +1,200 @@
+<template>
+  <div class="mt-3">
+    <v-tabs v-model="tab" align-tabs="start" color="primary" :bg-color="props.tabListBg ? '#f7f8fa': '#fff'" @update:modelValue="queryParams.pageNo = 1, getOrderPage()">
+      <v-tab v-for="(val, i) in tabList" :key="i" :value="val.value">{{ val.title }}</v-tab>
+    </v-tabs>
+    <div v-if="orderList.length" class="mt-3">
+      <div v-for="val in orderList" :key="val.id" class="order-item mb-3">
+        <div class="order-item-header px-5">
+          <div style="width: 40%;">
+            <span>订单号:{{ val.no }}</span>
+            <span class="ml-5">{{ timesTampChange(val.createTime) }}</span>
+          </div>
+          <div class="text-end color-warning" :class="formatOrderColor(val)" style="flex: 1">
+            {{ formatOrderStatus(val) }}
+          </div>
+        </div>
+        <!-- 商品列表 -->
+        <GoodsItem v-for="k in val.items" :key="k.id" :item="k" />
+        <!-- 操作按钮 -->
+        <div class="text-end pa-3 font-size-13 color-666">
+          <div>共{{ val.productCount }}件商品,合计:¥{{ fen2yuan(val.payPrice) }}</div>
+          <v-btn class="mt-2" variant="tonal" rounded="xl" @click.stop="handleDetail(val)">查看详情</v-btn>
+          <v-btn v-if="val.buttons.includes('confirm')" class="mt-2 ml-3" variant="tonal" color="success" rounded="xl" @click.stop="handleConfirm(val)">确认收货</v-btn>
+          <!-- <v-btn v-if="val.buttons.includes('comment')" class="mt-2" variant="tonal" rounded="xl" @click.stop="handleComment(val)">评价</v-btn> -->
+          <!-- <v-btn v-if="val.buttons.includes('express')" class="mt-2" variant="tonal" rounded="xl">查看物流</v-btn> -->
+          <v-btn v-if="val.buttons.includes('cancel')" class="mt-2 ml-3" variant="tonal" rounded="xl" @click.stop="handleCancel(val)">取消订单</v-btn>
+          <v-btn v-if="val.buttons.includes('delete')" class="mt-2 ml-3" variant="tonal" color="error" rounded="xl" @click.stop="handleDelete(val)">删除订单</v-btn>
+          <v-btn v-if="val.buttons.includes('pay')" class="mt-2 ml-3" variant="tonal" color="primary" rounded="xl" @click.stop="handlePay(val)">继续支付</v-btn>
+        </div>
+      </div>
+      <CtPagination :total="total" :page="queryParams.pageNo" :limit="queryParams.pageSize" @handleChange="handleChangePage"></CtPagination>
+    </div>
+    <Empty v-else :elevation="false" :message="tab === -1 ? '暂无订单' : '暂无' + tabList.find(e => e.value === tab).title + '订单'"></Empty>
+  </div>
+
+  <!-- <CtDialog :visible="showDialog" titleClass="text-h6" :footer="true" :widthType="3" title="商品评论" @submit="handleSubmit" @close="handleClose">
+    <CommentForm ref="commentFormRef" v-if="showDialog" :orderId="commentOrderId" />
+  </CtDialog> -->
+  <!-- 支付 -->
+  <CtDialog :visible="showPay" titleClass="text-h6" :widthType="3" title="收银台" :footer="false" @close="payCancel">
+    <pay ref="payRef" :id="payOrderId" @paySuccess="paySuccess"></pay>
+  </CtDialog>
+</template>
+
+<script setup>
+defineOptions({ name: 'mall-user-order-index'})
+import { ref } from 'vue'
+import { getMallOrderPage, receiveOrder, deleteTradeOrder, cancelTradeOrder, createOrderItemComment } from '@/api/mall/user'
+import { timesTampChange } from '@/utils/date'
+import { fen2yuan, handleOrderButtons, formatOrderStatus, formatOrderColor } from '@/hooks/web/useGoods'
+import Confirm from '@/plugins/confirm'
+import Snackbar from '@/plugins/snackbar'
+import GoodsItem from '@/views/mall/components/GoodsItem/index.vue'
+// import CommentForm from '../components/CommentForm.vue'
+import pay from '@/views/mall/components/details/order/pay.vue'
+import { useRoute } from 'vue-router'; const route = useRoute()
+import { useRouter } from 'vue-router'; const router = useRouter()
+
+const props = defineProps({
+  tabListBg: {
+    type: Boolean,
+    default: true
+  },
+})
+
+const tab = ref(route?.query?.tab ? (route.query.tab)-0 : -1)
+const tabList = [
+  { title: '全部', value: -1 },
+  { title: '待付款', value: 0 },
+  { title: '待发货', value: 10 },
+  { title: '待收货', value: 20 },
+  { title: '已完成', value: 30 },
+  { title: '已取消', value: 40 },
+  // { title: '待评价', value: 30 }
+]
+const total = ref(0)
+const queryParams = ref({
+  pageNo: 1,
+  pageSize: 10
+})
+
+// 获取订单列表
+const orderList = ref([])
+const getOrderPage = async () => {
+  queryParams.value.status = tab.value
+  if (tab.value === -1) delete queryParams.value.status
+  if (tab.value === 30) queryParams.value.commentStatus = false
+
+  const result = await getMallOrderPage(queryParams.value)
+
+  result.list.forEach(order => handleOrderButtons(order))
+  orderList.value = result.list
+  total.value = result.total
+}
+getOrderPage()
+
+// 分页
+const handleChangePage = (e) => {
+  queryParams.value.pageNo = e
+  getOrderPage()
+}
+
+// 查看详情
+const handleDetail = ({ id }) => {
+  window.open(`/mall/order/detail/${id}`)
+}
+
+// 删除订单
+const handleDelete = async ({ id }) => {
+  Confirm('系统提示', '是否确认删除该订单?').then(async () => {
+    await deleteTradeOrder(id)
+    Snackbar.success('删除成功')
+    await getOrderPage()
+  })
+}
+
+// 取消订单
+const handleCancel = async ({ id }) => {
+  Confirm('系统提示', '是否确认取消该订单?').then(async () => {
+    await cancelTradeOrder(id)
+    Snackbar.success('取消成功')
+    await getOrderPage()
+  })
+}
+
+// 商品评论
+// const showDialog = ref(false)
+// const commentOrderId = ref(null) // 订单id
+// const commentFormRef = ref()
+// const handleComment = (val) => {
+//   commentOrderId.value = val.id
+//   showDialog.value = true
+// }
+// const handleClose = () => {
+//   commentOrderId.value = null
+//   showDialog.value = false
+// }
+// const handleSubmit = async () => {
+//   const commentList = commentFormRef.value.commentList
+//   for (const comment of commentList) {
+//     await createOrderItemComment(comment)
+//   }
+//   Snackbar.success('评论成功')
+//   handleClose()
+//   getOrderPage()
+// }
+
+// // 收货成功后提示去评论
+// const handlePromptComment = (id) => {
+//   Confirm('确认收货成功', '是否前往评价?', { sureText: '立即评价', cancelText: '关闭' }).then(() => {
+//     handleComment({ id })
+//   })
+// }
+
+// 确认收货
+const handleConfirm = ({ id }) => {
+  if (!id) return
+  Confirm('系统提示', '是否确认收货?').then(async () => {
+    await receiveOrder(id)
+    Snackbar.success('收货成功')
+    queryParams.value.pageNo = 1
+    await getOrderPage()
+    handlePromptComment(id) // 收货成功后提示去评论
+  })
+}
+
+const showPay = ref(false)
+const payOrderId  = ref('')
+const handlePay = (val) => {
+  if (!payOrderId) return Snackbar.success('订单错误!')
+  payOrderId.value = val.payOrderId
+  showPay.value = true
+}
+// 
+const payCancel = () => {
+  Snackbar.warning('您已取消支付!')
+  showPay.value = false
+}
+const paySuccess = (e) => {
+  // Snackbar.success('支付成功!')
+  // showPay.value = false
+  // getOrderPage()
+  router.push({ path: '/mall/payOver', query: { price: e.price }})
+}
+
+</script>
+
+<style scoped lang="scss">
+.order-item {
+  border: 1px solid #dbdbdb;
+  &-header {
+    display: flex;
+    background-color: #f2f4f7;
+    height: 36px;
+    line-height: 36px;
+    font-size: 13px;
+    color: #666;
+  }
+}
+</style>

+ 68 - 0
src/views/recruit/personal/PersonalCenter/tradeOrder/dynamic/rechargeVip.vue

@@ -0,0 +1,68 @@
+<template>
+  <CtTable
+    class="mt-3"
+    :items="dataList"
+    :headers="headers"
+    :loading="false"
+    :elevation="0"
+    :isTools="false"
+    :showPage="true"
+    :total="total"
+    :page-info="query"
+    itemKey="id"
+    @pageHandleChange="handleChangePage"
+  >
+  </CtTable>
+</template>
+
+<script setup>
+defineOptions({name: 'tradingOrder'})
+import { getUserTradeOrder } from '@/api/recruit/personal/personalCenter'
+import { ref } from 'vue'
+import { timesTampChange } from '@/utils/date'
+import { getDict } from '@/hooks/web/useDictionaries'
+
+const total = ref(0)
+const query = ref({
+  pageNo: 1,
+  pageSize: 10
+})
+const dataList = ref([])
+
+// 支付渠道
+const channelData = ref([])
+const getPayChannelCode = async () => {
+  const { data } = await getDict('pay_channel_code')
+  channelData.value = data
+}
+getPayChannelCode()
+
+
+const headers = [
+  { title: '商品名称', key: 'spuName', sortable: false },
+  { title: '价格', key: 'price', sortable: false, value: item => item.price / 100 + '元' },
+  { title: '是否已支付', key: 'payStatus', sortable: false, value: item => item.payStatus ? '已支付' : '未支付' },
+  { title: '支付订单编号', key: 'payOrderId', sortable: false },
+  { title: '支付渠道', key: 'payChannelCode', value: item => channelData.value.find(e => e.value === item.payChannelCode)?.label, sortable: false },
+  { title: '订单支付时间', key: 'payTime', value: item =>  timesTampChange(item.payTime), sortable: false },
+  { title: '退款订单编号', key: 'payReFundId', sortable: false },
+  { title: '退款金额', key: 'refundPrice', sortable: false, value: item => item.refundPrice && item.refundPrice > 0 ? item.refundPrice / 100 + '元' : '' },
+  { title: '退款时间', key: 'refundTime', value: item =>  timesTampChange(item.refundTime), sortable: false },
+  { title: '更新时间', key: 'updateTime', value: item =>  timesTampChange(item.updateTime), sortable: false },
+]
+
+const getData = async () => {
+  const res = await getUserTradeOrder(query.value)
+  dataList.value = res.list
+  total.value = res.total
+}
+getData()
+
+const handleChangePage = (e) => {
+  query.value.pageNo = e
+  getData()
+}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 15 - 69
src/views/recruit/personal/PersonalCenter/tradeOrder/index.vue

@@ -1,83 +1,29 @@
 <!--  -->
 <!--  -->
 <template>
 <template>
-  <div class="white-bgc pa-3 ma-3">
-    <!-- <v-tabs v-model="tab" align-tabs="start" color="primary" bg-color="#f7f8fa" @update:model-value="handleChangeTab">
-      <v-tab :value="0">充值</v-tab>
-    </v-tabs> -->
-    <CtTable
-      class="mt-3"
-      :items="dataList"
-      :headers="headers"
-      :loading="false"
-      :elevation="0"
-      :isTools="false"
-      :showPage="true"
-      :total="total"
-      :page-info="query"
-      itemKey="id"
-      @pageHandleChange="handleChangePage"
-    >
-    </CtTable>
+  <div class="white-bgc pa-3">
+    <v-tabs v-model="tab" align-tabs="start" color="primary" bg-color="#f7f8fa" @update:model-value="handleChangeTab">
+      <v-tab v-for="k in items" :key="k.value" :value="k.value">{{ k.label }}</v-tab>
+    </v-tabs>
+    <component :is="items[tab].path" />
   </div>
   </div>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
 defineOptions({name: 'tradingOrder'})
 defineOptions({name: 'tradingOrder'})
-import { getUserTradeOrder } from '@/api/recruit/personal/personalCenter'
-import { ref } from 'vue'
-import { timesTampChange } from '@/utils/date'
-import { getDict } from '@/hooks/web/useDictionaries'
+import { ref, shallowRef } from 'vue'
+import RechargeVipOrder from './dynamic/rechargeVip.vue'
+import MallOrder from './dynamic/mallOrder.vue'
 
 
-// const tab = ref(0)
-const total = ref(0)
-const query = ref({
-  pageNo: 1,
-  pageSize: 10
-})
-const dataList = ref([])
-
-// 支付渠道
-const channelData = ref([])
-const getPayChannelCode = async () => {
-  const { data } = await getDict('pay_channel_code')
-  channelData.value = data
-}
-getPayChannelCode()
-
-
-const headers = [
-  { title: '商品名称', key: 'spuName', sortable: false },
-  { title: '价格', key: 'price', sortable: false, value: item => item.price / 100 + '元' },
-  { title: '是否已支付', key: 'payStatus', sortable: false, value: item => item.payStatus ? '已支付' : '未支付' },
-  { title: '支付订单编号', key: 'payOrderId', sortable: false },
-  { title: '支付渠道', key: 'payChannelCode', value: item => channelData.value.find(e => e.value === item.payChannelCode)?.label, sortable: false },
-  { title: '订单支付时间', key: 'payTime', value: item =>  timesTampChange(item.payTime), sortable: false },
-  { title: '退款订单编号', key: 'payReFundId', sortable: false },
-  { title: '退款金额', key: 'refundPrice', sortable: false, value: item => item.refundPrice && item.refundPrice > 0 ? item.refundPrice / 100 + '元' : '' },
-  { title: '退款时间', key: 'refundTime', value: item =>  timesTampChange(item.refundTime), sortable: false },
-  { title: '更新时间', key: 'updateTime', value: item =>  timesTampChange(item.updateTime), sortable: false },
-]
-
-const getData = async () => {
-  const res = await getUserTradeOrder(query.value)
-  dataList.value = res.list
-  total.value = res.total
-}
-getData()
-
-const handleChangePage = (e) => {
-  query.value.pageNo = e
-  getData()
-}
+const tab = ref(0)
+const items = shallowRef([
+  { label: '余额充值、购买会员订单', value: 0, path: RechargeVipOrder },
+  { label: '商城交易订单', value: 1, path: MallOrder }
+])
 
 
 // 切换
 // 切换
-// const handleChangeTab = () => {
-//   query.value.pageNo = 1
-//   query.value.type = tab.value
-//   getData()
-// }
+const handleChangeTab = () => {
+}
 
 
-// const headers = ref([orderHeaders.value])
 </script>
 </script>
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 </style>
 </style>