hurx преди 1 месец
родител
ревизия
9704bece70
променени са 3 файла, в които са добавени 97 реда и са изтрити 22 реда
  1. 1 1
      src/views/order/orderAudit/index.vue
  2. 79 19
      src/views/order/orderEvaluation/evaluation.vue
  3. 17 2
      src/views/order/orderManage/index.vue

+ 1 - 1
src/views/order/orderAudit/index.vue

@@ -10,7 +10,7 @@
 
     <!-- 搜索栏 -->
     <div class="search-bar">
-      <el-input v-model="queryParams.keyword" placeholder="搜索" style="width: 240px" clearable>
+      <el-input v-model="queryParams.keyword" placeholder="请输入订单号查询" style="width: 240px" clearable>
         <template #prefix>
           <el-icon><Search /></el-icon>
         </template>

+ 79 - 19
src/views/order/orderEvaluation/evaluation.vue

@@ -7,7 +7,7 @@
         <span class="header-info">{{ orderInfo.orderTime }}</span>
       </div>
       <div class="header-right">
-        <el-button type="primary" @click="handleSubmitEvaluate">提交评价</el-button>
+        <el-button v-if="evaluateForm.evaluationType !== 3" type="primary" @click="handleSubmitEvaluate">提交评价</el-button>
         <el-button type="info" @click="handleBack">返回</el-button>
       </div>
     </div>
@@ -18,15 +18,15 @@
         <div class="logistics-ratings">
           <div class="rating-item">
             <span class="rating-label">快递包装</span>
-            <el-rate v-model="evaluateForm.expressPacking" :colors="rateColors" />
+            <el-rate v-model="evaluateForm.expressPacking" :colors="rateColors" :disabled="evaluateForm.evaluationType === 3" />
           </div>
           <div class="rating-item">
             <span class="rating-label">送货速度</span>
-            <el-rate v-model="evaluateForm.deliverySpeed" :colors="rateColors" />
+            <el-rate v-model="evaluateForm.deliverySpeed" :colors="rateColors" :disabled="evaluateForm.evaluationType === 3" />
           </div>
           <div class="rating-item">
             <span class="rating-label">配送员评价</span>
-            <el-rate v-model="evaluateForm.deliveryManRating" :colors="rateColors" />
+            <el-rate v-model="evaluateForm.deliveryManRating" :colors="rateColors" :disabled="evaluateForm.evaluationType === 3" />
           </div>
         </div>
       </div>
@@ -46,33 +46,46 @@
           <div class="product-code">{{ item.productNo }}</div>
         </div>
         <div class="product-right">
-          <div class="evaluation-hint">
+          <div class="evaluation-hint" v-if="evaluateForm.evaluationType !== 3">
             <el-icon color="#e6a23c"><WarningFilled /></el-icon>
             <span>请至少填写一件商品的评价</span>
           </div>
           <div class="rating-row">
             <span class="field-label">商品评价</span>
-            <el-rate v-model="item.rating" :colors="rateColors" />
+            <el-rate v-model="item.rating" :colors="rateColors" :disabled="evaluateForm.evaluationType === 3" />
           </div>
           <div class="content-row">
             <span class="field-label">评价晒单</span>
-            <el-input v-model="item.content" type="textarea" :rows="4" placeholder="请输入评价内容" maxlength="200" />
+            <el-input v-model="item.content" type="textarea" :rows="4" placeholder="请输入评价内容" maxlength="200" :disabled="evaluateForm.evaluationType === 3" />
           </div>
-          <div class="upload-row">
+          <div class="upload-row" v-if="evaluateForm.evaluationType !== 3">
             <el-upload
               class="upload-box"
               :action="action"
               :show-file-list="false"
               :on-success="(res) => handleProductUploadSuccess(res, index)"
               :before-upload="beforeAvatarUpload"
+              accept="image/*"
+              multiple
+              list-type="picture-card"
             >
-              <div v-if="item.imageUrl" class="upload-preview">
-                <el-image :src="item.imageUrl" fit="cover" />
-              </div>
-              <div v-else class="upload-placeholder">
+              <div class="upload-placeholder">
                 <el-icon :size="24"><Plus /></el-icon>
               </div>
             </el-upload>
+            <div v-if="item.images && item.images.length > 0" class="image-list">
+              <div v-for="(img, imgIndex) in item.images" :key="imgIndex" class="image-item">
+                <el-image :src="img" fit="cover" style="width: 100px; height: 100px; border-radius: 6px;" />
+                <el-icon class="delete-icon" @click="handleDeleteImage(index, imgIndex)"><Close /></el-icon>
+              </div>
+            </div>
+          </div>
+          <div class="upload-row" v-else>
+            <div v-if="item.images && item.images.length > 0" class="image-list">
+              <div v-for="(img, imgIndex) in item.images" :key="imgIndex" class="image-item">
+                <el-image :src="img" fit="cover" style="width: 100px; height: 100px; border-radius: 6px;" />
+              </div>
+            </div>
           </div>
         </div>
       </div>
@@ -83,7 +96,7 @@
 <script setup lang="ts">
 import { ref, reactive, onMounted } from 'vue';
 import { useRouter, useRoute } from 'vue-router';
-import { Picture, Plus, WarningFilled } from '@element-plus/icons-vue';
+import { Picture, Plus, WarningFilled, Close } from '@element-plus/icons-vue';
 import { ElMessage } from 'element-plus';
 import type { UploadProps } from 'element-plus';
 import { getOrderProducts, addOrderEvaluation, getOrderEvaluation, getOrderEvaluationHeader } from '@/api/pc/enterprise/order';
@@ -123,7 +136,7 @@ const loadOrderProducts = async (orderId: string) => {
         productImg: product.productImage || '',
         rating: 5,
         content: '',
-        imageUrl: ''
+        images: []
       }));
     }
     return [];
@@ -154,7 +167,8 @@ const loadExistingEvaluation = async (orderId: string) => {
           if (productIndex !== -1) {
             evaluateForm.productEvaluations[productIndex].rating = evalItem.productScore || 5;
             evaluateForm.productEvaluations[productIndex].content = evalItem.content || '';
-            evaluateForm.productEvaluations[productIndex].imageUrl = evalItem.images || '';
+            const imgStr = evalItem.images || '';
+            evaluateForm.productEvaluations[productIndex].images = imgStr ? imgStr.split(',').filter((url: string) => url) : [];
           }
         });
       }
@@ -167,15 +181,28 @@ const loadExistingEvaluation = async (orderId: string) => {
 //上传成功(按商品索引)
 const handleProductUploadSuccess = (res: any, index: number) => {
   if (res.code == 200) {
-    evaluateForm.productEvaluations[index].imageUrl = res.data.url;
+    if (!evaluateForm.productEvaluations[index].images) {
+      evaluateForm.productEvaluations[index].images = [];
+    }
+    evaluateForm.productEvaluations[index].images.push(res.data.url);
   } else {
     ElMessage({ message: res.msg, type: 'warning' });
   }
 };
 
+// 删除图片
+const handleDeleteImage = (productIndex: number, imageIndex: number) => {
+  evaluateForm.productEvaluations[productIndex].images.splice(imageIndex, 1);
+};
+
 const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
+  const isImage = rawFile.type.startsWith('image/');
+  if (!isImage) {
+    ElMessage.error('只能上传图片文件!');
+    return false;
+  }
   if (rawFile.size / 1024 / 1024 > 2) {
-    ElMessage.error('不能大于2MB!');
+    ElMessage.error('图片大小不能超过2MB!');
     return false;
   }
   return true;
@@ -205,7 +232,7 @@ const handleSubmitEvaluate = async () => {
           productImg: item.productImg || item.image,
           productScore: item.rating,
           content: item.content,
-          images: item.imageUrl ? String(item.imageUrl) : ''
+          images: item.images && item.images.length > 0 ? item.images.join(',') : ''
         }))
     };
 
@@ -254,7 +281,7 @@ onMounted(async () => {
           productImg: p.productImg || p.image,
           rating: 5,
           content: '',
-          imageUrl: ''
+          images: []
         }));
       } catch (e) {
         products = await loadOrderProducts(orderId);
@@ -445,4 +472,37 @@ onMounted(async () => {
     }
   }
 }
+
+.image-list {
+  display: flex;
+  gap: 10px;
+  flex-wrap: wrap;
+  margin-top: 10px;
+
+  .image-item {
+    position: relative;
+    width: 100px;
+    height: 100px;
+
+    .delete-icon {
+      position: absolute;
+      top: 2px;
+      right: 2px;
+      width: 20px;
+      height: 20px;
+      background: rgba(0, 0, 0, 0.5);
+      color: #fff;
+      border-radius: 50%;
+      cursor: pointer;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 14px;
+
+      &:hover {
+        background: rgba(0, 0, 0, 0.7);
+      }
+    }
+  }
+}
 </style>

+ 17 - 2
src/views/order/orderManage/index.vue

@@ -86,7 +86,7 @@
         <div class="order-header flex-row-between">
           <div class="flex-row-start" style="gap: 0 15px">
             <el-checkbox style="margin: 2px 0px 0px 0" v-model="order.checked" @change="handleOrderCheck" />
-            <div>{{ order.orderTime }}</div>
+            <div>{{ formatOrderTime(order.orderTime) }}</div>
             <div>订单号:{{ order.orderNo }}</div>
             <div>下单人:{{ order.orderPerson }}</div>
             <div>部门:{{ order.department }}</div>
@@ -130,7 +130,7 @@
             <div class="status-cell" v-if="itemIndex === 0">
               <span class="status-text" :style="{ color: getStatusColor(order.status) }">{{ order.statusText }}</span>
               <span v-if="order.auditStatus" :class="['audit-status', getAuditStatusClass(order.auditStatus)]">{{
-                order.auditStatus == '0' ? '待审批' : order.auditStatus == '1' ? '审批通过' : '审批驳回'
+                order.auditStatus == '0' ? '待审批' : order.auditStatus == '1' ? '' : '审批驳回'
               }}</span>
               <!-- <el-button type="primary" link size="small" @click="handleViewDetail(order)">查看订单轨迹</el-button> -->
               <el-button v-if="order.fileCount" type="primary" link size="small">审核文件({{ order.fileCount }})</el-button>
@@ -242,6 +242,21 @@ import { getDeptTree } from '@/api/pc/organization';
 import { DeptInfo } from '@/api/pc/organization/types';
 import { addProductShoppingCart } from '@/api/goods/index';
 import { onPath } from '@/utils/siteConfig';
+import { parseTime } from '@/utils/ruoyi';
+
+// 格式化订单时间
+const formatOrderTime = (timeStr: string) => {
+  if (!timeStr) return '';
+  try {
+    // 处理后端返回的中文时间格式 "2026/3/13 上午3:35"
+    const date = new Date(timeStr);
+    if (isNaN(date.getTime())) return timeStr;
+    return parseTime(date, '{y}-{m}-{d} {h}:{i}:{s}');
+  } catch (e) {
+    return timeStr;
+  }
+};
+
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { order_status, pay_method } = toRefs<any>(proxy?.useDict('order_status', 'pay_method'));