瀏覽代碼

3-14fix bug

Alex 10 月之前
父節點
當前提交
b777698810
共有 27 個文件被更改,包括 984 次插入538 次删除
  1. 111 74
      src/components/CommonPage/SimpleFormModal.vue
  2. 2 3
      src/views/customer/list/components/customer-detail.vue
  3. 1 1
      src/views/customer/list/components/detail/base-info.vue
  4. 1 1
      src/views/data/books/components/books-edit.vue
  5. 23 3
      src/views/data/books/components/books-search.vue
  6. 3 0
      src/views/data/books/index.vue
  7. 24 4
      src/views/finance/bookPayments/index.vue
  8. 68 0
      src/views/finance/withdrawal/components/detail-dialog.vue
  9. 12 1
      src/views/finance/withdrawal/index.vue
  10. 1 6
      src/views/optimization/complain/components/complain-item.vue
  11. 51 24
      src/views/optimization/fallback/components/deal-fallback.vue
  12. 2 1
      src/views/optimization/fallback/index.vue
  13. 18 1
      src/views/recycle/components/book-search.vue
  14. 112 0
      src/views/recycleOrder/components/apply-order-restore.vue
  15. 11 1
      src/views/recycleOrder/components/order-page-all.vue
  16. 3 0
      src/views/recycleOrder/components/order-remarks.vue
  17. 2 2
      src/views/recycleOrder/components/order-search.vue
  18. 51 38
      src/views/recycleOrder/components/order-timeline.vue
  19. 4 12
      src/views/recycleOrder/detail/index.vue
  20. 464 353
      src/views/recycleOrder/detail/order-book-list.vue
  21. 1 1
      src/views/recycleOrder/detail/order-status.vue
  22. 2 2
      src/views/recycleOrder/needReturned/index.vue
  23. 1 1
      src/views/recycleOrder/needReturned/refund-detail.vue
  24. 8 1
      src/views/recycleOrder/needReturned/return-search.vue
  25. 4 4
      src/views/recycleService/stockIn/components/stock-in-search.vue
  26. 1 1
      src/views/recycleService/stockOut/components/stock-out-search.vue
  27. 3 3
      src/views/recycleService/stockOut/index.vue

+ 111 - 74
src/components/CommonPage/SimpleFormModal.vue

@@ -1,35 +1,56 @@
 <!-- 编辑弹窗 -->
 <template>
-    <ele-modal form :width="width" v-model="visible" :title="title" position="center"
-        :body-style="{ maxHeight: '84vh', position: 'relative', ...bodyStyle }">
-        <slot name="other"></slot>
+  <ele-modal
+    form
+    :width="width"
+    v-model="visible"
+    :title="title"
+    position="center"
+    :body-style="{ maxHeight: '84vh', position: 'relative', ...bodyStyle }"
+  >
+    <slot name="other"></slot>
 
-        <SimpleForm :items="items" :labelWidth="labelWidth" ref="formRef" v-bind="formProps"
-            :disabled="type === 'detail'">
-            <template v-for="(val, key) in slotArray" v-slot:[key]="{ item, model, updateValue }">
-                <slot :name="key" :item="item" :model="model" :updateValue="updateValue"></slot>
-            </template>
-        </SimpleForm>
+    <SimpleForm
+      :items="items"
+      :labelWidth="labelWidth"
+      ref="formRef"
+      v-bind="formProps"
+      :disabled="type === 'detail'"
+    >
+      <template
+        v-for="(val, key) in slotArray"
+        v-slot:[key]="{ item, model, updateValue }"
+      >
+        <slot
+          :name="key"
+          :item="item"
+          :model="model"
+          :updateValue="updateValue"
+        ></slot>
+      </template>
+    </SimpleForm>
 
-        <template #footer>
-            <el-button @click="handleCancel">关闭</el-button>
-            <el-button type="primary" @click="handleSumbit" v-if="type !== 'detail'">确定</el-button>
-        </template>
-    </ele-modal>
+    <template #footer>
+      <el-button @click="handleCancel">关闭</el-button>
+      <el-button type="primary" @click="handleSumbit" v-if="type !== 'detail'"
+        >确定</el-button
+      >
+    </template>
+  </ele-modal>
 </template>
 
 <script setup>
-import { ref, reactive, nextTick, getCurrentInstance, useSlots } from 'vue';
-import { Flag, ChatDotSquare } from '@element-plus/icons-vue';
-import orderTimeline from '@/views/recycleOrder/components/order-timeline.vue';
-import SimpleForm from '@/components/CommonPage/SimpleForm.vue';
-import validators from '@/utils/validators';
-import { EleMessage } from 'ele-admin-plus/es';
-let { proxy } = getCurrentInstance();
+  import { ref, reactive, nextTick, getCurrentInstance, useSlots } from 'vue';
+  import { Flag, ChatDotSquare } from '@element-plus/icons-vue';
+  import orderTimeline from '@/views/recycleOrder/components/order-timeline.vue';
+  import SimpleForm from '@/components/CommonPage/SimpleForm.vue';
+  import validators from '@/utils/validators';
+  import { EleMessage } from 'ele-admin-plus/es';
+  let { proxy } = getCurrentInstance();
 
-const slotArray = useSlots();
+  const slotArray = useSlots();
 
-const props = defineProps({
+  const props = defineProps({
     items: { type: Array, default: () => [] },
     title: { type: String, default: '编辑' },
     type: { type: String },
@@ -41,81 +62,97 @@ const props = defineProps({
     //是否需要合并打开时传入的参数
     isMerge: { type: Boolean, default: false },
     formatData: {
-        type: Function,
-        default: (data) => data
+      type: Function,
+      default: (data) => data
     }, //格式化提交数据
     idKey: { type: String, default: 'id' },
     fallbackData: { type: Function, default: (data) => data } //回填数据
-});
-const emit = defineEmits(['success']);
-/** 弹窗是否打开 */
-const visible = defineModel({ type: Boolean });
+  });
+  const emit = defineEmits(['success']);
+  /** 弹窗是否打开 */
+  const visible = defineModel({ type: Boolean });
 
-/** 关闭弹窗 */
-const handleCancel = () => {
+  /** 关闭弹窗 */
+  const handleCancel = () => {
     visible.value = false;
-};
+  };
 
-const form = ref({});
-const mergeData = ref({});
-/** 弹窗打开事件 */
-const handleOpen = async (data) => {
+  const form = ref({});
+  const mergeData = ref({});
+  /** 弹窗打开事件 */
+  const handleOpen = async (data) => {
     visible.value = true;
     nextTick(() => {
-        formRef.value?.resetForm();
-        mergeData.value = data;
-        if (!props.baseUrl.detail) {
-            form.value = data;
-            formRef.value?.setData(data);
-        } else {
-            getDetail(data.id).then((res) => {
-                form.value = res.data;
-                let data = props.fallbackData(res.data);
-                formRef.value?.setData(data);
-            });
+      formRef.value?.resetForm();
+      mergeData.value = data;
+      if (!props.baseUrl.detail) {
+        form.value = data;
+        formRef.value?.setData(data);
+      } else {
+        getDetail(data.id).then((res) => {
+          form.value = res.data;
+          let data = props.fallbackData(res.data);
+          formRef.value?.setData(data);
+        });
+      }
+
+      // 重置滚动条位置
+      resetScrollPosition();
+    });
+  };
+
+  // 重置滚动条位置
+  const resetScrollPosition = () => {
+    nextTick(() => {
+      setTimeout(() => {
+        const modalBody = document.querySelectorAll('.ele-modal-body');
+        if (modalBody) {
+          modalBody[modalBody.length - 1].scrollTop = 0;
         }
+      }, 100);
     });
-};
+  };
 
-//获取详情数据
-const getDetail = (id) => {
+  //获取详情数据
+  const getDetail = (id) => {
     if (!props.baseUrl.detail || !id) return;
     let url = `${props.baseUrl.detail}/${id}`;
     return new Promise((resolve, reject) => {
-        proxy.$http.get(url).then((res) => {
-            if (res.data.code !== 200) return EleMessage.error(res.data.msg);
-            resolve(res.data || {});
-        });
+      proxy.$http.get(url).then((res) => {
+        if (res.data.code !== 200) return EleMessage.error(res.data.msg);
+        resolve(res.data || {});
+      });
     });
-};
+  };
 
-const formRef = ref();
-const handleSumbit = () => {
+  const formRef = ref();
+  const handleSumbit = () => {
     console.log(props.formatData, '格式化数据');
 
     formRef.value?.submitForm().then((data) => {
-        console.log(data, '格式化数据data');
+      console.log(data, '格式化数据data');
 
-        data[props.idKey] = form.value[props.idKey];
-        let url = data[props.idKey] ? props.baseUrl.update : props.baseUrl.add;
-        data = props.isMerge ? { ...mergeData.value, ...data } : data;
-        let format = props.formatData(data);
-        proxy.$http.post(url, format).then((res) => {
-            if (res.data.code !== 200) return EleMessage.error(res.data.msg);
-            visible.value = false;
-            emit('success', data);
-            EleMessage.success(format[props.idKey] ? '编辑成功' : '操作成功');
-        });
+      data[props.idKey] = form.value[props.idKey];
+      let url = data[props.idKey] ? props.baseUrl.update : props.baseUrl.add;
+      data = props.isMerge ? { ...mergeData.value, ...data } : data;
+      let format = props.formatData(data);
+      proxy.$http.post(url, format).then((res) => {
+        if (res.data.code !== 200) return EleMessage.error(res.data.msg);
+        visible.value = false;
+        emit('success', data);
+        EleMessage.success(format[props.idKey] ? '编辑成功' : '操作成功');
+      });
     });
-};
+  };
 
-const setData = (data) => {
+  const setData = (data) => {
     formRef.value?.setData(data);
-};
+  };
 
-defineExpose({
+  defineExpose({
     handleOpen,
     handleSumbit,
-    setData
-});
+    setData,
+    resetScrollPosition
+  });
 </script>

+ 2 - 3
src/views/customer/list/components/customer-detail.vue

@@ -16,12 +16,12 @@
     </div>
 
     <div class="flex items-center mb-5 mt-5 ml-3">
-      <el-statistic :value="accountInfo.restMoney">
+      <el-statistic :value="detail.restMoney">
         <template #title>
           <el-text>账户余额</el-text>
         </template>
       </el-statistic>
-      <el-statistic :value="accountInfo.totalMoney" style="margin-left: 80px">
+      <el-statistic :value="detail.orderNum" style="margin-left: 80px">
         <template #title>
           <el-text>总订单数</el-text>
         </template>
@@ -65,7 +65,6 @@
     nextTick(() => {
       activeName.value = tabName || 'baseinfo';
       getUserInfo(row.id);
-      getAccountInfo(row.id);
     });
   }
 

+ 1 - 1
src/views/customer/list/components/detail/base-info.vue

@@ -9,7 +9,7 @@
     </el-row>
     <div class="common-title">概况信息</div>
     <el-row :gutter="12" class="p-4 leading-8">
-      <el-col :span="24">用户标签:{{ detail.userTagNames || '-' }}</el-col>
+      <el-col :span="24">用户标签:{{ detail.userTagStr || '-' }}</el-col>
       <el-col :span="12">注册时间:{{ detail.createTime || '-' }}</el-col>
       <el-col :span="12">最近登录时间:{{ detail.loginTime || '-' }}</el-col>
     </el-row>

+ 1 - 1
src/views/data/books/components/books-edit.vue

@@ -27,7 +27,7 @@
 </template>
 
 <script setup>
-  import { reactive, ref, defineEmits, getCurrentInstance } from 'vue';
+  import { reactive, ref, defineEmits, getCurrentInstance, nextTick } from 'vue';
   import { useFormData } from '@/utils/use-form-data';
   import SimpleFormModal from '@/components/CommonPage/SimpleFormModal.vue';
   import ImageUpload from '@/components/ImageUpload/index.vue';

+ 23 - 3
src/views/data/books/components/books-search.vue

@@ -23,7 +23,7 @@
     { type: 'input', label: '作者', prop: 'author' },
     { type: 'input', label: '出版社', prop: 'publish' },
     {
-        type: 'dictSelect',
+      type: 'dictSelect',
       label: '人工核实',
       prop: 'perCheck',
       props: { code: 'is_common_yes' }
@@ -34,6 +34,23 @@
       prop: 'suit',
       props: { code: 'is_common_yes' }
     },
+    {
+      type: 'select',
+      label: '信息缺失',
+      prop: 'emptyType',
+      props: {
+        multiple: true,
+        clearable: true,
+        collapseTags: true
+      },
+      options: [
+        { label: '图片', value: 1 },
+        { label: '书名', value: 2 },
+        { label: '作者', value: 3 },
+        { label: '出版社', value: 4 },
+        { label: '出版时间', value: 5 }
+      ]
+    }
   ]);
 
   const initKeys = reactive({
@@ -42,12 +59,15 @@
     cityId: '',
     schoolLevel: '',
     departmentName: '',
-    shcoolTag: ''
+    shcoolTag: '',
+    emptyType: []
   });
 
   const searchRef = ref(null);
   /** 搜索 */
   const search = (data) => {
-    emit('search', { ...data });
+    let params = JSON.parse(JSON.stringify(data));
+    params.emptyType = params.emptyType.join(',');
+    emit('search', { ...params });
   };
 </script>

+ 3 - 0
src/views/data/books/index.vue

@@ -73,6 +73,9 @@
           style="width: 80px; height: 100px"
           fit="cover"
           :src="row.cover"
+          :preview-src-list="[row.cover]"
+          :initial-index="0"
+          preview-teleported
         />
       </template>
 

+ 24 - 4
src/views/finance/bookPayments/index.vue

@@ -10,21 +10,21 @@
             title="累计书款金额"
             :precision="2"
             value-style="font-size:30px"
-            class="mr-10"
+            class="mr-20"
           ></el-statistic>
           <el-statistic
             :value="statistics.unFinishMoney"
             title="待结算书款"
             :precision="2"
             value-style="font-size:30px"
-            class="mr-10"
+            class="mr-20"
           ></el-statistic>
           <el-statistic
             :value="statistics.finishMoney"
             title="已结算书款"
             value-style="font-size:30px"
             :precision="2"
-            class="mr-10"
+            class="mr-20"
           ></el-statistic>
         </div>
 
@@ -40,7 +40,15 @@
       <template #status="{ row }">
         {{ statusDicts.find((d) => d.value == row.status)?.label }}
       </template>
+
+      <template #orderId="{ row }">
+        <el-button type="primary" link @click="handleOrderId(row)">{{
+          row.orderId
+        }}</el-button>
+      </template>
     </common-table>
+
+    <orderDetail ref="orderDetailRef" />
   </ele-page>
 </template>
 
@@ -49,6 +57,7 @@
   import CommonTable from '@/components/CommonPage/CommonTable.vue';
   import pageSearch from './page-search.vue';
   import request from '@/utils/request';
+  import OrderDetail from '@/views/recycleOrder/components/order-detail.vue';
 
   defineOptions({ name: 'bookPayments' });
 
@@ -71,6 +80,11 @@
     }
   }
 
+  const orderDetailRef = ref(null);
+  const handleOrderId = (row) => {
+    orderDetailRef.value?.handleOpen(row);
+  };
+
   onMounted(() => {
     fetchStatistics();
   });
@@ -105,7 +119,13 @@
       align: 'center',
       formatter: (row) => (row.status == 2 ? '已结算书款' : '未结算书款')
     },
-    { label: '订单编号', prop: 'orderId', align: 'center', minWidth: 160 }
+    {
+      label: '订单编号',
+      prop: 'orderId',
+      align: 'center',
+      minWidth: 120,
+      slot: 'orderId'
+    }
   ]);
 
   /** 页面组件实例 */

+ 68 - 0
src/views/finance/withdrawal/components/detail-dialog.vue

@@ -0,0 +1,68 @@
+<!-- 详情弹窗 -->
+<template>
+  <ele-modal v-model="visible" title="提现详情" width="700">
+    <el-descriptions :column="2" border :label-width="120">
+      <el-descriptions-item label="ID" :span="2">{{
+        detail.id
+      }}</el-descriptions-item>
+      <el-descriptions-item label="审核人">{{
+        detail.auditName
+      }}</el-descriptions-item>
+      <el-descriptions-item label="审核时间">{{
+        detail.auditTime
+      }}</el-descriptions-item>
+      <el-descriptions-item label="状态">
+        {{ statusDicts.find((d) => d.dictValue == detail.status)?.dictLabel }}
+      </el-descriptions-item>
+    </el-descriptions>
+
+    <template #footer>
+      <el-button @click="visible = false">关闭</el-button>
+    </template>
+  </ele-modal>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import request from '@/utils/request';
+  import { ElMessage } from 'element-plus';
+  import { useDictData } from '@/utils/use-dict-data';
+
+  const emit = defineEmits(['success']);
+  const visible = defineModel({ type: Boolean });
+
+  const [statusDicts] = useDictData(['withdrawal_status']);
+  const detail = reactive({
+    id: '',
+    createTime: '',
+    nickName: '',
+    transferNo: '',
+    withdrawType: '',
+    withdrawMoney: '',
+    status: '',
+    auditId: '',
+    auditName: '',
+    auditTime: ''
+  });
+
+  // 打开弹窗
+  const handleOpen = async (row) => {
+    if (row) {
+      visible.value = true;
+      request
+        .get(`/sys/finance/withdrawList/getDetail/${row.id}`)
+        .then((res) => {
+          console.log(res, row, 'xxxx');
+          if (res.data.code === 200) {
+            Object.assign(detail, row, res.data.data);
+          } else {
+            ElMessage.error(res.data.msg || '获取详情失败');
+          }
+        });
+    }
+  };
+
+  defineExpose({
+    handleOpen
+  });
+</script>

+ 12 - 1
src/views/finance/withdrawal/index.vue

@@ -62,7 +62,8 @@
 
         <el-radio-group @change="handleStatusChange" v-model="useStatus">
           <el-radio-button label="全部" value="" />
-          <el-radio-button label="提现中" value="2" />
+          <el-radio-button label="待审核" value="1" />
+          <el-radio-button label="待确认" value="2" />
           <el-radio-button label="提现完成" value="4" />
           <el-radio-button label="提现失败" value="5" />
           <el-radio-button label="长期不提现用户" value="6" />
@@ -98,6 +99,9 @@
 
     <!-- 审核弹窗 -->
     <audit-dialog ref="auditDialogRef" @success="reload" />
+
+    <!-- 详情弹窗 -->
+    <detail-dialog ref="detailDialogRef" />
   </ele-page>
 </template>
 
@@ -108,6 +112,7 @@
   import { useDictData } from '@/utils/use-dict-data';
   import request from '@/utils/request';
   import auditDialog from './components/audit-dialog.vue';
+  import detailDialog from './components/detail-dialog.vue';
 
   defineOptions({ name: 'withdrawal' });
 
@@ -206,6 +211,7 @@
   /** 页面组件实例 */
   const pageRef = ref(null);
   const auditDialogRef = ref(null);
+  const detailDialogRef = ref(null);
 
   const pageConfig = reactive({
     pageUrl: '/sys/finance/withdrawList',
@@ -223,6 +229,11 @@
     auditDialogRef.value?.handleOpen(row.id);
   }
 
+  //详情
+  function handleUpdate(row) {
+    detailDialogRef.value?.handleOpen(row);
+  }
+
   //一键审核
   function handleStepAudit() {
     const selections = pageRef.value?.getSelections();

+ 1 - 6
src/views/optimization/complain/components/complain-item.vue

@@ -15,12 +15,7 @@
         }}</ele-text>
       </div>
       <div class="mt-2">
-        <ele-text v-if="item.userType === '1'"
-          >用户发起投诉,投诉原因: {{ item.reason }},投诉说明:{{
-            item.description || ''
-          }}</ele-text
-        >
-        <ele-text v-else>{{ item.description || '' }}</ele-text>
+        <ele-text>{{ item.description || '' }}</ele-text>
       </div>
       <!-- 显示图片列表 -->
       <div

+ 51 - 24
src/views/optimization/fallback/components/deal-fallback.vue

@@ -4,28 +4,37 @@
     v-model="visible"
     :title="type === 'detail' ? '反馈详情' : '处理反馈'"
     width="600px"
-    @open="handleDialogOpen"
   >
     <el-form ref="formRef" :model="form" label-width="100px">
       <el-form-item label="联系方式">
-        <el-input v-model="form.mobile" disabled />
+        <el-input v-model="form.mobile" :disabled="type === 'detail'" />
       </el-form-item>
       <el-form-item label="意见描述">
-        <el-input v-model="form.desc" type="textarea" :rows="4" disabled />
+        <el-input
+          v-model="form.description"
+          type="textarea"
+          :rows="4"
+          :disabled="type === 'detail'"
+        />
       </el-form-item>
       <el-form-item label="反馈图片">
-        <el-image
-          v-if="form.image"
-          :src="form.image"
-          style="width: 120px; height: 120px; border-radius: 4px"
-          fit="cover"
-        />
+        <div class="image-container">
+          <el-image
+            v-for="(img, index) in form.images"
+            :key="index"
+            :src="img"
+            style="width: 120px; height: 120px; border-radius: 4px; margin-right: 10px; margin-bottom: 10px; cursor: pointer;"
+            fit="cover"
+            :preview-src-list="form.images"
+            :initial-index="index"
+          />
+        </div>
       </el-form-item>
     </el-form>
     <template #footer>
       <span class="dialog-footer">
         <el-button @click="visible = false">取 消</el-button>
-        <template v-if="!type && form.status === 1">
+        <template v-if="type === 'deal' && form.status == 1">
           <el-button type="primary" @click="handleProcessing">已反馈</el-button>
           <el-button type="success" @click="handleFinish">已处理</el-button>
         </template>
@@ -43,30 +52,43 @@
 
   const visible = ref(false);
   const type = ref('');
-  const form = reactive({
+  const form = ref({
     id: '',
     mobile: '',
-    desc: '',
-    image: '',
-    status: 0
+    description: '',
+    images: [],
+    status: 1
   });
 
   // 打开弹窗
-  function handleOpen(data = {}, dialogType) {
-    type.value = dialogType;
-    Object.assign(form, data);
-    visible.value = true;
+  function handleOpen(data, dialogType) {
+    if (data && data.id) {
+      type.value = dialogType;
+      form.value = data;
+      visible.value = true;
+      // 获取反馈详情
+      getFallbackDetail();
+    }
   }
-
-  // 弹窗打开回调
-  function handleDialogOpen() {
-    // 可以在这里做一些初始化工作
+  //获取反馈详情
+  async function getFallbackDetail() {
+    request.get(`/sys/suggestionLog/getInfo/${form.value.id}`).then((res) => {
+      if (res.data.code === 200) {
+        form.value = res.data.data;
+        // 确保 image 是数组
+        if (form.value.images && !Array.isArray(form.value.images)) {
+          form.value.images = [form.value.images];
+        }
+      } else {
+        ElMessage.error(res.data.msg);
+      }
+    });
   }
 
   // 处理中
   async function handleProcessing() {
     try {
-      await request.post(`/sys/suggestionLog/processing/${form.id}`);
+      await request.post(`/sys/suggestionLog/processing/${form.value.id}`);
       ElMessage.success('操作成功');
       visible.value = false;
       emit('done');
@@ -78,7 +100,7 @@
   // 已处理
   async function handleFinish() {
     try {
-      await request.post(`/sys/suggestionLog/finish/${form.id}`);
+      await request.post(`/sys/suggestionLog/finish/${form.value.id}`);
       ElMessage.success('操作成功');
       visible.value = false;
       emit('done');
@@ -96,4 +118,9 @@
     justify-content: flex-end;
     gap: 8px;
   }
+
+  .image-container {
+    display: flex;
+    flex-wrap: wrap;
+  }
 </style>

+ 2 - 1
src/views/optimization/fallback/index.vue

@@ -41,7 +41,7 @@
             link
             v-if="row.status == 1"
             v-permission="'optimization:fallback:deal'"
-            @click="handleUpdate(row)"
+            @click="handleUpdate(row, 'deal')"
           >
             去处理
           </el-button>
@@ -54,6 +54,7 @@
 
 <script setup>
   import { ref, reactive } from 'vue';
+  import { DownloadOutlined } from '@/components/icons';
   import CommonTable from '@/components/CommonPage/CommonTable.vue';
   import dealFallback from '@/views/optimization/fallback/components/deal-fallback.vue';
   import pageSearch from '@/views/optimization/fallback/components/page-search.vue';

+ 18 - 1
src/views/recycle/components/book-search.vue

@@ -64,6 +64,21 @@
           });
         }
       }
+    },
+    {
+      type: 'select',
+      label: '默认参数',
+      prop: 'defaultType',
+      props: {
+        multiple: true,
+        clearable: true,
+        collapseTags: true
+      },
+      options: [
+        { label: '最大回收数量', value: 1 },
+        { label: '单个订单回收数量', value: 2 },
+        { label: '回收折扣', value: 3 }
+      ]
     }
   ]);
 
@@ -80,7 +95,8 @@
     maxDiscount: void 0,
     searchType: 0,
     globalInDiscount: void 0,
-    globalNotInDiscount: void 0
+    globalNotInDiscount: void 0,
+    defaultType: []
   });
 
   const searchRef = ref(null);
@@ -90,6 +106,7 @@
     delete params.price;
     delete params.discount;
     delete params.pubDate;
+    params.defaultType = params.defaultType.join(',');
     emit('search', params);
   };
 </script>

+ 112 - 0
src/views/recycleOrder/components/apply-order-restore.vue

@@ -0,0 +1,112 @@
+<!-- 申请恢复订单弹窗 -->
+<template>
+  <ele-modal
+    form
+    :width="500"
+    v-model="visible"
+    title="申请恢复订单"
+    @open="handleOpen"
+  >
+    <el-form
+      ref="formRef"
+      :model="form"
+      :rules="rules"
+      label-width="80px"
+      @submit.prevent=""
+    >
+      <el-form-item label="订单编号">
+        <el-text>{{ form.orderId }}</el-text>
+      </el-form-item>
+      <el-form-item label="申请原因" prop="reason">
+        <el-input
+          v-model="form.reason"
+          type="textarea"
+          :rows="4"
+          placeholder="请输入申请原因"
+        ></el-input>
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <el-button @click="handleCancel">关闭</el-button>
+      <el-button type="primary" @click="handleSubmit">确定</el-button>
+    </template>
+  </ele-modal>
+</template>
+
+<script setup>
+  import { ref, reactive, getCurrentInstance } from 'vue';
+  import { EleMessage } from 'ele-admin-plus/es';
+
+  const { proxy } = getCurrentInstance();
+  const emit = defineEmits(['success']);
+
+  /** 弹窗是否打开 */
+  const visible = defineModel({ type: Boolean });
+
+  /** 表单引用 */
+  const formRef = ref();
+
+  /** 表单数据 */
+  const form = reactive({
+    orderId: '',
+    reason: ''
+  });
+
+  /** 表单验证规则 */
+  const rules = reactive({
+    reason: [
+      {
+        required: true,
+        message: '请输入申请原因',
+        trigger: 'blur'
+      }
+    ]
+  });
+
+  /** 关闭弹窗 */
+  const handleCancel = () => {
+    visible.value = false;
+    resetForm();
+  };
+
+  /** 重置表单 */
+  const resetForm = () => {
+    form.orderId = '';
+    form.reason = '';
+    formRef.value?.resetFields();
+  };
+
+  /** 弹窗打开事件 */
+  const handleOpen = (row) => {
+    if (row && row.orderId) {
+      visible.value = true;
+      form.orderId = row.orderId;
+    }
+  };
+
+  /** 提交表单 */
+  const handleSubmit = () => {
+    formRef.value?.validate(async (valid) => {
+      if (!valid) return;
+      proxy.$http
+        .post('/order/orderInfo/adminCancelRecover', {
+          orderId: form.orderId,
+          reason: form.reason
+        })
+        .then((res) => {
+          if (res.data.code === 200) {
+            EleMessage.success('申请恢复订单成功');
+            emit('success');
+            handleCancel();
+          } else {
+            EleMessage.error(res.data.msg || '申请恢复订单失败');
+          }
+        });
+    });
+  };
+
+  defineExpose({
+    handleOpen
+  });
+</script>

+ 11 - 1
src/views/recycleOrder/components/order-page-all.vue

@@ -272,7 +272,7 @@
 
     <slot></slot>
     <!-- 备注 -->
-    <orderRemarks ref="remarksRef" />
+    <orderRemarks ref="remarksRef" @refresh="reload()" />
     <!-- 初审 -->
     <firstCheckModal ref="firstCheckRef" @success="reload()" />
     <!-- 修改地址 -->
@@ -293,6 +293,8 @@
     <sendSMS ref="sendSMSRef" />
     <!-- 短信记录 -->
     <orderSmsLog ref="orderSmsLogRef" />
+    <!-- 申请恢复订单 -->
+    <applyOrderRestore ref="applyOrderRestoreRef" @success="reload()" />
   </ele-page>
 </template>
 
@@ -327,6 +329,8 @@
   import sendSMS from '@/views/recycleOrder/components/send-SMS.vue';
   //短信记录
   import orderSmsLog from '@/views/recycleOrder/components/order-sms-log.vue';
+  //申请恢复订单
+  import applyOrderRestore from '@/views/recycleOrder/components/apply-order-restore.vue';
 
   let props = defineProps({
     pageConfig: {
@@ -692,6 +696,12 @@
     auditScreenshotRef.value?.handleOpen(row);
   }
 
+  //申请恢复订单
+  const applyOrderRestoreRef = ref(null);
+  function handleApplyForOrderRestore(row) {
+    applyOrderRestoreRef.value?.handleOpen(row);
+  }
+
   defineExpose({
     selections,
     reload,

+ 3 - 0
src/views/recycleOrder/components/order-remarks.vue

@@ -55,6 +55,9 @@ const handleOpen = (data) => {
     });
 };
 
+/** 刷新事件 */
+const emit = defineEmits(['refresh']);
+
 /** 确定 /order/orderInfo/addRemark */
 const formRef = ref(null);
 const handleSubmit = () => {

+ 2 - 2
src/views/recycleOrder/components/order-search.vue

@@ -42,7 +42,7 @@ const columns = ref([
     {
         type: 'input',
         label: '搜索备注关键字',
-        prop: 'userRemarkLike'
+        prop: 'userRemark'
     },
     {
         type: 'select',
@@ -60,7 +60,7 @@ const columns = ref([
     {
         type: 'dictSelect',
         label: '物流公司',
-        prop: 'userExpress',
+        prop: 'finalExpress',
         props: { code: 'final_express' }
     },
     {

+ 51 - 38
src/views/recycleOrder/components/order-timeline.vue

@@ -1,60 +1,73 @@
 <template>
-    <div class="demo-timeline">
-        <div v-if="records.length" style="margin-bottom: 10px">{{ title }}</div>
-        <el-timeline v-if="records.length">
-            <el-timeline-item v-for="(item, index) in records" :key="index" :timestamp="item.createTime"
-                :color="item.label">
-                <div style="display: flex;align-items: center;flex-wrap: wrap;">
-                    <el-icon :size="14" :color="item.label">
-                        <Flag />
-                    </el-icon>
-                    <span>{{ item.createName }}:</span>
-                    <span>{{ item.remark }}</span>
-                </div>
-            </el-timeline-item>
-        </el-timeline>
-        <el-empty v-else description="暂无数据"></el-empty>
-    </div>
+  <div class="demo-timeline">
+    <div v-if="loading" v-loading="loading" style="height: 180px"></div>
+    <template v-else>
+      <div v-if="records.length" style="margin-bottom: 10px">{{ title }}</div>
+      <el-timeline v-if="records.length">
+        <el-timeline-item
+          v-for="(item, index) in records"
+          :key="index"
+          :timestamp="item.createTime"
+          :color="item.label"
+        >
+          <div style="display: flex; align-items: center; flex-wrap: wrap">
+            <el-icon :size="14" :color="item.label">
+              <Flag />
+            </el-icon>
+            <span>{{ item.createName }}:</span>
+            <span>{{ item.remark }}</span>
+          </div>
+        </el-timeline-item>
+      </el-timeline>
+      <el-empty v-else description="暂无数据" :image-size="80"></el-empty>
+    </template>
+  </div>
 </template>
 
 <script setup>
-import { watch, ref, onMounted } from 'vue';
-import request from '@/utils/request';
-import { Flag } from '@element-plus/icons-vue';
+  import { watch, ref, onMounted } from 'vue';
+  import request from '@/utils/request';
+  import { Flag } from '@element-plus/icons-vue';
 
-const props = defineProps({
+  const props = defineProps({
     orderId: {
-        type: String,
-        default: ''
+      type: [String, Number],
+      default: ''
     },
     title: {
-        type: String,
-        default: ''
+      type: String,
+      default: ''
     }
-});
+  });
 
-const records = ref([]);
-const loading = ref(false);
+  const records = ref([]);
+  const loading = ref(false);
 
-//获取备注
-const getRemarks = async () => {
+  //获取备注
+  const getRemarks = async () => {
     if (!props.orderId || loading.value) return;
 
     loading.value = true;
     try {
-        const res = await request.get(`/order/remark/list?orderId=${props.orderId}`);
-        records.value = res.data.data;
+      const res = await request.get(
+        `/order/remark/list?orderId=${props.orderId}`
+      );
+      records.value = res.data.data;
     } catch (error) {
-        console.error('Failed to fetch remarks:', error);
+      console.error('Failed to fetch remarks:', error);
     } finally {
-        loading.value = false;
+      loading.value = false;
     }
-};
+  };
 
-watch(() => props.orderId, (newVal, oldVal) => {
-    if (newVal && newVal !== oldVal) {
+  watch(
+    () => props.orderId,
+    (newVal, oldVal) => {
+      if (newVal && newVal !== oldVal) {
         records.value = [];
         getRemarks();
-    }
-}, { immediate: true });
+      }
+    },
+    { immediate: true }
+  );
 </script>

+ 4 - 12
src/views/recycleOrder/detail/index.vue

@@ -25,7 +25,7 @@
       </template>
 
       <orderBookList
-        :isExpand="isExpand"
+        :isExpand="detail.status >= 8 ? true : isExpand"
         :detail="detail"
         @refresh="emit('refresh')"
         ref="bookListRef"
@@ -36,14 +36,14 @@
     <ele-card class="order-service" header="订单服务">
       <el-tag size="large" style="margin-right: 20px">免费退回</el-tag>
       <el-tag size="large" style="margin-right: 20px">24小时验</el-tag>
-      <el-tag size="large">速打款</el-tag>
+      <el-tag size="large">速打款</el-tag>
     </ele-card>
 
     <ele-card class="order-note" header="审核计价说明">
       品相良好:按原始回收折扣计价;品相一般:按原始回收折扣*0.7计价;品相极差:不收。
     </ele-card>
     <ele-card class="order-freight" header="物流动态">
-      <orderFreightStatus :records="detail.trackingVoList" />
+      <orderFreightStatus :records="detail.trackingVoList||[]" />
     </ele-card>
   </ele-page>
 </template>
@@ -62,7 +62,7 @@
     }
   });
 
-  const isExpand = ref(true);
+  const isExpand = ref(false);
   const handleExpand = () => {
     isExpand.value = true;
   };
@@ -70,14 +70,6 @@
     isExpand.value = false;
   };
 
-  watch(
-    () => props.detail,
-    (newVal) => {
-      isExpand.value = newVal.status >= 8;
-    },
-    { deep: true, immediate: true }
-  );
-
   // 其余审核良好
   const bookListRef = ref(null);
   function handleOtherAuditGood() {

+ 464 - 353
src/views/recycleOrder/detail/order-book-list.vue

@@ -1,477 +1,588 @@
 <template>
-    <ele-data-table row-key="userId" :columns="columns" :data="dataList" border class="order-books"
-        :span-method="handleSpanMethod">
-        <template #baseInfo="{ row }">
-            <div class="base-info flex justify-between">
-                <div class="base-info-left flex flex-1">
-                    <el-image style="min-width: 80px;width: 80px; height: 100px" fit="cover" :src="row.cover" />
-                    <div class="base-info-left-con flex flex-col items-start ml-3">
-                        <div><el-text type="primary">{{ row.bookName }}</el-text></div>
-                        <div><el-text>ISBN:{{ row.isbn }}</el-text></div>
-                        <div class="base-info-btns flex">
-                            <el-button size="small" color="#4f4f4f" v-if="row.bookStatus != 3"
-                                @click="handleBlackList([row.isbn])">加入黑名单</el-button>
-                            <el-button size="small" color="#4f4f4f" v-if="row.bookStatus == 3">已在黑名单</el-button>
+  <ele-data-table
+    row-key="userId"
+    :columns="columns"
+    :data="dataList"
+    border
+    class="order-books"
+    :span-method="handleSpanMethod"
+  >
+    <template #baseInfo="{ row }">
+      <div class="base-info flex justify-between">
+        <div class="base-info-left flex flex-1">
+          <el-image
+            style="min-width: 80px; width: 80px; height: 100px"
+            fit="cover"
+            :src="row.cover"
+          />
+          <div class="base-info-left-con flex flex-col items-start ml-3">
+            <div
+              ><el-text type="primary" style="cursor: pointer" @click="handleBooksEdit(row)">{{
+                row.bookName
+              }}</el-text></div
+            >
+            <div
+              ><el-text>ISBN:{{ row.isbn }}</el-text></div
+            >
+            <div class="base-info-btns flex">
+              <el-button
+                size="small"
+                color="#4f4f4f"
+                v-if="row.bookStatus != 3"
+                @click="handleBlackList([row.isbn])"
+                >加入黑名单</el-button
+              >
+              <el-button size="small" color="#4f4f4f" v-if="row.bookStatus == 3"
+                >已在黑名单</el-button
+              >
 
-                            <el-button size="small" type="success" v-if="row.bookStatus == 1"
-                                @click="handleAddBookList(row)">加入回收书单</el-button>
-                            <el-button size="small" color="#2d430a" v-if="row.bookStatus == 2">已在回收书单</el-button>
+              <el-button
+                size="small"
+                type="success"
+                v-if="row.bookStatus == 1"
+                @click="handleAddBookList(row)"
+                >加入回收书单</el-button
+              >
+              <el-button size="small" color="#2d430a" v-if="row.bookStatus == 2"
+                >已在回收书单</el-button
+              >
 
-                            <el-button size="small" type="warning" v-if="row.settingStatus == 0"
-                                @click="handleSpecifiedDiscount(row)">指定回收折扣</el-button>
-                            <el-button size="small" color="#7728f5" v-if="row.settingStatus == 1"
-                                @click="handleModifyDiscount(row)">修改回收折扣</el-button>
-                        </div>
-                        <div><el-text type="danger">(已回收数量:{{ row.recycleNum }}当前库存:{{
-                            row.stockNum
-                                }})</el-text></div>
-                    </div>
-                </div>
-                <div class="base-info-right w-36 shrink-0">
-                    <div class="common-text flex">
-                        <el-text>定  价:</el-text>
-                        <el-text>¥ {{ row.bookPrice }}</el-text>
-                    </div>
-                    <div class="common-text flex">
-                        <el-text>回收折扣:</el-text>
-                        <el-text>¥ {{ row.recycleDiscount }}折</el-text>
-                    </div>
-                    <div class="common-text flex">
-                        <el-text>预估金额:</el-text>
-                        <el-text>¥ {{ row.recyclePrice }}</el-text>
-                    </div>
-                    <div class="common-text flex">
-                        <el-text>销售价格:</el-text>
-                        <el-text>¥ {{ row.salePrice || '-' }}</el-text>
-                    </div>
-                </div>
+              <el-button
+                size="small"
+                type="warning"
+                v-if="row.settingStatus == 0"
+                @click="handleSpecifiedDiscount(row)"
+                >指定回收折扣</el-button
+              >
+              <el-button
+                size="small"
+                color="#7728f5"
+                v-if="row.settingStatus == 1"
+                @click="handleModifyDiscount(row)"
+                >修改回收折扣</el-button
+              >
             </div>
-        </template>
-        <template #action="{ row }">
-            <div class="action-btns">
-                <el-button class="mb-10" color="#4f4f4f" @click="">审核图片</el-button>
-                <el-button class="mb-10" color="#a4adb3" @click="handleViewUrl(row, 'dd')">查看当当</el-button>
-                <el-button class="mb-10" color="#e99d42" @click="handleRecycleLog(row)">回收日志</el-button>
-                <el-button class="mb-10" color="#f27606" @click="handleViewUrl(row, 'tb')">查看淘宝</el-button>
-                <el-button color="#0f7dc7" @click="handleSalesLog(row)">售价日志</el-button>
-                <el-button color="#399420" @click="handleViewUrl(row, 'db')">查看豆瓣</el-button>
-            </div>
-        </template>
-        <template #auditInfo="{ row }">
-            <div class="audit-info flex justify-center">
-                <el-radio-group v-model="row.sts" style="width: 120px"
-                    :disabled="!(detail.status == 8 || detail.status == 9)"
-                    @change="(value) => handleAuditInfo(value, row)">
-                    <el-radio :value="1">品相良好</el-radio>
-                    <el-radio :value="2" disabled>品相一般</el-radio>
-                    <el-radio :value="3">品相极差</el-radio>
-                </el-radio-group>
+            <div
+              ><el-text type="danger"
+                >(已回收数量:{{ row.recycleNum }}当前库存:{{
+                  row.stockNum
+                }})</el-text
+              ></div
+            >
+          </div>
+        </div>
+        <div class="base-info-right w-36 shrink-0">
+          <div class="common-text flex">
+            <el-text>定  价:</el-text>
+            <el-text>¥ {{ row.bookPrice }}</el-text>
+          </div>
+          <div class="common-text flex">
+            <el-text>回收折扣:</el-text>
+            <el-text>¥ {{ row.recycleDiscount }}折</el-text>
+          </div>
+          <div class="common-text flex">
+            <el-text>预估金额:</el-text>
+            <el-text>¥ {{ row.recyclePrice }}</el-text>
+          </div>
+          <div class="common-text flex">
+            <el-text>销售价格:</el-text>
+            <el-text>¥ {{ row.salePrice || '-' }}</el-text>
+          </div>
+        </div>
+      </div>
+    </template>
+    <template #action="{ row }">
+      <div class="action-btns">
+        <el-button class="mb-10" color="#4f4f4f" @click="">审核图片</el-button>
+        <el-button
+          class="mb-10"
+          color="#a4adb3"
+          @click="handleViewUrl(row, 'dd')"
+          >查看当当</el-button
+        >
+        <el-button class="mb-10" color="#e99d42" @click="handleRecycleLog(row)"
+          >回收日志</el-button
+        >
+        <el-button
+          class="mb-10"
+          color="#f27606"
+          @click="handleViewUrl(row, 'tb')"
+          >查看淘宝</el-button
+        >
+        <el-button color="#0f7dc7" @click="handleSalesLog(row)"
+          >售价日志</el-button
+        >
+        <el-button color="#399420" @click="handleViewUrl(row, 'db')"
+          >查看豆瓣</el-button
+        >
+      </div>
+    </template>
+    <template #auditInfo="{ row }">
+      <div class="audit-info flex justify-center">
+        <el-radio-group
+          v-model="row.sts"
+          style="width: 120px"
+          :disabled="!(detail.status == 8 || detail.status == 9)"
+          @change="(value) => handleAuditInfo(value, row)"
+        >
+          <el-radio :value="1">品相良好</el-radio>
+          <el-radio :value="2" disabled>品相一般</el-radio>
+          <el-radio :value="3">品相极差</el-radio>
+        </el-radio-group>
 
-                <el-select v-model="row.com" style="width: 180px" placeholder="请选择品相极差的原因" multiple
-                    :disabled="!(detail.status == 8 || detail.status == 9) || row.sts !== 3" class="reason-select"
-                    @change="(value) => handleSelectReason(value, row)">
-                    <el-option v-for="item in auditReason" :key="item.dictValue" :label="item.dictValue"
-                        :value="item.dictValue" />
-                </el-select>
-            </div>
-        </template>
-    </ele-data-table>
-    <orderModifyDiscount ref="specifiedRef" @refresh="handleRefresh('specified')" />
-    <setParams ref="modifyRef" @refresh="handleRefresh('modify')" />
-    <orderBlacklist ref="blacklistRef" @refresh="handleRefresh('blacklist')" />
-    <orderRecycleLog ref="recycleLogRef" />
-    <orderSalesLog ref="salesLogRef" />
+        <el-select
+          v-model="row.com"
+          style="width: 180px"
+          placeholder="请选择品相极差的原因"
+          multiple
+          :disabled="
+            !(detail.status == 8 || detail.status == 9) || row.sts !== 3
+          "
+          class="reason-select"
+          @change="(value) => handleSelectReason(value, row)"
+        >
+          <el-option
+            v-for="item in auditReason"
+            :key="item.dictValue"
+            :label="item.dictValue"
+            :value="item.dictValue"
+          />
+        </el-select>
+      </div>
+    </template>
+  </ele-data-table>
+  <orderModifyDiscount
+    ref="specifiedRef"
+    @refresh="handleRefresh('specified')"
+  />
+  <setParams ref="modifyRef" @refresh="handleRefresh('modify')" />
+  <orderBlacklist ref="blacklistRef" @refresh="handleRefresh('blacklist')" />
+  <orderRecycleLog ref="recycleLogRef" />
+  <orderSalesLog ref="salesLogRef" />
+  <booksEdit ref="booksEditRef" />
 </template>
 
 <script setup>
-import { ref, reactive, watch, nextTick, onMounted } from 'vue';
-import orderModifyDiscount from '@/views/recycle/components/modify-discount.vue';
-import orderBlacklist from '@/views/recycleOrder/detail/order-blacklist.vue';
-import orderRecycleLog from '@/views/recycleOrder/detail/order-recycle-log.vue';
-import orderSalesLog from '@/views/recycleOrder/detail/order-sales-log.vue';
-import setParams from '@/views/recycle/components/set-params.vue';
-import request from '@/utils/request';
+  import { ref, reactive, watch, nextTick, onMounted } from 'vue';
+  import orderModifyDiscount from '@/views/recycle/components/modify-discount.vue';
+  import orderBlacklist from '@/views/recycleOrder/detail/order-blacklist.vue';
+  import orderRecycleLog from '@/views/recycleOrder/detail/order-recycle-log.vue';
+  import orderSalesLog from '@/views/recycleOrder/detail/order-sales-log.vue';
+  import setParams from '@/views/recycle/components/set-params.vue';
+  import BooksEdit from '@/views/data/books/components/books-edit.vue';
+  import request from '@/utils/request';
 
-const props = defineProps({
+  const props = defineProps({
     detail: {
-        type: Object,
-        default: () => ({
-            detailVoList: []
-        })
+      type: Object,
+      default: () => ({
+        detailVoList: []
+      })
     },
     isExpand: {
-        type: Boolean,
-        default: false
+      type: Boolean,
+      default: false
     }
-});
-const dataList = ref([]);
+  });
+  const dataList = ref([]);
+
+  const booksEditRef = ref();
+  function handleBooksEdit(row) {
+    row.id = row.bookId;
+    booksEditRef.value?.handleOpen(row);
+  }
 
-// 处理detailVoList数据
-const processDetailList = (list) => {
+  // 处理detailVoList数据
+  const processDetailList = (list) => {
     if (!list) return [];
     const result = [];
     let currentIndex = 0;
-    list.forEach(item => {
-        let auditInfo = item.auditCommentList
-        // 根据num拆分对象
-        for (let i = 0; i < item.num; i++) {
-            let audit = auditInfo ? auditInfo[i] ? auditInfo[i] : { sts: 0, com: [] } : { sts: 0, com: [] }
-            // 如果com存在且包含逗号,则分割为数组
-            if (audit.com && typeof audit.com === 'string') {
-                audit.com = audit.com.split(',').filter(Boolean);
-            } else if (!Array.isArray(audit.com)) {
-                audit.com = [];
-            }
-            result.push({
-                ...item,
-                ...audit,
-                _index: i,
-                _groupIndex: currentIndex,
-                _isFirstRow: i === 0
-            });
+    list.forEach((item) => {
+      let auditInfo = item.auditCommentList;
+      // 根据num拆分对象
+      for (let i = 0; i < item.num; i++) {
+        let audit = auditInfo
+          ? auditInfo[i]
+            ? auditInfo[i]
+            : { sts: 0, com: [] }
+          : { sts: 0, com: [] };
+        // 如果com存在且包含逗号,则分割为数组
+        if (audit.com && typeof audit.com === 'string') {
+          audit.com = audit.com.split(',').filter(Boolean);
+        } else if (!Array.isArray(audit.com)) {
+          audit.com = [];
         }
-        currentIndex++;
+        result.push({
+          ...item,
+          ...audit,
+          _index: i,
+          _groupIndex: currentIndex,
+          _isFirstRow: i === 0
+        });
+      }
+      currentIndex++;
     });
     return result;
-};
+  };
 
-// 初始化数据
-const initData = () => {
+  // 初始化数据
+  const initData = () => {
     const list = props.detail.detailVoList || [];
     console.log('Initializing data with list:', list);
 
     if (props.isExpand) {
-        dataList.value = processDetailList(list);
+      dataList.value = processDetailList(list);
     } else {
-        const processedList = [];
-        list.forEach(item => {
-            processedList.push({
-                ...item,
-                _index: 0,
-                _groupIndex: processedList.length,
-                _isFirstRow: true,
-                sts: item.auditCommentList && item.auditCommentList[0] ? item.auditCommentList[0].sts : 0,
-                com: item.auditCommentList && item.auditCommentList[0] && item.auditCommentList[0].com ?
-                    (typeof item.auditCommentList[0].com === 'string' ?
-                        item.auditCommentList[0].com.split(',').filter(Boolean) :
-                        item.auditCommentList[0].com) :
-                    []
-            });
+      const processedList = [];
+      list.forEach((item) => {
+        processedList.push({
+          ...item,
+          _index: 0,
+          _groupIndex: processedList.length,
+          _isFirstRow: true,
+          sts:
+            item.auditCommentList && item.auditCommentList[0]
+              ? item.auditCommentList[0].sts
+              : 0,
+          com:
+            item.auditCommentList &&
+            item.auditCommentList[0] &&
+            item.auditCommentList[0].com
+              ? typeof item.auditCommentList[0].com === 'string'
+                ? item.auditCommentList[0].com.split(',').filter(Boolean)
+                : item.auditCommentList[0].com
+              : []
         });
-        dataList.value = processedList;
+      });
+      dataList.value = processedList;
     }
 
     console.log('Initialized dataList:', dataList.value);
-};
+  };
 
-// 组件挂载时初始化数据
-onMounted(() => {
+  // 组件挂载时初始化数据
+  onMounted(() => {
     initData();
-});
+  });
 
-// 添加对detail.detailVoList的监听,确保弹窗打开时数据能正确显示
-watch(() => props.detail.detailVoList, (newVal) => {
-    if (!newVal) return;
-    console.log('detail.detailVoList changed:', newVal);
-    initData();
-}, { immediate: true, deep: true });
+  // 添加对detail.detailVoList的监听,确保弹窗打开时数据能正确显示
+  watch(
+    () => props.detail.detailVoList,
+    (newVal) => {
+      if (!newVal) return;
+      console.log('detail.detailVoList changed:', newVal);
+      initData();
+    },
+    { immediate: true, deep: true }
+  );
 
-watch(() => props.isExpand, (newVal) => {
-    console.log('isExpand changed:', newVal);
-    initData();
-}, { deep: true, immediate: true });
+  watch(
+    () => props.isExpand,
+    (newVal) => {
+      console.log('isExpand changed:', newVal);
+      initData();
+    },
+    { deep: true, immediate: true }
+  );
 
-// 处理单元格合并
-const handleSpanMethod = ({ row, column, rowIndex }) => {
+  // 处理单元格合并
+  const handleSpanMethod = ({ row, column, rowIndex }) => {
     if (column.property === 'num') {
-        // 确保行有必要的属性
-        if (!row._groupIndex && row._groupIndex !== 0) {
-            return {
-                rowspan: 1,
-                colspan: 1
-            };
-        }
+      // 确保行有必要的属性
+      if (!row._groupIndex && row._groupIndex !== 0) {
+        return {
+          rowspan: 1,
+          colspan: 1
+        };
+      }
 
-        // 找到当前行所在组的所有行
-        const currentGroup = dataList.value.filter(item => item._groupIndex === row._groupIndex);
-        if (row._isFirstRow) {
-            // 如果是组内第一行,设置合并行数
-            return {
-                rowspan: currentGroup.length,
-                colspan: 1
-            };
-        } else {
-            // 组内其他行不显示
-            return {
-                rowspan: 0,
-                colspan: 0
-            };
-        }
+      // 找到当前行所在组的所有行
+      const currentGroup = dataList.value.filter(
+        (item) => item._groupIndex === row._groupIndex
+      );
+      if (row._isFirstRow) {
+        // 如果是组内第一行,设置合并行数
+        return {
+          rowspan: currentGroup.length,
+          colspan: 1
+        };
+      } else {
+        // 组内其他行不显示
+        return {
+          rowspan: 0,
+          colspan: 0
+        };
+      }
     }
     return {
-        rowspan: 1,
-        colspan: 1
+      rowspan: 1,
+      colspan: 1
     };
-};
-//审核书籍
-function handleAudit(row) {
+  };
+  //审核书籍
+  function handleAudit(row) {
     const payload = {
-        orderId: props.detail.orderId,
-        isbn: row.isbn,
-        inx: row._index,
-        sts: row.sts,
-        com: Array.isArray(row.com) ? row.com.join(',') : ''
+      orderId: props.detail.orderId,
+      isbn: row.isbn,
+      inx: row._index,
+      sts: row.sts,
+      com: Array.isArray(row.com) ? row.com.join(',') : ''
     };
 
     request.post('/order/orderInfo/adminCheckOrder', payload).then((res) => {
-        if (res.data.code == 200) {
-            ElMessage.success('操作成功');
-        } else {
-            ElMessage.error(res.data.msg)
-        }
+      if (res.data.code == 200) {
+        ElMessage.success('操作成功');
+      } else {
+        ElMessage.error(res.data.msg);
+      }
     });
-}
+  }
 
-//其余审核良好 列表中sts为0的设置为1,并提交
-function handleOtherAuditGood() {
+  //其余审核良好 列表中sts为0的设置为1,并提交
+  function handleOtherAuditGood() {
     let stsList = [];
-    dataList.value.forEach(item => {
-        if (item.sts == 0) {
-            item.sts = 1;
-            stsList.push({
-                orderId: props.detail.orderId,
-                isbn: item.isbn,
-                sts: 1,
-                com: '',
-                inx: item._index
-            });
-        }
+    dataList.value.forEach((item) => {
+      if (item.sts == 0) {
+        item.sts = 1;
+        stsList.push({
+          orderId: props.detail.orderId,
+          isbn: item.isbn,
+          sts: 1,
+          com: '',
+          inx: item._index
+        });
+      }
     });
     let data = {
-        orderIds: [props.detail.orderId],
-        checkType: 2
-    }
+      orderIds: [props.detail.orderId],
+      checkType: 2
+    };
     //后端接口批量审核
     request.post('/order/orderInfo/adminCheckBatch', data).then((res) => {
-        if (res.data.code == 200) {
-            ElMessage.success('操作成功');
-            emit('close');
-        } else {
-            ElMessage.error(res.data.msg)
-        }
+      if (res.data.code == 200) {
+        ElMessage.success('操作成功');
+        emit('close');
+      } else {
+        ElMessage.error(res.data.msg);
+      }
     });
-}
+  }
 
-//单选框选择变化
-function handleAuditInfo(value, row) {
+  //单选框选择变化
+  function handleAuditInfo(value, row) {
     if (value == 1) {
-        row.com = [];
-        nextTick(() => {
-            handleAudit(row);
-        });
+      row.com = [];
+      nextTick(() => {
+        handleAudit(row);
+      });
     } else if (value == 3 && row.com.length > 0) {
-        nextTick(() => {
-            handleAudit(row);
-        });
+      nextTick(() => {
+        handleAudit(row);
+      });
     }
-}
-//选择审核原因
-function handleSelectReason(value, row) {
+  }
+  //选择审核原因
+  function handleSelectReason(value, row) {
     if (row.sts == 3) {
-        row.com = value;
-        nextTick(() => {
-            handleAudit(row);
-        });
+      row.com = value;
+      nextTick(() => {
+        handleAudit(row);
+      });
     }
-}
+  }
 
-const emit = defineEmits(['update:detail', 'refresh', 'close']);
+  const emit = defineEmits(['update:detail', 'refresh', 'close']);
 
-const columns = ref([
+  const columns = ref([
     {
-        type: 'index',
-        columnKey: 'index',
-        width: 60,
-        align: 'center'
+      type: 'index',
+      columnKey: 'index',
+      width: 60,
+      align: 'center'
     },
     {
-        label: '信息',
-        prop: 'baseInfo',
-        slot: 'baseInfo',
-        minWidth: 560,
-        align: 'center'
+      label: '信息',
+      prop: 'baseInfo',
+      slot: 'baseInfo',
+      minWidth: 560,
+      align: 'center'
     },
     {
-        label: '操作',
-        prop: 'action',
-        slot: 'action',
-        width: 220,
-        align: 'center'
+      label: '操作',
+      prop: 'action',
+      slot: 'action',
+      width: 220,
+      align: 'center'
     },
     {
-        label: '数量',
-        prop: 'num',
-        minWidth: 90,
-        align: 'center',
-        formatter: (row) => {
-            return `× ${row.num}`;
-        }
+      label: '数量',
+      prop: 'num',
+      minWidth: 90,
+      align: 'center',
+      formatter: (row) => {
+        return `× ${row.num}`;
+      }
     },
     {
-        label: '审核信息',
-        prop: 'auditInfo',
-        slot: 'auditInfo',
-        align: 'center',
-        minWidth: 317
+      label: '审核信息',
+      prop: 'auditInfo',
+      slot: 'auditInfo',
+      align: 'center',
+      minWidth: 317
     },
     {
-        label: '审核金额',
-        prop: 'recyclePrice',
-        align: 'center',
-        minWidth: 100,
-        formatter: (row) => {
-            return row.sts == 1 ? `¥ ${row.recyclePrice}` : '0';
-        }
+      label: '审核金额',
+      prop: 'recyclePrice',
+      align: 'center',
+      minWidth: 100,
+      formatter: (row) => {
+        return row.sts == 1 ? `¥ ${row.recyclePrice}` : '0';
+      }
     }
-]);
-//获取审核原因的字典 book_audit_reason
-const auditReason = ref([]);
-const getAuditReason = async () => {
+  ]);
+  //获取审核原因的字典 book_audit_reason
+  const auditReason = ref([]);
+  const getAuditReason = async () => {
     const res = await request.get('/system/dict/data/type/book_audit_reason');
     auditReason.value = res.data.data;
-    console.log(res, 'xxxx')
-};
-getAuditReason();
-
+    console.log(res, 'xxxx');
+  };
+  getAuditReason();
 
-//查看当当、淘宝、豆瓣链接
-const handleViewUrl = (row, type) => {
+  //查看当当、淘宝、豆瓣链接
+  const handleViewUrl = (row, type) => {
     let url = '';
     if (type == 'dd') {
-        url = `https://search.dangdang.com/?key=${row.isbn}&act=input`;
+      url = `https://search.dangdang.com/?key=${row.isbn}&act=input`;
     } else if (type == 'tb') {
-        url = `https://s.taobao.com/search?page=1&q=${row.isbn}&sort=sale-desc&tab=all`;
+      url = `https://s.taobao.com/search?page=1&q=${row.isbn}&sort=sale-desc&tab=all`;
     } else if (type == 'db') {
-        url = `https://search.douban.com/book/subject_search?search_text=${row.isbn}`;
+      url = `https://search.douban.com/book/subject_search?search_text=${row.isbn}`;
     } else if (type == 'kw') {
-        url = `https://search.kongfz.com/product_result/?key=${row.isbn}&status=0&_stpmt=eyJzZWFyY2hfdHlwZSI6ImFjdGl2ZSJ9`;
+      url = `https://search.kongfz.com/product_result/?key=${row.isbn}&status=0&_stpmt=eyJzZWFyY2hfdHlwZSI6ImFjdGl2ZSJ9`;
     }
     window.open(url, '_blank');
-};
-//加入回收书单
-const handleAddBookList = (row) => {
+  };
+  //加入回收书单
+  const handleAddBookList = (row) => {
     ElMessageBox.confirm('确认加入回收书单?', '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '关闭',
-        type: 'warning'
+      confirmButtonText: '确定',
+      cancelButtonText: '关闭',
+      type: 'warning'
     }).then(() => {
-        request.post('/book/bookRecycleInfo/addIn', {
-            isbnList: [row.isbn]
-        }).then(() => {
-            ElMessage.success('操作成功');
-            // 更新列表数据
-            const index = props.detail.detailVoList.findIndex(item => item.isbn === row.isbn);
-            if (index > -1) {
-                const newList = [...props.detail.detailVoList];
-                newList[index] = { ...newList[index], bookStatus: 2 };
-                dataList.value = newList;
-            }
+      request
+        .post('/book/bookRecycleInfo/addIn', {
+          isbnList: [row.isbn]
+        })
+        .then(() => {
+          ElMessage.success('操作成功');
+          // 更新列表数据
+          const index = props.detail.detailVoList.findIndex(
+            (item) => item.isbn === row.isbn
+          );
+          if (index > -1) {
+            const newList = [...props.detail.detailVoList];
+            newList[index] = { ...newList[index], bookStatus: 2 };
+            dataList.value = newList;
+          }
         });
     });
-};
-const currentRow = ref(null);
-//修改回收折扣
-const modifyRef = ref();
-const handleModifyDiscount = (row) => {
+  };
+  const currentRow = ref(null);
+  //修改回收折扣
+  const modifyRef = ref();
+  const handleModifyDiscount = (row) => {
     currentRow.value = row;
     modifyRef.value?.handleOpen(row);
-};
-//指定回收折扣
-const specifiedRef = ref();
-const handleSpecifiedDiscount = (row) => {
+  };
+  //指定回收折扣
+  const specifiedRef = ref();
+  const handleSpecifiedDiscount = (row) => {
     currentRow.value = row;
     specifiedRef.value?.handleOpen(row);
-};
-//加入黑名单
-const blacklistRef = ref();
-const handleBlackList = (row) => {
+  };
+  //加入黑名单
+  const blacklistRef = ref();
+  const handleBlackList = (row) => {
     currentRow.value = row;
     blacklistRef.value?.handleOpen(row);
-};
-//查看回收日志
-const recycleLogRef = ref();
-const handleRecycleLog = (row) => {
+  };
+  //查看回收日志
+  const recycleLogRef = ref();
+  const handleRecycleLog = (row) => {
     recycleLogRef.value?.handleOpen(row);
-};
-//查看售价日志
-const salesLogRef = ref();
-const handleSalesLog = (row) => {
+  };
+  //查看售价日志
+  const salesLogRef = ref();
+  const handleSalesLog = (row) => {
     salesLogRef.value?.handleOpen(row);
-};
+  };
 
-const handleRefresh = (type) => {
+  const handleRefresh = (type) => {
     if (!currentRow.value) return;
-    const index = dataList.value.findIndex(item => item.isbn === currentRow.value.isbn);
+    const index = dataList.value.findIndex(
+      (item) => item.isbn === currentRow.value.isbn
+    );
     if (index > -1) {
-        const newList = [...dataList.value];
-        if (type === 'specified' || type === 'modify') {
-            newList[index] = { ...newList[index], settingStatus: 1 };
-        } else if (type === 'blacklist') {
-            newList[index] = { ...newList[index], bookStatus: 3 };
-        }
-        dataList.value = newList;
+      const newList = [...dataList.value];
+      if (type === 'specified' || type === 'modify') {
+        newList[index] = { ...newList[index], settingStatus: 1 };
+      } else if (type === 'blacklist') {
+        newList[index] = { ...newList[index], bookStatus: 3 };
+      }
+      dataList.value = newList;
     }
-};
+  };
 
-// 手动刷新数据
-const refreshData = () => {
+  // 手动刷新数据
+  const refreshData = () => {
     console.log('Manual refresh triggered');
     initData();
-};
+  };
 
-defineExpose({
+  defineExpose({
     handleOtherAuditGood,
     refreshData
-});
+  });
 </script>
 
 <style lang="scss" scoped>
-.mb-10 {
+  .mb-10 {
     margin-bottom: 7px;
-}
+  }
 
-.reason-select {
+  .reason-select {
     :deep(.el-select__wrapper) {
-        height: 120px !important;
+      height: 120px !important;
     }
 
     :deep(.el-select__placeholder) {
-        top: 0;
-        text-wrap: wrap;
-        white-space: normal;
-        text-overflow: initial;
+      top: 0;
+      text-wrap: wrap;
+      white-space: normal;
+      text-overflow: initial;
     }
-}
+  }
 
-.order-books {
+  .order-books {
     .action-btns {
-        display: flex;
-        flex-wrap: wrap;
-        gap: 10px;
+      display: flex;
+      flex-wrap: wrap;
+      gap: 10px;
 
-        .el-button {
-            margin: 0;
-            color: #fff;
-        }
+      .el-button {
+        margin: 0;
+        color: #fff;
+      }
     }
 
     // 处理合并单元格效果
     .el-table {
-        td.el-table__cell {
-            &.first-row {
-                border-bottom: none;
-            }
+      td.el-table__cell {
+        &.first-row {
+          border-bottom: none;
         }
+      }
     }
-}
+  }
 </style>

+ 1 - 1
src/views/recycleOrder/detail/order-status.vue

@@ -29,7 +29,7 @@
     { statusName: '快递取书', createTime: '', createName: '', stutus: '5' },
     { statusName: '快递签收', createTime: '', createName: '', stutus: '6' },
     { statusName: '仓库收货', createTime: '', createName: '', stutus: '8' },
-    { statusName: '到货审核', createTime: '', createName: '', stutus: '9' },
+    { statusName: '到货审核', createTime: '', createName: '', stutus: '10' },
     {
       statusName: '支付书款(完成)',
       createTime: '',

+ 2 - 2
src/views/recycleOrder/needReturned/index.vue

@@ -145,6 +145,7 @@
   import manualDelivery from '@/views/recycleOrder/components/manual-delivery.vue';
   //订单详情
   import orderRefundDetail from '@/views/recycleOrder/needReturned/order-refund-detail.vue';
+  const status = ref('');
 
   let props = defineProps({
     pageConfig: {
@@ -163,7 +164,6 @@
   /** 表格实例 */
   const tableRef = ref(null);
 
-  const status = ref('');
   function handleStatusChange(val) {
     reload({ status: val });
   }
@@ -230,7 +230,7 @@
 
   /** 搜索 */
   const reload = (where) => {
-    tableRef.value?.reload?.({ page: 1, where });
+    tableRef.value?.reload?.({ page: 1, where: { ...where, status: status.value } });
   };
 
   //订单详情

+ 1 - 1
src/views/recycleOrder/needReturned/refund-detail.vue

@@ -31,7 +31,7 @@
     <ele-card class="order-service" header="订单服务">
       <el-tag size="large" style="margin-right: 20px">免费退回</el-tag>
       <el-tag size="large" style="margin-right: 20px">24小时验</el-tag>
-      <el-tag size="large">速打款</el-tag>
+      <el-tag size="large">速打款</el-tag>
     </ele-card>
 
     <ele-card class="order-note" header="审核计价说明">

+ 8 - 1
src/views/recycleOrder/needReturned/return-search.vue

@@ -40,7 +40,14 @@
       prop: 'firstOrder',
       span: 4,
       tagAttrs: { code: 'is_first_order', type: 'select' }
-    }
+    },
+    // {
+    //   tag: 'dict-data',
+    //   label: '是否推送',
+    //   prop: 'isPush',
+    //   span: 4,
+    //   tagAttrs: { code: 'is_push', type: 'select' }
+    // }
   ]);
 
   const initKeys = {};

+ 4 - 4
src/views/recycleService/stockIn/components/stock-in-search.vue

@@ -42,13 +42,13 @@ const formItems = computed(() => {
         { type: 'input', label: '入库库位', prop: 'positionCode' },
         { type: 'input', label: '物流单号', prop: 'waybillCode' },
         { type: 'input', label: '订单编号', prop: 'orderId' },
-        { type: 'input', label: '入库单号', prop: 'inputCode' },
+        { type: 'input', label: '入库单号', prop: 'stockCode' },
         {
             type: 'select',
             label: '操作员',
             prop: 'userId',
             options: userList.value.map((item) => ({
-                label: item.nickName,
+                label: item.userName,
                 value: item.userId
             })),
             props: {
@@ -62,7 +62,7 @@ const formItems = computed(() => {
                 }
             }
         },
-        { type: 'input', label: '入库备注', prop: 'inputRemark' },
+        { type: 'input', label: '入库备注', prop: ' remark' },
         {
             type: 'datetimerange',
             label: '入库时间',
@@ -101,4 +101,4 @@ const searchRef = ref(null);
 const search = (data) => {
     emit('search', { ...data });
 };
-</script> 
+</script>

+ 1 - 1
src/views/recycleService/stockOut/components/stock-out-search.vue

@@ -47,7 +47,7 @@ const formItems = computed(() => {
             label: '操作员',
             prop: 'userId',
             options: userList.value.map((item) => ({
-                label: item.nickName,
+                label: item.userName,
                 value: item.userId
             })),
             props: {

+ 3 - 3
src/views/recycleService/stockOut/index.vue

@@ -31,11 +31,11 @@ const columns = ref([
     { label: '出库库位', prop: 'positionCode', align: 'center', minWidth: 120 },
     { label: '订单编号', prop: 'orderId', align: 'center', width: 176 },
     { label: '物流单号', prop: 'waybillCode', align: 'center', width: 146 },
-    { label: '退回物流', prop: 'returnLogistics', align: 'center', width: 120 },
+    { label: '退回物流', prop: 'refundWaybillCode', align: 'center', width: 120 },
     { label: '不良数量', prop: 'bookNum', align: 'center', width: 100 },
-    { label: '数量', prop: 'num', align: 'center' },
+    { label: '数量', prop: 'num', align: 'center', formatter: (row) => 1 },
     { label: '验收时间', prop: 'checkTime', align: 'center', formatter: (row) => dayjs(row.checkTime).format('YYYY-MM-DD HH:mm:ss'), width: 160 },
-    { label: '反馈', prop: 'outputRemark', align: 'center', minWidth: 200 },
+    { label: '反馈', prop: 'outputRemark', align: 'center', minWidth: 200, formatter: (row) => row.outputRemark || '--' },
     { label: '操作员', prop: 'outputName', align: 'center', width: 120 }
 ]);