Browse Source

Merge branch 'master' of http://39.105.58.247:3100/yidiandao/ydd_front

ZZ 3 weeks ago
parent
commit
a393b35e74

+ 104 - 0
mer_plat_admin/src/api/secondHand.js

@@ -152,4 +152,108 @@ export function secondHandCategoryBatchApi(data) {
     method: 'POST',
     data,
   });
+}
+
+/**
+ *获取退款订单各状态数量
+ */
+export function refundStatusNumApi(params) {
+  return request({
+    url: `/admin/platform/secondhand/refund/order/status/num`,
+    method: 'GET',
+    params,
+  });
+}
+/**
+ *退款列表
+ */
+export function refundListApi(params) {
+  return request({
+    url: `/admin/platform/secondhand/refund/order/list`,
+    method: 'get',
+    params,
+  });
+}
+/**
+ * 平台强制退款
+ * @param refundOrderNo
+ * @returns {*}
+ */
+export function orderRefundCompulsoryApi(refundOrderNo) {
+  return request({
+    url: `/admin/platform/secondhand/refund/order/compulsory/refund/${refundOrderNo}`,
+    method: 'post',
+  });
+}
+/**
+ *平台备注退款订单
+ */
+export function refundMarkApi(data) {
+  return request({
+    url: `/admin/platform/secondhand/refund/order/mark`,
+    method: 'post',
+    data,
+  });
+}
+/**
+ * 平台端退款订单详情
+ * @param refundOrderNo 订单号
+ */
+export function refundOrderDetailApi(refundOrderNo) {
+  return request({
+    url: `/admin/platform/secondhand/refund/order/detail/${refundOrderNo}`,
+    method: 'get',
+  });
+}
+/**
+ * 订单 列表 获取各状态数量
+ * @param params
+ */
+export function orderStatusNumApi(params) {
+  return request({
+    url: '/admin/platform/secondhand/order/status/num',
+    method: 'get',
+    params,
+  });
+}
+/**
+ * 订单 列表
+ * @param prams
+ */
+export function orderListApi(params) {
+  return request({
+    url: '/admin/platform/secondhand/order/list',
+    method: 'get',
+    params,
+  });
+}
+/**
+ * 订单 详情
+ * @param prams
+ */
+export function orderDetailApi(params) {
+  return request({
+    url: '/admin/platform/secondhand/order/info',
+    method: 'get',
+    params,
+  });
+}
+/**
+ * 获取订单发货单列表
+ * @param orderNo 订单号
+ */
+export function orderInvoiceListApi(orderNo) {
+  return request({
+    url: `/admin/platform/secondhand/order/${orderNo}/invoice/list`,
+    method: 'get',
+  });
+}
+/**
+ *平台端订单物流详情
+ */
+export function getLogisticsInfoApi(invoiceId) {
+  return request({
+    url: `/admin/platform/secondhand/order/get/${invoiceId}/logistics/info`,
+    method: 'get',
+  });
 }

+ 1 - 1
mer_plat_admin/src/components/OrderDetail/index.vue

@@ -43,7 +43,7 @@
               <ul class="list">
                 <li class="item">
                   <div class="lang">用户名称:</div>
-                  <div class="value">{{ orderDatalist.nikeName }} | {{ orderDatalist.uid }}</div>
+                  <div class="value">{{ orderDatalist.nickname }} | {{ orderDatalist.uid }}</div>
                 </li>
                 <li class="item">
                   <div class="lang">用户电话:</div>

+ 3 - 0
mer_plat_admin/src/router/index.js

@@ -28,6 +28,7 @@ import operationRouter from './modules/operation';
 import merchant from './modules/merchant';
 import pagediy from '@/router/modules/pagediy';
 import riderRouter from '@/router/modules/rider';
+import secondhandRouter from './modules/secondhand';
 
 /**
  * Note: sub-menu only appear when route children.length >= 1
@@ -78,6 +79,8 @@ export const constantRoutes = [
   pagediy,
   // 骑手
   riderRouter,
+  //二手交易
+  secondhandRouter,
 
   {
     path: '/404',

+ 1 - 13
mer_plat_admin/src/router/modules/order.js

@@ -32,19 +32,7 @@ const orderRouter = {
       component: () => import('@/views/order/refund'),
       name: 'refund',
       meta: { title: '退款单' },
-    },
-    {
-      path: 'fastMail',
-      component: () => import('@/views/order/fastMail'),
-      name: 'fastMail',
-      meta: { title: '快递订单' },
-    },
-    {
-      path: 'secondHand',
-      component: () => import('@/views/order/secondHand'),
-      name: 'secondHand',
-      meta: { title: '二手交易订单' },
-    },
+    }
   ],
 };
 

+ 111 - 0
mer_plat_admin/src/router/modules/secondhand.js

@@ -0,0 +1,111 @@
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+
+import Layout from '@/layout';
+
+const secondhandRouter = {
+ path: '/secondhand',
+ component: Layout,
+ redirect: '/secondhand/classify',
+ name: 'Secondhand',
+ meta: {
+   title: '二手交易',
+   icon: 'clipboard',
+ },
+ children: [
+	{
+	  path: 'order',
+	  name: 'order',
+	  meta: {
+	    title: '订单',
+	    noCache: true,
+	  },
+	  component: () => import('@/views/secondhand/order/index'),
+	  children: [
+	    {
+	      path: 'list',
+	      name: 'Orderlist',
+	      meta: {
+	        title: '订单列表',
+	        noCache: true,
+	      },
+	      component: () => import('@/views/secondhand/order/list'),
+	    },
+	    {
+	      path: 'refund',
+	      name: 'refund',
+	      meta: {
+	        title: '退款',
+	        noCache: true,
+	      },
+	      component: () => import('@/views/secondhand/order/refund'),
+	    }
+	  ],
+	}, 
+	{
+	 path: 'product',
+	 name: 'product',
+	 meta: {
+	   title: '商品',
+	   noCache: true,
+	 },
+	 component: () => import('@/views/secondhand/index'),
+	 children: [
+	   {
+	     path: 'classification',
+	     name: 'secondHandClassification',
+	     meta: {
+	      title: '商品分类',
+	       noCache: true,
+	     },
+	     component: () => import('@/views/secondhand/classification/index'),
+	   },
+	   {
+	     path: 'content',
+	     name: 'secondHandContent',
+	     meta: {
+	       title: '商品内容',
+	       noCache: true,
+	     },
+	     component: () => import('@/views/secondhand/content/index'),
+	   },
+	   {
+	     path: 'config',
+	     name: 'secondHandConfig',
+	     component: () => import('@/views/secondhand/config/index'),
+	     meta: {
+	       title: '内容配置',
+	       icon: 'clipboard',
+	     },
+	   },
+	 ],
+	},
+   // {
+   //   path: 'order',
+   //   name: 'RiderList',
+   //   component: () => import('@/views/secondhand/order/list'),
+   //   meta: { title: '订单列表', icon: '' },
+   // },
+   // {
+   //   path: 'application',
+   //   name: 'RiderApplication',
+   //   component: () => import('@/views/rider/application'),
+   //   meta: { title: '骑手入驻申请', icon: '' },
+   // },
+   // {
+   //   path: 'deliverySetting',
+   //   name: 'deliverySetting',
+   //   component: () => import('@/views/rider/deliverySetting'),
+   //   meta: { title: '配送费设置', icon: '' },
+   // }
+ ],
+};
+
+export default secondhandRouter;

+ 2 - 1
mer_plat_admin/src/store/modules/user.js

@@ -31,7 +31,8 @@ const state = {
     token: '',
   }, //滑块验证token
   // 菜单数据
-  menuList: JSON.parse(localStorage.getItem('MerPlatAdmin_MenuList')) || [],
+  //menuList: [],
+  menuList: localStorage.getItem('MerPlatAdmin_MenuList')!=null? JSON.parse(localStorage.getItem('MerPlatAdmin_MenuList')) : [],
   oneLvMenus: [],
   oneLvRoutes: JSON.parse(localStorage.getItem('MerPlatAdmin_oneLvRoutes')) || [],
   childMenuList: [],

+ 243 - 0
mer_plat_admin/src/views/secondhand/classification/index.vue

@@ -0,0 +1,243 @@
+<template>
+  <div class="divBox relative">
+    <el-card
+      v-hasPermi="['platform:secondHand:category:page:list']"
+      :bordered="false"
+      shadow="never"
+      class="ivu-mt"
+      :body-style="{ padding: 0 }"
+    >
+      <div class="padding-add">
+        <el-form :inline="true" @submit.native.prevent>
+          <el-form-item label="分类名称:">
+            <el-input
+              v-model.trim="name"
+              @keyup.enter.native="getList(1)"
+              placeholder="请输入分类名称"
+              class="selWidth"
+              size="small"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="显示状态:">
+            <el-select v-model="tableFrom.isShow" placeholder="请选择显示状态" size="small" class="selWidth" clearable>
+              <el-option label="显示" value="1"></el-option>
+              <el-option label="隐藏" value="0"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" size="small" @click="getList(1)">查询</el-button>
+            <el-button size="small" @click="reset()">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-card>
+    <el-card class="box-card mt14" :body-style="{ padding: '20px' }" :bordered="false" shadow="never">
+      <div class="acea-row">
+        <el-button
+          type="primary"
+          size="small"
+          v-hasPermi="['platform:secondHand:category:add']"
+          @click="handlerOpenEdit(0)"
+          >添加二手交易分类</el-button
+        >
+      </div>
+      <el-table v-loading="listLoading" :data="tableData.data" size="small" :highlight-current-row="true" class="mt20">
+        <el-table-column prop="id" label="ID" min-width="50" />
+        <el-table-column label="分类名称" prop="name" min-width="100" :show-overflow-tooltip="true"> </el-table-column>
+		<el-table-column label="分类图标" min-width="120">
+				  <template slot-scope="scope">
+				    <div class="demo-image__preview line-heightOne">
+				      <el-image :src="scope.row.icon" :preview-src-list="[scope.row.icon]" v-if="scope.row.icon" />
+				      <img v-else :src="defaultImg" alt="" />
+				    </div>
+				  </template>
+		</el-table-column>
+        <el-table-column prop="sort" label="排序" min-width="100" />
+        <el-table-column label="添加时间" min-width="120">
+          <template slot-scope="scope">
+            <span>{{ scope.row.createTime }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="是否开启" fixed="right" min-width="90">
+          <template slot-scope="scope">
+            <el-switch
+              v-if="checkPermi(['platform:secondHand:category:show:switch'])"
+              v-model="scope.row.isShow"
+              :active-value="1"
+              :inactive-value="0"
+              active-text="开启"
+              inactive-text="关闭"
+              @click.native="onchangeIsShow(scope.row)"
+            />
+            <div v-else>{{ scope.row.isShow ? '开启' : '关闭' }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="100" fixed="right">
+          <template slot-scope="scope">
+            <a @click="handlerOpenEdit(1, scope.row)" v-hasPermi="['platform:secondHand:category:update']">编辑</a>
+            <el-divider direction="vertical"></el-divider>
+            <a @click="handlerOpenDel(scope.row)" v-hasPermi="['platform:secondHand:category:delete']">删除</a>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="block">
+        <el-pagination
+          background
+          :page-sizes="[20, 40, 60, 80]"
+          :page-size="tableFrom.limit"
+          :current-page="tableFrom.page"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="tableData.total"
+          @size-change="handleSizeChange"
+          @current-change="pageChange"
+        />
+      </div>
+    </el-card>
+  </div>
+</template>
+<script>
+// +---------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +---------------------------------------------------------------------
+// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
+// +---------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +---------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +---------------------------------------------------------------------
+import * as secondHand from '@/api/secondHand';
+import { checkPermi } from '@/utils/permission'; // 权限判断函数
+export default {
+  data() {
+    return {
+      tableFrom: {
+        page: 1,
+        limit: 20,
+        name: '',
+        isShow: '',
+      },
+      name: '',
+      tableData: {
+        data: [],
+        total: 0,
+      },
+      listLoading: false,
+      keyNum: 0,
+      id: 0,
+	 defaultImg: require('@/assets/imgs/moren.jpg'),
+    };
+  },
+  mounted() {
+    if (checkPermi(['platform:secondHand:category:page:list'])) this.getList();
+  },
+  methods: {
+    checkPermi,
+    onchangeIsShow(row) {
+      secondHand.secondHandCategoryShowApi(row.id).then((res) => {
+        this.$message.success('操作成功');
+        this.getList();
+      });
+    },
+    // 列表
+    getList(num) {
+      this.tableFrom.page = num ? num : this.tableFrom.page;
+      this.tableFrom.name = encodeURIComponent(this.name);
+      this.listLoading = true;
+      secondHand
+        .secondHandCategoryListApi(this.tableFrom)
+        .then((res) => {
+          this.tableData.data = res.list;
+          this.tableData.total = res.total;
+          this.listLoading = false;
+        })
+        .catch((res) => {
+          this.listLoading = false;
+        });
+    },
+    reset() {
+      this.tableFrom.name = '';
+      this.tableFrom.isShow = '';
+      this.name = '';
+      this.getList(1);
+    },
+    pageChange(page) {
+      this.tableFrom.page = page;
+      this.getList();
+    },
+    handleSizeChange(val) {
+      this.tableFrom.limit = val;
+      this.getList(1);
+    },
+    handlerOpenEdit(isCreate, editDate) {
+      console.log(editDate)
+      const _this = this;
+      this.id = editDate ? editDate.id : 0;
+      this.$modalParserFrom(
+        isCreate === 0 ? '新建分类' : '编辑分类',
+        'communityClassification',
+        isCreate,
+        isCreate === 0
+          ? {
+              id: 0,
+              name: '',
+              handlingFee: '',
+            }
+          : Object.assign({}, editDate),
+        function (formValue) {
+          _this.submit(formValue);
+          _this.resetForm(formValue);
+        },
+        (this.keyNum += 1),
+      );
+    },
+    submit(formValue) {
+      const data = {
+        id: this.id,
+        name: formValue.name,
+        isShow: formValue.isShow,
+        sort: formValue.sort,
+		icon: formValue.icon,
+      };
+      !this.id
+        ? secondHand
+            .secondHandCategoryAddApi(data)
+            .then((res) => {
+              this.$message.success('操作成功');
+              this.$msgbox.close();
+              this.getList();
+            })
+            .catch(() => {
+              this.loading = false;
+            })
+        : secondHand
+            .secondHandCategoryUpdateApi(data)
+            .then((res) => {
+              this.$message.success('操作成功');
+              this.$msgbox.close();
+              this.getList();
+            })
+            .catch(() => {
+              this.loading = false;
+            });
+    },
+    handlerOpenDel(rowData) {
+      this.$modalSure(
+        '删除当前分类吗?删除之后,移动端页面分类筛选不展示此分类,移动端再次发表图文时,也不能够选择此分类。',
+      ).then(() => {
+        secondHand.secondHandCategoryDelApi(rowData.id).then((data) => {
+          this.$message.success('删除分类成功');
+          if (this.tableData.data.length === 1 && this.tableFrom.page > 1)
+            this.tableFrom.page = this.tableFrom.page - 1;
+          this.getList();
+        });
+      });
+    },
+  },
+};
+</script>
+<style>
+.alert_title {
+  margin-right: 10px;
+}
+</style>

+ 462 - 0
mer_plat_admin/src/views/secondhand/comments/index.vue

@@ -0,0 +1,462 @@
+<template>
+  <div class="divBox">
+    <el-card
+      v-hasPermi="['platform:community:reply:page:list']"
+      :bordered="false"
+      shadow="never"
+      class="ivu-mt"
+      :body-style="{ padding: 0 }"
+    >
+      <div class="padding-add">
+        <el-form :inline="true" label-position="right" @submit.native.prevent>
+          <el-form-item label="用户搜索:" label-for="nickname">
+            <UserSearchInput v-model="tableFrom" />
+          </el-form-item>
+          <el-form-item label="时间选择:">
+            <el-date-picker
+              @change="onchangeTime"
+              v-model="timeVal"
+              value-format="yyyy-MM-dd"
+              format="yyyy-MM-dd"
+              size="small"
+              type="daterange"
+              placement="bottom-end"
+              placeholder="自定义时间"
+              class="selWidth"
+            ></el-date-picker>
+          </el-form-item>
+          <el-form-item label="审核状态:">
+            <el-select
+              v-model="tableFrom.auditStatus"
+              placeholder="请选择"
+              size="small"
+              class="selWidth"
+              clearable
+              @change="getList(1)"
+            >
+              <el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="内容标题:">
+            <el-input
+              v-model.trim="title"
+              placeholder="请输入文章标题"
+              class="selWidth"
+              size="small"
+              @keyup.enter.native="getList(1)"
+              clearable
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="评论内容:">
+            <el-input
+              v-model.trim="keywords"
+              placeholder="请输入评论内容"
+              class="selWidth"
+              size="small"
+              clearable
+            ></el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" size="small" @click="getList(1)">查询</el-button>
+            <el-button size="small" @click="reset()">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-card>
+    <el-card class="box-card mt14" :body-style="{ padding: '20px' }" :bordered="false" shadow="never">
+      <el-table :data="tableData.data" size="small">
+        <el-table-column prop="id" label="ID" width="50" />
+        <el-table-column label="用户名/ID" min-width="150">
+          <template slot-scope="{ row }">
+            <span>{{ row.userNickname + ' / ' + row.uid }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="noteTitle" label="文章标题" min-width="120" :show-overflow-tooltip="true" />
+        <el-table-column prop="content" label="评论内容" min-width="150" :show-overflow-tooltip="true" />
+        <el-table-column prop="countReply" label="评论数" min-width="100" />
+        <el-table-column prop="countStart" label="点赞数" min-width="100" />
+        <el-table-column label="评论时间" min-width="150" prop="createTime" />
+        <el-table-column label="审核状态" min-width="100">
+          <template slot-scope="scope">
+            <span class="tag-background" :class="tagClass[scope.row.auditStatus]">{{
+              scope.row.auditStatus | communityStatusFilter
+            }}</span>
+            <span v-if="scope.row.auditStatus == 2" style="display: block; font-size: 12px; color: red"
+              >原因: {{ scope.row.refusal }}</span
+            >
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="150" fixed="right">
+          <template slot-scope="scope">
+            <a @click="onAudit(scope.row, 'info')">详情</a>
+            <el-divider direction="vertical"></el-divider>
+            <template v-if="scope.row.auditStatus === 0 && checkPermi(['platform:community:reply:audit'])">
+              <a @click="onAudit(scope.row, 'audit')">审核</a>
+              <el-divider direction="vertical"></el-divider>
+            </template>
+            <a @click="handleDelete(scope.row.id, scope.$index)" v-hasPermi="['platform:community:reply:delete']"
+              >删除</a
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="block">
+        <el-pagination
+          background
+          :page-sizes="[20, 40, 60, 80]"
+          :page-size="tableFrom.limit"
+          :current-page="tableFrom.page"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="tableData.total"
+          @size-change="handleSizeChange"
+          @current-change="pageChange"
+        />
+      </div>
+    </el-card>
+
+    <!--审核 详情-->
+    <el-drawer
+      custom-class="demo-drawer"
+      direction="rtl"
+      :visible.sync="dialogVisible"
+      size="1000px"
+      @close="onClose()"
+    >
+      <div class="detailHead">
+        <div class="acea-row row-between headerBox">
+          <div class="full">
+            <div class="order_icon"><span class="iconfont icon-daipingjia-2"></span></div>
+            <div class="text">
+              <div class="title">{{auditType === 'audit'? '评论审核':'评论详情'}}</div>
+              <div>
+                <span class="mr20">审核结果:{{ commentsInfo.auditStatus | communityStatusFilter }}</span>
+              </div>
+            </div>
+          </div>
+          <div v-if="auditType === 'audit'" class="acea-row justify-content">
+            <el-button
+              v-hasPermi="['platform:community:reply:audit']"
+              v-debounceClick="
+                () => {
+                  onAuditStatus(2);
+                }
+              "
+              style="margin-left: 0"
+              >{{ loadingBtn ? '提交中 ...' : '审核拒绝' }}</el-button
+            >
+            <el-button
+              type="primary"
+              v-hasPermi="['platform:community:reply:audit']"
+              v-debounceClick="
+                () => {
+                  onAuditStatus(1);
+                }
+              "
+              >{{ loadingBtnSuccess ? '提交中 ...' : '审核通过' }}</el-button
+            >
+          </div>
+        </div>
+      </div>
+      <div class="demo-drawer__content detailSection" v-loading="loading">
+        <ul class="list">
+          <li class="item">
+            <div class="lang">用户昵称:</div>
+            <div class="value">{{ commentsInfo.userNickname }}</div>
+          </li>
+          <li class="item">
+            <div class="tips">用户ID:</div>
+            <div class="value">{{ commentsInfo.uid }}</div>
+          </li>
+          <li class="item">
+            <div class="tips">评论类型:</div>
+            <div class="value">{{ commentsInfo.type === 1 ? '评论' : '回复' }}</div>
+          </li>
+          <li class="item">
+            <div class="lang">评论数:</div>
+            <div class="value">{{ commentsInfo.countReply }}</div>
+          </li>
+          <li class="item">
+            <div class="tips">点赞数:</div>
+            <div class="value">{{ commentsInfo.countStart }}</div>
+          </li>
+        </ul>
+        <div class="list" style="display: block">
+          <div class="item">
+            <div class="lang">内容:</div>
+            <div class="value">{{ commentsInfo.content }}</div>
+          </div>
+          <div v-show="commentsInfo.auditStatus === 2" class="item">
+            <div class="lang">审核失败原因:</div>
+            <div class="value">{{ commentsInfo.refusal }}</div>
+          </div>
+        </div>
+      </div>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+// +---------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +---------------------------------------------------------------------
+// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
+// +---------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +---------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +---------------------------------------------------------------------
+import { communityReplyListApi, communityReplyDelApi, communityReplyAuditApi } from '@/api/community';
+import { formatDates } from '@/utils/index';
+import { checkPermi } from '@/utils/permission';
+import { handleDeleteTable } from '@/libs/public'; // 权限判断函数
+export default {
+  name: 'StoreComment',
+  filters: {
+    formatDate(time) {
+      if (time !== 0) {
+        const date = new Date(time * 1000);
+        return formatDates(date, 'yyyy-MM-dd hh:mm');
+      }
+    },
+  },
+  data() {
+    return {
+      tagClass: ['doingTag', 'endTag', 'notStartTag'],
+      loadingBtn: false,
+      dialogVisible: false,
+      statusList: [
+        { label: '待审核', value: 0 },
+        { label: '已通过', value: 1 },
+        { label: '已拒绝', value: 2 },
+      ],
+      props: {
+        children: 'child',
+        label: 'name',
+        value: 'id',
+        emitPath: false,
+      },
+      fromList: this.$constants.fromList,
+      tableData: {
+        data: [],
+        total: 0,
+      },
+      listLoading: false,
+      tableFrom: {
+        page: 1,
+        limit: 20,
+        auditStatus: '',
+        dateLimit: '',
+        keywords: '',
+        userName: '',
+        title: '',
+        searchType: 'all',
+        content: '',
+      },
+      keywords: '',
+      title: '',
+      timeVal: [],
+      loading: false,
+      uids: [],
+      options: [],
+      timer: '',
+      commentsInfo: {},
+      //审核
+      auditStatusFrom: {
+        auditStatus: 1,
+        id: 0,
+        refusalReason: '',
+      },
+      id: 0,
+      loadingBtnSuccess: false, //审核成功通过
+      auditType: '', //详情还是审核
+    };
+  },
+  watch: {
+    $route(to, from) {
+      this.getList();
+    },
+  },
+  mounted() {
+    if (checkPermi(['platform:community:reply:page:list'])) this.getList();
+  },
+  methods: {
+    checkPermi,
+    onClose() {
+      this.dialogVisible = false;
+    },
+    //审核拒绝
+    cancelForm() {
+      this.$modalPrompt('textarea', '拒绝原因').then((V) => {
+        this.auditStatusFrom.refusalReason = V;
+        this.onAuditSubmit();
+      });
+    },
+    // 审核点击
+    onAuditStatus(type) {
+      this.auditStatusFrom.auditStatus = type;
+      if (type === 1) {
+        this.$modalSure('审核通过该内容吗?').then(() => {
+          this.onAuditSubmit();
+        });
+      } else {
+        this.cancelForm();
+      }
+    },
+    //审核提交
+    onAuditSubmit() {
+      this.auditStatusFrom.id = this.id;
+      if (this.auditStatusFrom.auditStatus === 1) {
+        this.loadingBtnSuccess = true;
+      } else {
+        this.loadingBtn = true;
+      }
+      communityReplyAuditApi(this.auditStatusFrom)
+        .then((res) => {
+          this.$message.success('操作成功');
+          this.dialogVisible = false;
+          if (this.auditStatusFrom.auditStatus === 1) {
+            this.loadingBtnSuccess = false;
+          } else {
+            this.loadingBtn = false;
+          }
+          this.getList();
+        })
+        .catch((res) => {
+          if (this.auditStatusFrom.auditStatus === 1) {
+            this.loadingBtnSuccess = false;
+          } else {
+            this.loadingBtn = false;
+          }
+        });
+    },
+    seachList() {
+      this.tableFrom.page = 1;
+      this.getList();
+    },
+    // 选择时间
+    selectChange(tab) {
+      this.timeVal = [];
+      this.tableFrom.page = 1;
+      this.getList();
+    },
+    // 具体日期
+    onchangeTime(e) {
+      this.timeVal = e;
+      this.tableFrom.dateLimit = e ? this.timeVal.join(',') : '';
+      this.tableFrom.page = 1;
+      this.getList();
+    },
+    // 删除
+    handleDelete(id, idx) {
+      this.$modalSure('删除该评论吗?').then(() => {
+        communityReplyDelApi(id).then(() => {
+          this.$message.success('删除成功');
+          handleDeleteTable(this.tableData.data.length, this.tableFrom);
+          this.getList();
+        });
+      });
+    },
+    // 列表
+    getList() {
+      this.listLoading = true;
+      this.tableFrom.title = encodeURIComponent(this.title);
+      this.tableFrom.keywords = encodeURIComponent(this.keywords);
+      communityReplyListApi(this.tableFrom)
+        .then((res) => {
+          this.tableData.data = res.list;
+          this.tableData.total = res.total;
+          this.listLoading = false;
+        })
+        .catch(() => {
+          this.listLoading = false;
+        });
+    },
+    reset() {
+      this.tableFrom.page = 1;
+      this.tableFrom.auditStatus = '';
+      this.tableFrom.dateLimit = '';
+      this.tableFrom.keywords = '';
+      this.tableFrom.userName = '';
+      this.tableFrom.title = '';
+      this.tableFrom.content = '';
+      this.tableFrom.searchType = 'all';
+      this.keywords = '';
+      this.title = '';
+      this.selectChange();
+    },
+    pageChange(page) {
+      this.tableFrom.page = page;
+      this.getList();
+    },
+    handleSizeChange(val) {
+      this.tableFrom.limit = val;
+      this.getList();
+    },
+    // 审核
+    onAudit(row, type) {
+      this.auditType = type;
+      this.commentsInfo = row;
+      this.id = row.id;
+      this.dialogVisible = true;
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.demo-drawer__content {
+  padding: 25px 30px;
+}
+.description {
+  &-term {
+    display: table-cell;
+    padding-bottom: 5px;
+    line-height: 30px;
+    width: 50%;
+    font-size: 14px;
+    color: #606266;
+  }
+  ::v-deep .el-divider--horizontal {
+    margin: 12px 0 !important;
+  }
+}
+::v-deep.el-drawer__header {
+  margin-bottom: 0 !important;
+}
+.box-container {
+  overflow: hidden;
+}
+.box-container .list {
+  float: left;
+  line-height: 40px;
+}
+.box-container .sp {
+  width: 50%;
+}
+.box-container .sp3 {
+  width: 33.3333%;
+}
+.box-container .sp100 {
+  width: 100%;
+}
+.box-container .list .name {
+  display: inline-block;
+  width: 150px;
+  text-align: right;
+  color: #606266;
+}
+.box-container .list.image {
+  margin-bottom: 40px;
+}
+.box-container .list.image img {
+  position: relative;
+  top: 40px;
+}
+::v-deep.el-form-item__content .el-rate {
+  position: relative;
+  top: 8px;
+}
+.tag-background {
+  padding: 3px 8px;
+}
+</style>

+ 88 - 0
mer_plat_admin/src/views/secondhand/config/index.vue

@@ -0,0 +1,88 @@
+<template>
+  <div class="divBox">
+    <el-card class="box-card" :bordered="false" shadow="never" :body-style="{ padding: '40px 50px' }">
+      <!--el-alert type="warning" class="mb35" :closable="false" show-icon>
+        <slot name="title">
+          <div class="acea-row">
+            <div>社区状态在页面设计中进行开启/关闭;</div>
+            <el-link type="primary" @click="handlerToLink">立即前往</el-link>
+          </div>
+        </slot>
+      </el-alert-->
+      <div class="form-data" v-loading="loading">
+        <z-b-parser
+          v-if="!loading && checkPermi(['platform:community:get:config'])"
+          :is-create="1"
+          :form-conf="formConf"
+          :edit-data="editData"
+          :form-name="formName"
+          :key-num="keyNum"
+          @submit="handlerSubmit"
+        />
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script>
+import { secondHandConfigApi, secondHandConfigUpdateApi } from '@/api/secondHand';
+import { checkPermi } from '@/utils/permission'; // 权限判断函数
+export default {
+  name: 'secondHandConfig',
+  data() {
+    return {
+      formConf: { fields: [] },
+      loading: false,
+      keyNum: 0,
+      editData: {},
+      formName: 'secondHandConfig',
+    };
+  },
+  created() {
+    if (checkPermi(['platform:secondHand:get:config'])) this.getConfigInfo();
+  },
+  methods: {
+    checkPermi,
+    //立即前往
+    handlerToLink() {
+      const { href } = this.$router.resolve({
+        path: '/page/design/viewDesign',
+      });
+      window.open(href);
+    },
+    handlerSubmit(formValue) {
+      if (checkPermi(['platform:secondHand:update:config'])) {
+        secondHandConfigUpdateApi(formValue)
+          .then((res) => {
+            this.$message.success('操作成功');
+            this.getConfigInfo();
+          })
+          .catch(() => {
+            this.loading = false;
+          });
+      } else {
+        this.$message.warning('暂无操作权限');
+      }
+    },
+    // 获取配置信息
+    getConfigInfo() {
+      this.keyNum += 1;
+      this.loading = true;
+      secondHandConfigApi()
+        .then((res) => {
+          this.editData = res;
+          this.loading = false;
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+  },
+};
+</script>
+
+<style scoped>
+.acea-row {
+  align-items: baseline;
+}
+</style>

+ 1053 - 0
mer_plat_admin/src/views/secondhand/content/index.vue

@@ -0,0 +1,1053 @@
+<template>
+  <div class="divBox">
+    <el-card
+      v-hasPermi="['platform:secondHand:prod:page:list']"
+      :bordered="false"
+      shadow="never"
+      class="ivu-mt"
+      :body-style="{ padding: 0 }"
+    >
+      <div class="padding-add">
+        <el-form inline size="small" label-position="right" @submit.native.prevent>
+          <el-form-item label="审核状态:" v-if="tabActive === '10'">
+            <el-select
+              v-model="tableFrom.auditStatus"
+              placeholder="请选择"
+              class="filter-item selWidth"
+              clearable
+              @change="getList(1)"
+            >
+              <el-option v-for="item in statusList" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="用户搜索:" label-for="nickname">
+            <UserSearchInput v-model="tableFrom" />
+          </el-form-item>
+          <el-form-item label="分类名称:" style="display: inline-block">
+            <el-select
+              v-model="tableFrom.categoryId"
+              clearable
+              filterable
+              placeholder="请选择分类名称"
+              class="selWidth"
+              @change="getList(1)"
+            >
+              <el-option
+                v-for="item in cateSelect"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
+                :disabled="item.isShow === 0"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="内容标题:" label-width="66px">
+            <el-input v-model="title" @keyup.enter.native="getList(1)" placeholder="请输入内容标题" class="selWidth" />
+          </el-form-item>
+          <!--el-form-item label="话题名称:" style="display: inline-block">
+            <el-select
+              @change="getList(1)"
+              class="selWidth"
+              clearable
+              filterable
+              v-model="tableFrom.topicId"
+              v-selectLoadMore="selectLoadMore"
+              :loading="loading"
+              remote
+              :multiple="multiple"
+              :remote-method="remoteMethod"
+              placeholder="请选择话题"
+            >
+              <el-option v-for="user in topicSelect" :key="user.id" :label="user.name" :value="user.id"> </el-option>
+            </el-select>
+          </el-form-item-->
+          <el-form-item label="图文类型:">
+            <el-select
+              v-model="tableFrom.type"
+              placeholder="请选择图文类型"
+              class="filter-item selWidth"
+              clearable
+              @change="getList(1)"
+            >
+              <el-option label="图文" value="1" />
+              <el-option label="短视频" value="2" />
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" size="small" @click="getList(1)">查询</el-button>
+            <el-button size="small" @click="reset()">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-card>
+    <el-card class="box-card mt14" :body-style="{ padding: '0 20px 20px' }" shadow="never" :bordered="false">
+      <el-tabs class="list-tabs" v-model="tabActive" @tab-click="handleClick">
+        <el-tab-pane v-for="(item, index) in headeNum" :key="index" :name="item.type" :label="item.title" />
+      </el-tabs>
+      <el-button
+        v-hasPermi="['platform:community:note:category:batch:update']"
+        @click="categoryBatch"
+        size="small"
+        type="primary"
+        class="mt5"
+        >批量移动</el-button
+      >
+      <el-table
+        v-loading="listLoading"
+        ref="table"
+        :data="tableData.data"
+        size="small"
+        highlight-current-row
+        @selection-change="handleSelectionChange"
+        class="mt20 tableSelection"
+      >
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column label="ID" prop="id" width="60" />
+        <el-table-column label="内容标题" min-width="160" :show-overflow-tooltip="true">
+          <template slot-scope="scope">
+            <div>{{ scope.row.title | filterEmpty }}</div>
+          </template>
+        </el-table-column>
+		<el-table-column label="内容" min-width="160" :show-overflow-tooltip="true">
+		  <template slot-scope="scope">
+		    <div>{{ scope.row.content | filterEmpty }}</div>
+		  </template>
+		</el-table-column>
+        <el-table-column label="内容作者" prop="authorName" min-width="140" />
+        <el-table-column label="内容类型" min-width="70">
+          <template slot-scope="scope">
+            <div>{{ scope.row.type === 1 ? '图文' : '视频' }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="封面" min-width="50px">
+          <template slot-scope="scope">
+            <div class="demo-image__preview line-heightOne">
+              <el-image :src="scope.row.cover" class="mr5 imgStyle" :preview-src-list="[scope.row.cover]" />
+            </div>
+          </template>
+        </el-table-column>
+		<el-table-column label="价格" prop="price" min-width="100" />
+		<el-table-column label="所在城市" prop="city" min-width="100">
+			<template slot-scope="scope">
+			  <div>{{ scope.row.city | filterEmpty }}</div>
+			</template>
+		 </el-table-column>
+		 <el-table-column label="所在学校" prop="school" min-width="130">
+		 	<template slot-scope="scope">
+		 	  <div>{{ scope.row.school | filterEmpty }}</div>
+		 	</template>
+		  </el-table-column>
+        <!--el-table-column label="推荐级别" min-width="130">
+          <template slot-scope="scope">
+            <el-rate disabled v-model="scope.row.star"> </el-rate>
+          </template>
+        </el-table-column-->
+        <!--el-table-column prop="likeNum" label="点赞数" min-width="100" />
+        <el-table-column prop="replyNum" label="评论数" min-width="100" /-->
+        <el-table-column prop="categoryName" label="分类" min-width="100" />
+        <!--el-table-column label="话题" min-width="130" :show-overflow-tooltip="true">
+          <template slot-scope="scope">
+            <div v-if="!scope.row.topicList">无</div>
+            <div v-for="(item, i) in scope.row.topicList" :key="i">{{ item }}<br /></div>
+          </template>
+        </el-table-column-->
+        <!--el-table-column label="评论" min-width="90">
+          <template slot-scope="scope">
+            <div>{{ scope.row.replyStatus | communityReplyStatusFilter }}</div>
+          </template>
+        </el-table-column-->
+        <el-table-column v-if="tabActive === '10'" label="审核状态" min-width="100">
+          <template slot-scope="scope">
+            <el-tag class="doingTag tag-background" v-if="scope.row.auditStatus === 0">待审核</el-tag>
+            <el-tag class="endTag tag-background" v-if="scope.row.auditStatus === 1">审核成功</el-tag>
+            <el-tag class="notStartTag tag-background" v-if="scope.row.auditStatus === 2">审核失败</el-tag>
+            <el-tag type="danger" v-if="scope.row.auditStatus === 3">平台关闭</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column
+          v-if="tabActive === '10'"
+          prop="refusal"
+          label="拒绝原因"
+          min-width="120"
+          :show-overflow-tooltip="true"
+        >
+          <template slot-scope="scope">
+            <div v-if="Number(scope.row.auditStatus) > 1">拒绝原因{{ scope.row.refusal }}</div>
+            <div v-else>无</div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="createTime" label="发布时间" min-width="150" />
+        <el-table-column label="操作" width="240" fixed="right">
+          <template slot-scope="scope">
+            <template
+              v-if="
+                scope.row.auditStatus == 0 &&
+                checkPermi(['platform:community:note:detail', 'platform:community:note:audit'])
+              "
+            >
+              <a @click="onAudit(scope.row.id, true)">审核</a>
+              <el-divider direction="vertical"></el-divider>
+            </template>
+            <!--template v-if="checkPermi(['platform:community:note:repley:force:off:switch'])">
+              <a @click="onReplyOff(scope.row)">{{ scope.row.replyStatus !== 3 ? '关闭评论' : '取消关闭评论' }}</a>
+              <el-divider direction="vertical"></el-divider>
+            </template-->
+            <template v-if="scope.row.auditStatus == 1 && checkPermi(['platform:secondHand:prod:forced:down'])">
+              <a @click="onOff(scope.row.id)">强制下架</a>
+              <el-divider direction="vertical"></el-divider>
+            </template>
+            <el-dropdown trigger="click">
+              <span class="el-dropdown-link"> 更多<i class="el-icon-arrow-down el-icon--right" /> </span>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item
+                  @click.native="onAudit(scope.row.id, false)"
+                  v-if="checkPermi(['platform:secondHand:prod:detail'])"
+                >
+                  详情
+                </el-dropdown-item>
+                <el-dropdown-item
+                  @click.native="handleDelete(scope.row.id, scope.$index)"
+                  v-if="checkPermi(['platform:secondHand:prod:delete'])"
+                >
+                  删除
+                </el-dropdown-item>
+                <!--el-dropdown-item
+                  @click.native="onEdit(scope.row)"
+                  v-if="scope.row.auditStatus == 1 && checkPermi(['platform:community:note:star:update'])"
+                >
+                  编辑星级
+                </el-dropdown-item-->
+              </el-dropdown-menu>
+            </el-dropdown>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="block">
+        <el-pagination
+          background
+          :page-sizes="[20, 40, 60, 80]"
+          :page-size="tableFrom.limit"
+          :current-page="tableFrom.page"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="tableData.total"
+          @size-change="handleSizeChange"
+          @current-change="pageChange"
+        />
+      </div>
+    </el-card>
+    <!--审核-->
+    <el-drawer
+      :visible.sync="dialogVisible"
+      :direction="direction"
+      custom-class="demo-drawer"
+      size="1000px"
+      ref="drawer"
+      class="infoBox"
+      @close="onClose"
+    >
+      <div v-loading="loading" v-if="dialogVisible">
+        <div class="detailHead">
+          <div class="acea-row row-between headerBox">
+            <div class="full">
+              <div class="order_icon"><span class="iconfont icon-shipinico"></span></div>
+              <div class="text">
+                <div class="title">{{ isExamine ? '内容审核' : '内容详情' }}</div>
+                <div>
+                  <span class="mr20"
+                    >审核状态:<span class="color-warning">{{
+                      formValidate.auditStatus | communityAuditStatusFilter
+                    }}</span></span
+                  >
+                </div>
+              </div>
+            </div>
+            <div v-if="isExamine" class="acea-row justify-content">
+              <el-button
+                v-hasPermi="['platform:community:note:audit']"
+                v-debounceClick="
+                  () => {
+                    onAuditStatus(2);
+                  }
+                "
+                style="margin-left: 0"
+                >{{ loadingBtn ? '提交中 ...' : '审核拒绝' }}</el-button
+              >
+              <el-button
+                type="primary"
+                v-hasPermi="['platform:community:note:audit']"
+                v-debounceClick="
+                  () => {
+                    onAuditStatus(1);
+                  }
+                "
+                >{{ loadingBtn ? '提交中 ...' : '审核通过' }}</el-button
+              >
+            </div>
+          </div>
+        </div>
+        <el-tabs type="border-card" v-model="currentTab">
+          <!-- 商品信息-->
+          <el-tab-pane label="基础信息" name="0">
+            <div class="detailSection">
+              <ul class="list mt-16">
+                <li class="item">
+                  <div class="tips">文章标题:</div>
+                  <div class="value">
+                    {{ formValidate.title | filterEmpty }}
+                  </div>
+                </li>
+                <li class="item">
+                  <div class="tips">作者:</div>
+                  <div class="value">
+                    {{ formValidate.authorName | filterEmpty }}
+                  </div>
+                </li>
+                <li class="item">
+                  <div class="tips">作者ID:</div>
+                  <div class="value">
+                    {{ formValidate.authorId | filterEmpty }}
+                  </div>
+                </li>
+                <li class="item">
+                  <div class="tips">发布时间:</div>
+                  <div class="value">
+                    {{ formValidate.createTime }}
+                  </div>
+                </li>
+				<li class="item">
+				  <div class="tips">城市:</div>
+				  <div class="value">
+				    {{ formValidate.city}}
+				  </div>
+				</li>
+				<li class="item">
+				  <div class="tips">学校:</div>
+				  <div class="value">
+				    {{ formValidate.school }}
+				  </div>
+				</li>
+				
+              </ul>
+              <div class="list" style="display: block">
+                <div class="item">
+                  <div class="tips">文章内容:</div>
+                  <div class="value">
+                    {{ formValidate.content | filterEmpty }}
+                  </div>
+                </div>
+				<div class="detailSection">
+				  <ul class="list mt-16">
+				    <li class="item">
+				      <div class="tips">价格:</div>
+				      <div class="value">
+				        {{ formValidate.price }}
+				      </div>
+				    </li>
+					</ul>
+				</div>
+                <div class="item row-middle">
+                  <div class="tips">封面图:</div>
+                  <div class="upLoadPicBox">
+                    <el-image
+                      class="pictrue"
+                      :src="formValidate.cover"
+                      :preview-src-list="[formValidate.cover]"
+                    ></el-image>
+                  </div>
+                </div>
+                <div class="item" v-if="formValidate.type === 2 && formValidate.video">
+                  <div class="acea-row row-middle">
+                    <div class="tips">短视频:</div>
+                    <div class="upLoadPicBox">
+                      <video class="pictrue" :src="formValidate.video" controls="controls">
+                        您的浏览器不支持 video 标签。
+                      </video>
+                    </div>
+                  </div>
+                </div>
+                <div class="item" v-if="formValidate.type === 1 && formValidate.image">
+                  <div class="tips">图片:</div>
+                  <div
+                    v-for="(item, index) in formValidate.image.split(',')"
+                    :key="index"
+                    class="pictrue"
+                    style="display: inline-block; margin: 0 10px 10px 0"
+                  >
+                    <el-image class="pictrue" :src="item || ''" :preview-src-list="[item ? item : '']" />
+                  </div>
+                </div>
+                <div class="item" v-if="formValidate.auditStatus === 2 || formValidate.auditStatus === 3">
+                  <div class="tips">{{ formValidate.auditStatus === 2 ? '拒绝原因:' : '关闭原因:' }}</div>
+                  <div class="value">
+                    {{ formValidate.refusal }}
+                  </div>
+                </div>
+                <div class="item" v-if="formValidate.operateTime">
+                  <div class="tips">{{ formValidate.auditStatus === 3 ? '关闭时间:' : '审核时间:' }}</div>
+                  <div class="value">
+                    {{ formValidate.operateTime }}
+                  </div>
+                </div>
+              </div>
+            </div>
+          </el-tab-pane>
+          <!--el-tab-pane label="关联商品" name="1">
+            <el-table
+              class="mt20"
+              ref="tableList"
+              row-key="id"
+              :data="formValidate.productList"
+              size="small"
+              border
+              style="width: 100%"
+            >
+              <el-table-column prop="id" label="ID" min-width="45" />
+              <el-table-column min-width="180" label="商品信息">
+                <template slot-scope="scope">
+                  <div class="acea-row row-middle">
+                    <div class="demo-image__preview mr10 acea-row">
+                      <el-image :src="scope.row.productImage" :preview-src-list="[scope.row.productImage]" />
+                    </div>
+                    <div class="row_title line2">{{ scope.row.productName }}</div>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column prop="price" label="售价" width="120" />
+            </el-table>
+          </el-tab-pane>
+          <el-tab-pane label="评论列表" name="2">
+            <el-table
+              ref="tableList"
+              row-key="id"
+              :data="replyData.data"
+              size="small"
+              border
+              class="mt20"
+              style="width: 100%"
+              :default-expand-all="isExpandAll"
+              :tree-props="{ children: 'replyList', hasChildren: 'hasChildren' }"
+            >
+              <el-table-column prop="用户名/Id" label="ID" min-width="100">
+                <template slot-scope="scope">
+                  <span>{{ scope.row.nickname + '/' + scope.row.id }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column prop="content" label="评论内容" width="150" :show-overflow-tooltip="true" />
+              <el-table-column prop="countReply" label="评论数" min-width="100" />
+              <el-table-column prop="countStart" label="点赞数" min-width="100" />
+              <el-table-column label="评论时间" min-width="150" prop="createTime" />
+              <el-table-column label="操作" width="120" fixed="right">
+                <template slot-scope="scope">
+                  <el-button
+                    type="text"
+                    size="small"
+                    @click="handleReplyDelete(scope.row.id, scope.$index)"
+                    v-hasPermi="['platform:product:reply:delete']"
+                    >删除</el-button
+                  >
+                </template>
+              </el-table-column>
+            </el-table-->
+            <!--div class="block">
+              <el-pagination
+                :page-sizes="[20, 40, 60, 80]"
+                :page-size="tableFromReply.limit"
+                :current-page="tableFromReply.page"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="replyData.total"
+                @size-change="handleSizeChangeReply"
+                @current-change="pageChangeReply"
+              />
+            </div-->
+          </el-tab-pane>
+        </el-tabs>
+      </div>
+      <div class="demo-drawer__footer">
+        <div v-show="isExamine" class="from-foot-btn drawer_fix">
+          <div class="acea-row justify-content"></div>
+        </div>
+      </div>
+    </el-drawer>
+    <!--编辑星级-->
+    <el-dialog :visible.sync="visible" title="编辑星级" destroy-on-close :close-on-click-modal="false" width="540px">
+      <el-rate v-model="star"></el-rate>
+      <span slot="footer">
+        <div class="dialog-btn-top">
+          <el-button @click="visible = false">取消</el-button>
+          <el-button
+            type="primary"
+            v-debounceClick="
+              () => {
+                submitForm();
+              }
+            "
+            >确 定</el-button
+          >
+        </div>
+      </span>
+    </el-dialog>
+    <!--编辑分类-->
+    <el-dialog
+      :visible.sync="visibleCategory"
+      title="编辑分类"
+      destroy-on-close
+      :close-on-click-modal="false"
+      width="540px"
+    >
+      <el-select v-model="categoryId" clearable filterable placeholder="请选择" class="selectStyle">
+        <el-option
+          v-for="item in cateSelect"
+          :key="item.id"
+          :label="item.name"
+          :value="item.id"
+          :disabled="item.isShow === 0"
+        />
+      </el-select>
+      <span slot="footer">
+        <div class="dialog-btn-top">
+          <el-button @click="visibleCategory = false">取消</el-button>
+          <el-button
+            type="primary"
+            v-debounceClick="
+              () => {
+                submitFormCategory();
+              }
+            "
+            >确 定</el-button
+          >
+        </div>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+import * as secondHand from '@/api/secondHand';
+import { checkPermi } from '@/utils/permission';
+import { filterEmpty } from '@/filters';
+import { handleDeleteTable } from '@/libs/public'; // 权限判断函数
+export default {
+  name: 'communityTopic',
+  directives: {
+    // 计算是否滚动到最下面
+    selectLoadMore: {
+      bind(el, binding) {
+        // 获取element-ui定义好的scroll盒子
+        const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap');
+        SELECTWRAP_DOM.addEventListener(
+          'scroll',
+          function () {
+            if (this.scrollHeight - this.scrollTop < this.clientHeight + 1) {
+              binding.value();
+            }
+          },
+          { passive: true },
+        );
+      },
+    },
+  },
+  data() {
+    return {
+      currentTab: 0,
+      tabActive: '',
+      star: 0,
+      visible: false,
+      direction: 'rtl',
+      // 是否展开,默认全部折叠
+      isExpandAll: false,
+      multiple: false,
+      moren: '',
+      isChecked: false,
+      listLoading: true,
+      tableData: {
+        data: [],
+        total: 0,
+      },
+      search: {
+        limit: 10,
+        page: 1,
+        name: '',
+      },
+      tableFrom: {
+        page: 1,
+        limit: 20,
+        auditStatus: 0,
+        type: '',
+        title: '',
+        authorName: '',
+        categoryId: '',
+        topicId: '',
+        searchType: 'all',
+      },
+      title: '',
+      statusList: [
+        { label: '待审核', value: 0 },
+        { label: '已通过', value: 1 },
+        { label: '已拒绝', value: 2 },
+        { label: '平台关闭', value: 3 },
+      ],
+      headeNum: [
+        { title: '待审核', type: '0' },
+        { title: '全部', type: '10' }, //全部无值,此处为了做选中样式,赋值10,10代表全部状态
+      ],
+      cateSelect: [],
+      topicSelect: [],
+      dialogVisible: false,
+      loading: false,
+      loadingAudit: false,
+      isExamine: false, // 是否是审核
+      community_id: '',
+      rules: {
+        status: [{ required: true, message: '请选择审核状态', trigger: 'change' }],
+        refusal: [{ required: true, message: '请填写拒绝原因', trigger: 'blur' }],
+      },
+      //强制下架
+      ruleForm: {
+        id: 0,
+        reason: '',
+      },
+      //评论列表分页
+      tableFromReply: {
+        page: 1,
+        limit: 20,
+        nid: 0,
+      },
+      //评论列表数据
+      replyData: {
+        data: [],
+        total: 0,
+      },
+      id: 0,
+      formValidate: {}, //详情
+      //审核
+      auditStatusFrom: {
+        auditStatus: 0,
+        id: 0,
+        refusalReason: '',
+      },
+      loadingBtn: false,
+      multipleSelectionAll: [],
+      multipleSelection: [],
+      idKey: 'id',
+      visibleCategory: false, //分类弹窗
+      categoryId: '', //分类
+      noteIdList: [], //笔记列表id
+    };
+  },
+  mounted() {
+    if (checkPermi(['platform:secondHand:prod:page:list'])) this.getList(1);
+    this.getCateSelect();
+    //this.getTopicSelect();
+  },
+  methods: {
+    filterEmpty,
+    checkPermi,
+    //审核拒绝
+    cancelForm() {
+      this.$modalPrompt('textarea', '拒绝原因').then((V) => {
+        this.auditStatusFrom.refusalReason = V;
+        this.onAuditSubmit();
+      });
+    },
+    // 审核点击
+    onAuditStatus(type) {
+      this.auditStatusFrom.auditStatus = type;
+      if (type === 1) {
+        this.$modalSure('审核通过该内容吗?').then(() => {
+          this.onAuditSubmit();
+        });
+      } else {
+        this.cancelForm();
+      }
+    },
+    //审核提交
+    onAuditSubmit() {
+      this.auditStatusFrom.id = this.community_id;
+      secondHand
+        .secondHandProdAuditApi(this.auditStatusFrom)
+        .then((res) => {
+          this.$message.success('操作成功');
+          this.dialogVisible = false;
+          this.loadingBtn = false;
+          this.getList();
+        })
+        .catch((res) => {
+          this.loadingBtn = false;
+        });
+    },
+    //编辑星级
+    submitForm() {
+      community.communityStarUpdateApi({ id: this.id, star: this.star }).then((res) => {
+        this.$message.success('编辑成功');
+        this.visible = false;
+        this.getList();
+      });
+    },
+    handleClick(tab) {
+      this.tabActive = tab.name;
+      if (this.tabActive === '10') {
+        this.tableFrom.auditStatus = '';
+      } else {
+        this.tableFrom.auditStatus = 0;
+      }
+      this.getList(1);
+    },
+    onClose() {
+      this.dialogVisible = false;
+    },
+    // 评论列表;
+    getReplyNoteList(id) {
+      this.tableFromReply.nid = id;
+      community.communityReplyNoteListApi(this.tableFromReply).then((res) => {
+        this.replyData.total = res.total;
+        this.replyData.data = res.list;
+      });
+    },
+    pageChangeReply(page) {
+      this.tableFromReply.page = page;
+      this.getReplyNoteList(this.community_id);
+    },
+    handleSizeChangeReply(val) {
+      this.tableFromReply.limit = val;
+      this.getReplyNoteList(this.community_id);
+    },
+    //评论删除
+    handleReplyDelete(id) {
+      this.$modalSure('删除该评论').then(() => {
+        community.communityReplyDelApi(id).then(() => {
+          this.$message.success('删除成功');
+          this.getReplyNoteList(this.community_id);
+        });
+      });
+    },
+    // 分类列表;
+    getCateSelect() {
+      secondHand
+        .secondHandCategoryListApi({
+          limit: 100,
+          page: 1,
+        })
+        .then((res) => {
+          this.cateSelect = res.list;
+        });
+    },
+    // 下拉加载更多
+    selectLoadMore() {
+      this.search.page = this.search.page + 1;
+      if (this.search.page > this.totalPage) return;
+      this.getTopicSelect(); // 请求接口
+    },
+    // 远程搜索
+    remoteMethod(query) {
+      this.loading = true;
+      this.search.name = query;
+      this.search.page = 1;
+      this.topicSelect = [];
+      setTimeout(() => {
+        this.loading = false;
+        this.getTopicSelect(); // 请求接口
+      }, 200);
+    },
+    // 话题列表;
+    getTopicSelect() {
+      community.communityTopicListApi(this.search).then((res) => {
+        this.totalPage = res.totalPage;
+        this.total = res.total;
+        this.topicSelect = this.topicSelect.concat(res.list);
+      });
+    },
+    //批量移动
+    categoryBatch() {
+      if (this.noteIdList.length === 0) return this.$message.warning('请至少选择一个内容');
+      this.visibleCategory = true;
+    },
+    //批量移动提交
+    submitFormCategory() {
+      if (this.categoryId === 0) return this.$message.warning('请选择要移动到的分类');
+      secondHand
+        .secondHandCategoryBatchApi({
+          categoryId: this.categoryId,
+          noteIdList: this.noteIdList,
+        })
+        .then((res) => {
+          this.$message.success('移动成功');
+          this.visibleCategory = false;
+          this.getList();
+        });
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+      setTimeout(() => {
+        this.changePageCoreRecordData();
+        let data = [];
+        if (this.multipleSelectionAll.length) {
+          this.multipleSelectionAll.map((item) => {
+            data.push(item.id);
+          });
+        }
+        this.noteIdList = data;
+      }, 50);
+    },
+    // 设置选中的方法
+    setSelectRow() {
+      if (!this.multipleSelectionAll || this.multipleSelectionAll.length <= 0) {
+        return;
+      }
+      // 标识当前行的唯一键的名称
+      let idKey = this.idKey;
+      let selectAllIds = [];
+      this.multipleSelectionAll.forEach((row) => {
+        selectAllIds.push(row[idKey]);
+      });
+      this.$refs.table.clearSelection();
+      for (var i = 0; i < this.tableData.data.length; i++) {
+        if (selectAllIds.indexOf(this.tableData.data[i][idKey]) >= 0) {
+          // 设置选中,记住table组件需要使用ref="table"
+          this.$refs.table.toggleRowSelection(this.tableData.data[i], true);
+        }
+      }
+    },
+    // 记忆选择核心方法
+    changePageCoreRecordData() {
+      // 标识当前行的唯一键的名称
+      let idKey = this.idKey;
+      let that = this;
+      // 如果总记忆中还没有选择的数据,那么就直接取当前页选中的数据,不需要后面一系列计算
+      if (this.multipleSelectionAll.length <= 0) {
+        this.multipleSelectionAll = this.multipleSelection;
+        return;
+      }
+      // 总选择里面的key集合
+      let selectAllIds = [];
+      this.multipleSelectionAll.forEach((row) => {
+        selectAllIds.push(row[idKey]);
+      });
+      let selectIds = [];
+      // 获取当前页选中的id
+      this.multipleSelection.forEach((row) => {
+        selectIds.push(row[idKey]);
+        // 如果总选择里面不包含当前页选中的数据,那么就加入到总选择集合里
+        if (selectAllIds.indexOf(row[idKey]) < 0) {
+          that.multipleSelectionAll.push(row);
+        }
+      });
+      let noSelectIds = [];
+      // 得到当前页没有选中的id
+      this.tableData.data.forEach((row) => {
+        if (selectIds.indexOf(row[idKey]) < 0) {
+          noSelectIds.push(row[idKey]);
+        }
+      });
+      noSelectIds.forEach((id) => {
+        if (selectAllIds.indexOf(id) >= 0) {
+          for (let i = 0; i < that.multipleSelectionAll.length; i++) {
+            if (that.multipleSelectionAll[i][idKey] == id) {
+              // 如果总选择中有未被选中的,那么就删除这条
+              that.multipleSelectionAll.splice(i, 1);
+              break;
+            }
+          }
+        }
+      });
+    },
+    // 列表
+    getList(num) {
+      this.listLoading = true;
+      this.tableFrom.page = num ? num : this.tableFrom.page;
+      this.tableFrom.title = encodeURIComponent(this.title);
+      secondHand
+        .secondHandProdListApi(this.tableFrom)
+        .then((res) => {
+          this.tableData.data = res.list;
+          this.tableData.total = res.total;
+          this.$nextTick(function () {
+            this.setSelectRow(); //调用跨页选中方法
+          });
+          this.listLoading = false;
+        })
+        .catch((res) => {
+          this.listLoading = false;
+        });
+    },
+    reset() {
+      this.tableFrom.auditStatus = '';
+      this.tableFrom.type = '';
+      this.tableFrom.title = '';
+      this.tableFrom.authorName = '';
+      this.tableFrom.categoryId = '';
+      this.tableFrom.topicId = '';
+      this.title = '';
+      this.tableFrom.content = '';
+      this.tableFrom.searchType = 'all';
+      this.getList(1);
+    },
+    pageChange(page) {
+      this.changePageCoreRecordData();
+      this.tableFrom.page = page;
+      this.getList('');
+    },
+    handleSizeChange(val) {
+      this.changePageCoreRecordData();
+      this.tableFrom.limit = val;
+      this.getList('');
+    },
+    // 编辑
+    onEdit(row) {
+      this.star = row.star;
+      this.id = row.id;
+      this.visible = true;
+    },
+    // 查看评论
+    onReply(id) {
+      this.$router.push({
+        path: 'reply',
+        query: {
+          community_id: id,
+        },
+      });
+    },
+    // 审核
+    onAudit(id, bl) {
+      this.loadingAudit = true;
+      this.currentTab = 0;
+      //this.getReplyNoteList(id);
+      this.community_id = id;
+      this.dialogVisible = true;
+      this.isExamine = bl;
+      secondHand.secondHandProdDetailApi(id).then((res) => {
+        this.formValidate = res;
+        this.loadingAudit = false;
+      });
+    },
+    // 强制下架
+    onOff(id) {
+      this.$modalPrompt('textarea', '强制下架原因').then((V) => {
+        this.ruleForm.reason = V;
+        this.submit(id);
+      });
+    },
+    submit(id) {
+      this.ruleForm.id = id;
+      secondHand.secondHandProdForcedDownApi(this.ruleForm).then((res) => {
+        this.$message.success('下架成功');
+        this.getList();
+      });
+    },
+    onSubmit() {
+      secondHand
+        .secondHandProdAuditApi(this.community_id, this.ruleForm)
+        .then((res) => {
+          this.$message.success(res.message);
+          this.dialogVisible = false;
+          this.getList('');
+        })
+        .catch((res) => {
+          this.$message.error(res.message);
+        });
+    },
+    //强制关闭评论
+    onReplyOff(row) {
+      this.$modalSure(
+        row.replyStatus !== 3
+          ? '关闭评论吗?关闭之后该内容将无法评论'
+          : '取消强制关闭评论吗?取消后评论将变成用户关闭状态',
+      ).then(() => {
+        community.communityNoteReplyOffApi(row.id).then(() => {
+          this.$message.success('关闭成功');
+          this.getList();
+        });
+      });
+    },
+    // 删除
+    handleDelete(id) {
+      this.$modalSure('删除该内容吗').then(() => {
+        secondHand.secondHandProdDelApi(id).then(() => {
+          this.$message.success('删除成功');
+          handleDeleteTable(this.tableData.data.length, this.tableFrom);
+          this.getList();
+        });
+      });
+    },
+    onchangeIsShow(row) {
+      community.communityNoteReplyOffApi(row.replyStatus).then(() => {
+        this.getList('');
+        this.$message.success('操作成功');
+      });
+    },
+  },
+};
+</script>
+
+<style scoped tips="scss">
+.detailSection {
+  border: none !important;
+}
+
+::v-deep .el-drawer__header {
+  display: none;
+}
+
+.icon-shipinico {
+  font-size: 50px;
+}
+
+.box-container {
+  overflow: hidden;
+}
+
+.box-container .list {
+  float: left;
+  line-height: 40px;
+}
+
+.box-container .sp {
+  width: 50%;
+}
+
+.box-container .sp3 {
+  width: 33.3333%;
+}
+
+.box-container .sp100 {
+  width: 100%;
+}
+
+.box-container .list .name {
+  display: inline-block;
+  width: 150px;
+  text-align: right;
+  color: #606266;
+}
+
+.box-container .list.image {
+  margin-bottom: 40px;
+}
+
+.box-container .list.image img {
+  position: relative;
+  top: 40px;
+}
+
+::v-deep.el-form-item__content .el-rate {
+  position: relative;
+  top: 8px;
+}
+
+.selectStyle {
+  width: 100%;
+  padding-bottom: 20px;
+}
+
+::v-deep .el-image__preview {
+  object-fit: contain;
+}
+</style>

+ 20 - 0
mer_plat_admin/src/views/secondhand/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div>
+    <router-view />
+  </div>
+</template>
+
+<script>
+// +---------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +---------------------------------------------------------------------
+// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
+// +---------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +---------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +---------------------------------------------------------------------
+export default {};
+</script>
+
+<style scoped></style>

+ 569 - 0
mer_plat_admin/src/views/secondhand/order/components/orderDetail.vue

@@ -0,0 +1,569 @@
+<template>
+  <div>
+    <el-drawer :visible.sync="dialogVisible" :direction="direction" size="1000px" :before-close="handleClose">
+      <div slot="title" class="demo-drawer_title">
+        <div class="detailHead">
+          <div class="full">
+            <div class="order_icon"><span class="iconfont icon-dingdan"></span></div>
+            <div class="text">
+              <div class="title">{{ orderDatalist.type | orderTypeFilter }}</div>
+              <div>
+                <span class="mr20">订单号:{{ orderDatalist.orderNo }}</span>
+              </div>
+            </div>
+          </div>
+          <ul class="list">
+            <li class="item">
+              <div class="title">订单状态</div>
+              <div class="color-warning">
+                <span v-if="orderDatalist.refundStatus === 3">已退款</span>
+                <span v-else>{{ orderDatalist.status | orderStatusFilter }}</span>
+              </div>
+            </li>
+            <li class="item">
+              <div class="title">实际支付</div>
+              <div>¥ {{ orderDatalist.payPrice || '0.0' }}</div>
+            </li>
+            <li class="item">
+              <div class="title">支付方式</div>
+              <div>{{ orderDatalist.payType | payTypeFilter }}</div>
+            </li>
+            <li class="item">
+              <div class="title">创建时间</div>
+              <div>{{ orderDatalist.createTime | filterEmpty }}</div>
+            </li>
+          </ul>
+        </div>
+      </div>
+      <div v-if="orderDatalist" v-loading="loading">
+        <el-tabs type="border-card" v-model="activeName">
+          <el-tab-pane label="订单信息" name="detail">
+            <div class="detailSection" style="border: none">
+              <div class="title">用户信息</div>
+              <ul class="list">
+                <li class="item">
+                  <div class="lang">用户名称:</div>
+                  <div class="value">{{ orderDatalist.nickname }} | {{ orderDatalist.uid }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">用户电话:</div>
+                  <div class="value">{{ orderDatalist.phone }}</div>
+                </li>
+              </ul>
+            </div>
+            <div v-show="orderDatalist.shippingType < 2 " class="detailSection">
+              <div class="title">收货信息</div>
+              <ul class="list">
+                <li class="item">
+                  <div class="lang">收货人:</div>
+                  <div class="value">
+                    {{ orderDatalist.realName }}
+                  </div>
+                </li>
+                <li class="item">
+                  <div class="lang">收货电话:</div>
+                  <div class="value">
+                    {{ orderDatalist.userPhone }}
+                  </div>
+                </li>
+                <li class="item">
+                  <div class="lang">收货地址:</div>
+                  <div class="value">
+                    {{ orderDatalist.userAddress }}
+                  </div>
+                </li>
+              </ul>
+            </div>
+            <div class="detailSection">
+              <div class="title">订单信息</div>
+              <ul class="list">
+                <li class="item">
+                  <div class="lang">商品总价:</div>
+                  <div class="value">{{ orderDatalist.proTotalPrice }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">商品总数:</div>
+                  <div class="value">{{ orderDatalist.totalNum }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">平台优惠金额:</div>
+                  <div class="value">{{ orderDatalist.platCouponPrice }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">支付状态:</div>
+                  <div class="value">{{ orderDatalist.paid ? '已支付' : '未支付' }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">实际支付:</div>
+                  <div class="value">{{ orderDatalist.payPrice || '0.0' }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">商户优惠金额:</div>
+                  <div class="value">{{ orderDatalist.merCouponPrice || '0.0' }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">会员抵扣金额:</div>
+                  <div class="value">{{ orderDatalist.svipDiscountPrice || '0.0' }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">支付邮费:</div>
+                  <div class="value">{{ orderDatalist.payPostage }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">赠送积分:</div>
+                  <div class="value">{{ orderDatalist.gainIntegral }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">积分抵扣金额:</div>
+                  <div class="value">{{ orderDatalist.integralPrice || '0.0' }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">支付方式:</div>
+                  <div class="value">{{ orderDatalist.payType | payTypeFilter }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">配送方式:</div>
+                  <div v-if="Number(orderDatalist.secondType) > 4" class="value">自动发货</div>
+                  <div v-else-if="Number(orderDatalist.secondType) == 2" class="value">虚拟发货</div>
+                  <div v-else class="value">{{ orderDatalist.shippingType | shippingTypeFilter }}</div>
+                </li>
+                <li class="item">
+                  <div class="lang">支付时间:</div>
+                  <div class="value">{{ orderDatalist.payTime | filterEmpty }}</div>
+                </li>
+              </ul>
+            </div>
+            <div class="detailSection">
+              <div class="title">买家留言</div>
+              <ul class="list">
+                <li class="item">
+                  <div>{{ orderDatalist.userRemark | filterEmpty }}</div>
+                </li>
+              </ul>
+            </div>
+            <div class="detailSection">
+              <div class="title">商家备注</div>
+              <ul class="list">
+                <li class="item">
+                  <div>{{ orderDatalist.merchantRemark | filterEmpty }}</div>
+                </li>
+              </ul>
+            </div>
+            <div v-if="orderExtend.length && orderDatalist.secondType !== 1" class="detailSection">
+              <div class="title">自定义留言</div>
+              <ul class="list">
+                <li class="item" v-for="(item, index) in orderExtend" :key="index">
+                  <div class="lang" :title="item.title">{{ item.title }}</div>
+                  <div>{{ item.title.includes(':') ? '' : ':' }}</div>
+                  <div v-if="!Array.isArray(item.value)" class="value">{{ item.value | filterEmpty }}</div>
+                  <div v-else class="flex conter">
+                    <template v-if="item.value">
+                      <div v-for="(pic, idx) in item.value" :key="idx">
+                        <el-image v-if="pic.includes('http')" class="pictrue" :src="pic" :preview-src-list="[pic]" />
+                        <div v-else class="text-14px fontColor333 ml-5px acea-row row-middle mr5">
+                          {{ pic }}
+                          <div style="margin-left: 6px" v-show="idx < item.value.length - 1">-</div>
+                        </div>
+                      </div>
+                    </template>
+                    <template v-else> - </template>
+                  </div>
+                </li>
+              </ul>
+            </div>
+          </el-tab-pane>
+          <el-tab-pane label="商品信息" name="goods">
+            <el-table class="mt20 orderDetailList" :data="orderDatalist.orderDetailList" size="small">
+              <el-table-column label="商品信息" min-width="400" :show-overflow-tooltip="true">
+                <template slot-scope="scope">
+                  <div class="acea-row row-middle">
+                    <div class="demo-image__preview mr15 line-heightOne">
+                      <el-image :src="scope.row.image" :preview-src-list="[scope.row.image]" />
+                    </div>
+                    <div style="width: 408px">
+                      <div class="line1 mb10">{{ scope.row.productName }}</div>
+                      <div class="line1 color-909399 line-heightOne">规格:{{ scope.row.sku }}</div>
+                    </div>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column label="商品售价" min-width="90">
+                <template slot-scope="scope">
+                  <div class="acea-row row-middle">
+                    <div class="line1">
+                      {{ scope.row.price }}
+                    </div>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column label="购买数量" min-width="90">
+                <template slot-scope="scope">
+                  <div class="acea-row row-middle">
+                    <div class="line1">
+                      {{ scope.row.payNum }}
+                    </div>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column :label="orderDatalist.shippingType == 2 ? '核销数量' : '发货数量'" min-width="90">
+                <template slot-scope="scope">
+                  <div class="acea-row row-middle">
+                    <div class="line1">
+                      {{ scope.row.deliveryNum }}
+                    </div>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column label="售后数量" min-width="90">
+                <template slot-scope="scope">
+                  <div class="acea-row row-middle">
+                    <div class="line1 mb10 line-heightOne">退款中:{{ scope.row.applyRefundNum }}</div>
+                    <div class="line1 line-heightOne">退款成功:{{ scope.row.refundNum }}</div>
+                  </div>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-tab-pane>
+          <el-tab-pane
+            v-if="
+              orderDatalist.status > 1 &&
+              orderDatalist.status < 9 &&
+              orderDatalist.secondType < 5 &&
+              orderDatalist.status !== 3 &&
+              orderDatalist.shippingType != 2
+            "
+            label="发货记录"
+            name="delivery"
+            class="tabBox"
+          >
+            <template v-for="item in InvoiceList">
+              <div v-if="InvoiceList.length">
+                <el-table class="mt20" :data="item.detailList" size="small" :key="item.id">
+                  <el-table-column min-width="400">
+                    <template slot="header" slot-scope="scope">
+                      <template v-if="item.deliveryType === 'express'">
+                        <span class="font-color">【快递配送】</span>
+                        <span>{{ item.expressName + ':' + item.trackingNumber }}</span>
+                        <span class="ml30">{{ item.createTime }}</span>
+                      </template>
+                      <template v-else-if="item.deliveryType === 'merchant'">
+                        <span class="font-color">【商家送货】</span>
+                        <span>{{ item.deliveryCarrier + ':' + item.carrierPhone }}</span>
+                        <span class="ml30">{{ item.createTime }}</span>
+                      </template>
+                      <template v-else>
+                        <span class="font-color"
+                          >【{{
+                            orderDatalist.secondType === OrderSecondTypeEnum.Fictitious ? '虚拟发货' : '无需配送'
+                          }}】</span
+                        >
+                        <span>{{ item.createTime }}</span>
+                      </template>
+                    </template>
+                    <template slot-scope="scope">
+                      <div class="acea-row row-middle">
+                        <div class="demo-image__preview mr15">
+                          <el-image :src="scope.row.image" :preview-src-list="[scope.row.image]" />
+                        </div>
+                        <div>
+                          <div class="line1 mb10 line-heightOne">{{ scope.row.productName }}</div>
+                          <div class="line1 color-909399 line-heightOne">规格:{{ scope.row.sku }}</div>
+                        </div>
+                        <div class="acea-row row-middle ml30">
+                          <div class="line1 font12 color-text">X {{ scope.row.num }}</div>
+                        </div>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column width="400" fixed="right">
+                    <template slot="header" slot-scope="scope">
+                      <div class="flex mr10" style="justify-content: flex-end">
+                        <a
+                          class="ml20"
+                          @click="openLogistics(item.id, item.expressName)"
+                          style="line-height: 1; height: auto"
+                          v-if="checkPermi(['platform:order:logistics:info']) && item.deliveryType === 'express'"
+                          >查看物流
+                        </a>
+                      </div>
+                    </template>
+                    <template v-if="item.deliveryType === 'noNeed'" slot-scope="scope">
+                      <div class="acea-row row-middle">
+                        <div class="font12 color-text">发货备注:{{ item.deliveryMark }}</div>
+                      </div>
+                    </template>
+                  </el-table-column>
+                </el-table>
+              </div>
+            </template>
+            <!--            <div v-if="parseFloat(orderDatalist.shippingType) === 2">-->
+            <!--              <div class="detailSection">-->
+            <!--                <ul class="list">-->
+            <!--                  <li class="item">-->
+            <!--                    <div>核销员名称:</div>-->
+            <!--                    <div class="value">{{ orderDatalist.clerkName }} | {{ orderDatalist.clerkId }}</div>-->
+            <!--                  </li>-->
+            <!--                </ul>-->
+            <!--              </div>-->
+            <!--            </div>-->
+          </el-tab-pane>
+        </el-tabs>
+      </div>
+    </el-drawer>
+    <el-dialog v-if="orderDatalist" title="提示" :visible.sync="modal2" width="600px">
+      <div class="logistics acea-row row-top">
+        <div class="logistics_img"><img src="@/assets/imgs/expressi.jpg" /></div>
+        <div class="logistics_cent">
+          <span class="mb10">物流公司:{{ expressName }}</span>
+          <span>物流单号:{{ resultInfo.number }}</span>
+          <span v-show="resultInfo.courierPhone">快递站:{{ resultInfo.courierPhone }}</span>
+          <span v-show="resultInfo.courierPhone">快递员电话:{{ resultInfo.courierPhone }}</span>
+        </div>
+      </div>
+      <div class="acea-row row-column-around trees-coadd">
+        <div class="scollhide">
+          <el-timeline :reverse="reverse">
+            <el-timeline-item v-for="(item, i) in result" :key="i">
+              <p class="time" v-text="item.time"></p>
+              <p class="content" v-text="item.status"></p>
+            </el-timeline-item>
+          </el-timeline>
+        </div>
+      </div>
+      <span slot="footer">
+        <el-button type="primary" @click="modal2 = false">关闭</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+import { getLogisticsInfoApi, orderInvoiceListApi, orderDetailApi, refundOrderDetailApi } from '@/api/secondHand';
+import { checkPermi } from '@/utils/permission'; // 权限判断函数
+import { OrderSecondTypeEnum } from '@/enums/productEnums';
+export default {
+  name: 'OrderDetail',
+  props: {
+    orderNo: {
+      type: String,
+      default: 0,
+    },
+  },
+  data() {
+    return {
+      OrderSecondTypeEnum: OrderSecondTypeEnum,
+      activeName: 'detail',
+      direction: 'rtl',
+      reverse: true,
+      dialogVisible: false,
+      orderDatalist: {},
+      loading: false,
+      modal2: false,
+      result: [],
+      resultInfo: {},
+      InvoiceList: [],
+      refundInfo: {},
+      expressName: '', //快递名称
+      orderExtend: [], //系统表单数据
+    };
+  },
+  watch: {},
+  mounted() {
+    this.activeName = 'detail';
+  },
+  methods: {
+    checkPermi,
+    tabClick(tab) {
+      if (tab.name == 'orderList') {
+        //this.getRecordList();
+      }
+    },
+    handleClose() {
+      this.dialogVisible = false;
+    },
+    openLogistics(id, expressName) {
+      this.expressName = expressName;
+      this.getOrderData(id);
+      this.modal2 = true;
+    },
+    // 获取订单退款信息
+    getRefundOrderDetail(id) {
+      refundOrderDetailApi(id).then(async (res) => {
+        this.refundInfo = res;
+      });
+    },
+    // 获取订单物流信息
+    getOrderData(id) {
+      getLogisticsInfoApi(id).then(async (res) => {
+        this.resultInfo = res;
+        this.result = res.list;
+      });
+    },
+    // 获取订单发货单列表
+    getOrderInvoiceList(id) {
+      orderInvoiceListApi(id)
+        .then((res) => {
+          this.InvoiceList = res;
+        })
+        .catch(() => {});
+    },
+    getDetail(id) {
+      this.loading = true;
+      orderDetailApi({ orderNo: id })
+        .then((res) => {
+          this.orderDatalist = res;
+          this.orderExtend = res.orderExtend ? JSON.parse(res.orderExtend) : [];
+          this.activeName = 'detail';
+          this.loading = false;
+        })
+        .catch(() => {
+          this.orderDatalist = null;
+          this.loading = false;
+        });
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+::v-deep .el-drawer__header {
+  display: flex !important;
+  align-items: flex-start !important;
+  padding: 15px 15px 0 15px !important;
+  margin: 0 !important;
+}
+::v-deep .el-drawer__body{
+  padding: 0 0 30px 0 !important;
+}
+::v-deep .demo-drawer_title {
+  width: 90%;
+}
+::v-deep .el-tabs__content {
+  padding: 0 20px !important;
+}
+.detailSection {
+  padding: 25px 15px !important;
+}
+::v-deep .el-table th.el-table__cell > .cell,
+::v-deep.el-table .cell,
+.el-table--border .el-table__cell:first-child .cell {
+  padding-left: 15px;
+}
+.InvoiceList {
+  ::v-deep.el-collapse-item__header {
+    font-size: 12px;
+    color: #606266;
+  }
+}
+
+.wrapper {
+  background-color: #fff;
+  margin-top: 7px;
+  padding: 10px 12px;
+  &-num {
+    font-size: 10px;
+    color: #999999;
+  }
+
+  &-title {
+    color: #666666;
+    font-size: 12px;
+  }
+
+  &-img {
+    width: 60px;
+    height: 60px;
+    margin-right: 10px;
+    border-radius: 7px;
+    overflow: hidden;
+    margin-bottom: 10px;
+
+    image {
+      width: 100%;
+      height: 100%;
+    }
+
+    &:nth-child(5n) {
+      margin-right: 0;
+    }
+  }
+}
+
+.demo-drawer__content {
+  padding: 0 30px;
+}
+
+.demo-image__preview {
+  display: inline-block;
+  .el-image {
+    width: 50px;
+    height: 50px;
+  }
+}
+
+.logistics {
+  align-items: center;
+  padding: 10px 0px;
+  .logistics_img {
+    width: 45px;
+    height: 45px;
+    margin-right: 12px;
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+  .logistics_cent {
+    span {
+      display: block;
+      font-size: 12px;
+    }
+  }
+}
+
+.trees-coadd {
+  width: 100%;
+  height: 400px;
+  border-radius: 4px;
+  overflow: hidden;
+  .scollhide {
+    width: 100%;
+    height: 100%;
+    overflow: auto;
+    margin-left: 18px;
+    padding: 10px 0 10px 0;
+    box-sizing: border-box;
+    .content {
+      font-size: 12px;
+    }
+
+    .time {
+      font-size: 12px;
+      color: #2d8cf0;
+    }
+  }
+}
+
+.description {
+  &-term {
+    display: table-cell;
+    padding-bottom: 5px;
+    line-height: 20px;
+    width: 50%;
+    font-size: 12px;
+    color: #606266;
+  }
+  ::v-deep .el-divider--horizontal {
+    margin: 12px 0 !important;
+  }
+}
+</style>

+ 18 - 18
mer_plat_admin/src/views/order/components/secondHandOrderDetail.vue → mer_plat_admin/src/views/secondhand/order/components/refundOrderDetail.vue

@@ -96,7 +96,7 @@
                   <div class="lang">退回运费:</div>
                   <div class="value">{{ refundInfo.refundFreightFee }}</div>
                 </li>
-                <li v-show="refundInfo.refundStatus === 2 || refundInfo.refundStatus === 3" class="item">
+                <!--li v-show="refundInfo.refundStatus === 2 || refundInfo.refundStatus === 3" class="item">
                   <div class="lang">退一级佣金:</div>
                   <div class="value">{{ refundInfo.refundFirstBrokerageFee }}</div>
                 </li>
@@ -111,7 +111,7 @@
                 <li v-show="refundInfo.refundStatus === 2 || refundInfo.refundStatus === 3" class="item">
                   <div class="lang">退二级返佣:</div>
                   <div class="value">{{ refundInfo.refundSecondBrokerageFee }}</div>
-                </li>
+                </li-->
               </ul>
             </div>
             <!-- 退款流程信息-->
@@ -127,7 +127,7 @@
                     "
                     finish-status="success"
                   >
-                    <el-step title="直接退款-家" v-if="refundInfo.promoterType === 'merchant'">
+                    <el-step title="直接退款-家" v-if="refundInfo.promoterType === 'merchant'">
                       <template slot="description">
                         <div class="mb10">
                           {{ refundInfo.refundTime }}
@@ -190,7 +190,7 @@
                       </template>
                     </el-step>
                     <el-step
-                      title="商家审核-商家"
+                      title="卖家审核-卖家"
                       v-if="
                         refundInfo.statusList &&
                         refundInfo.statusList.length &&
@@ -278,7 +278,7 @@
                       </template>
                     </el-step>
                     <el-step
-                      title="商家确认收货-商家"
+                      title="卖家确认收货-卖家"
                       v-if="
                         refundInfo.refundStatus !== 1 &&
                         refundInfo.refundStatus !== 6 &&
@@ -298,7 +298,7 @@
                       </template>
                     </el-step>
                     <el-step
-                      title="商品拒绝收货-家"
+                      title="商品拒绝收货-家"
                       v-if="
                         refundInfo.statusList &&
                         refundInfo.statusList.length &&
@@ -376,7 +376,7 @@
                       </template>
                     </el-step>
                     <el-step
-                      :title="refundInfo.promoterType === 'user' ? '退款成功' : '退款成功-家直接退款'"
+                      :title="refundInfo.promoterType === 'user' ? '退款成功' : '退款成功-家直接退款'"
                       v-if="
                         refundInfo.refundStatus !== 1 &&
                         refundInfo.refundStatus !== 6 &&
@@ -396,7 +396,7 @@
                       </template>
                     </el-step>
                     <el-step
-                      title="商家审核-商家"
+                      title="卖家审核-卖家"
                       v-if="
                         refundInfo.refundStatus !== 1 &&
                         refundInfo.refundStatus !== 2 &&
@@ -417,7 +417,7 @@
                     >
                     </el-step>
                     <el-step
-                      title="商家确认收货-商家"
+                      title="卖家确认收货-卖家"
                       v-if="
                         refundInfo.refundStatus !== 1 &&
                         refundInfo.refundStatus !== 2 &&
@@ -454,7 +454,7 @@
               </ul>
             </div>
             <div class="detailSection">
-              <div class="title">家备注</div>
+              <div class="title">家备注</div>
               <ul class="list">
                 <li class="item">
                   <div>{{ refundInfo.merRemark | filterEmpty }}</div>
@@ -485,7 +485,7 @@
               <ul class="list">
                 <li class="item">
                   <div class="lang">配送方式:</div>
-                  <div class="value">{{ refundInfo.orderInfoVo.shippingType === 1 ? '商家配送' :(refundInfo.orderInfoVo.shippingType === 2? '到店自提':'外卖配送' ) }}</div>
+                  <div class="value">{{ refundInfo.orderInfoVo.shippingType === 1 ? '商家配送' :(refundInfo.orderInfoVo.shippingType === 2? '上门自提':'外卖配送' ) }}</div>
                 </li>
                 <li class="item">
                   <div class="lang">收货电话:</div>
@@ -548,19 +548,19 @@
                   <div class="lang">商品总价:</div>
                   <div class="value">¥{{ refundInfo.orderInfoVo.proTotalPrice }}</div>
                 </li>
-                <li class="item">
+                <!--li class="item">
                   <div class="lang">平台优惠金额:</div>
                   <div class="value">¥{{ refundInfo.orderInfoVo.platCouponPrice }}</div>
                 </li>
                 <li class="item">
                   <div class="lang">赠送积分:</div>
                   <div class="value">¥{{ refundInfo.orderInfoVo.gainIntegral }}</div>
-                </li>
+                </li-->
                 <li class="item">
                   <div class="lang">实际支付:</div>
                   <div class="value">¥{{ refundInfo.orderInfoVo.payPrice }}</div>
                 </li>
-                <li class="item">
+                <!--li class="item">
                   <div class="lang">扣除抵扣积分:</div>
                   <div class="value">{{ refundInfo.orderInfoVo.useIntegral }}</div>
                 </li>
@@ -579,7 +579,7 @@
                 <li class="item">
                   <div class="lang">积分抵扣金额:</div>
                   <div class="value">¥{{ refundInfo.orderInfoVo.integralPrice }}</div>
-                </li>
+                </li-->
               </ul>
             </div>
             <div class="detailSection">
@@ -591,7 +591,7 @@
               </ul>
             </div>
             <div class="detailSection">
-              <div class="title">家备注</div>
+              <div class="title">家备注</div>
               <ul class="list">
                 <li class="item">
                   <div class="value productName">{{ refundInfo.orderInfoVo.merchantRemark | filterEmpty }}</div>
@@ -606,11 +606,11 @@
   </div>
 </template>
 <script setup>
-import { orderRefundCompulsoryApi, refundMarkApi, refundOrderDetailApi } from '@/api/order';
+import { orderRefundCompulsoryApi, refundMarkApi, refundOrderDetailApi } from '@/api/secondHand';
 import { checkPermi } from '@/utils/permission'; // 权限判断函数
 import { filterEmpty, refundStatusFilter } from '@/filters';
 export default {
-  name: 'secondHandOrderDetail',
+  name: 'refundOrderDetail',
   props: {
     //退款单号
     refundOrderNo: {

+ 20 - 0
mer_plat_admin/src/views/secondhand/order/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div>
+    <router-view />
+  </div>
+</template>
+
+<script>
+// +---------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +---------------------------------------------------------------------
+// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
+// +---------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +---------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +---------------------------------------------------------------------
+export default {};
+</script>
+
+<style scoped></style>

+ 25 - 18
mer_plat_admin/src/views/order/secondHand.vue → mer_plat_admin/src/views/secondhand/order/list.vue

@@ -48,7 +48,14 @@
             <UserSearchInput v-model="tableFrom" />
           </el-form-item>
           <el-form-item label="商户名称:">
-            <merchant-name @getMerId="getMerId" :merIdChecked="tableFrom.merId"></merchant-name>
+            <el-input
+              v-model.trim="tableFrom.merName"
+              placeholder="请输入商户名称"
+              class="selWidth"
+              size="small"
+              clearable
+              @keyup.enter.native="handleSearchList"
+            />
           </el-form-item>
           <el-form-item>
             <el-button type="primary" size="small" @click="handleSearchList">查询</el-button>
@@ -123,17 +130,17 @@
             <span class="textE93323 tag-background notStartTag tag-padding" v-if="scope.row.refundStatus === 3"
               >已退款</span
             >
-            <span
-              :class="scope.row.status < 5 ? 'doingTag' : 'endTag'"
-              class="tag-background tag-padding"
-              v-else-if="
-                scope.row.groupBuyRecordStatus == 99 || scope.row.status == 9 || scope.row.groupBuyRecordStatus == 10
-              "
-              >{{ scope.row.status | orderStatusFilter }}</span
-            >
-            <span class="textE93323 tag-background notStartTag tag-padding" v-else>{{
-              scope.row.groupBuyRecordStatus == 0 ? '拼团中' : '拼团失败'
-            }}</span>
+           <span
+             :class="scope.row.status < 5 ? 'doingTag' : 'endTag'"
+             class="tag-background tag-padding"
+             v-else-if="
+               scope.row.groupBuyRecordStatus == 99 || scope.row.status == 9 || scope.row.groupBuyRecordStatus == 10 || scope.row.status < 9
+             "
+             >{{ scope.row.status | orderStatusFilter }}</span
+           >
+           <span class="textE93323 tag-background notStartTag tag-padding" v-else>{{
+             scope.row.groupBuyRecordStatus == 0 ? '拼团中' : '拼团失败'
+           }}</span>
           </template>
         </el-table-column>
         <el-table-column prop="createTime" label="下单时间" min-width="140" v-if="checkedCities.includes('下单时间')" />
@@ -191,13 +198,13 @@
 // +---------------------------------------------------------------------
 // | Author: CRMEB Team <admin@crmeb.com>
 // +---------------------------------------------------------------------
-import { orderStatusNumApi, orderListApi, orderExcelApi } from '@/api/order';
-import detailsFrom from '@/components/OrderDetail';
+import { orderStatusNumApi, orderListApi, orderExcelApi } from '@/api/secondHand';
+import detailsFrom from './components/orderDetail.vue';
 import merchantName from '@/components/merchantName';
 import { isWriteOff } from '@/utils';
 import { checkPermi } from '@/utils/permission'; // 权限判断函数
 export default {
-  name: 'orderSecondHand',
+  name: 'orderlistDetails',
   components: {
     detailsFrom,
     merchantName,
@@ -248,7 +255,7 @@ export default {
         orderNo: '',
         page: 1,
         limit: 20,
-        merId: null,
+        merName: null,
         type: '',
         searchType: 'all',
         content: '',
@@ -283,7 +290,7 @@ export default {
   methods: {
     checkPermi,
     getMerId(id) {
-      this.tableFrom.merId = id;
+      //this.tableFrom.merId = id;
       this.handleSearchList();
     },
     resetForm(formValue) {
@@ -296,7 +303,7 @@ export default {
       this.tableFrom.dateLimit = '';
       this.tableFrom.orderNo = '';
       this.tableFrom.page = 1;
-      this.tableFrom.merId = null;
+      this.tableFrom.merName = null;
       this.tableFrom.type = '';
       this.tableFrom.searchType = 'all';
       this.tableFrom.content = '';

+ 547 - 0
mer_plat_admin/src/views/secondhand/order/refund.vue

@@ -0,0 +1,547 @@
+<template>
+  <div class="divBox relative">
+    <el-card
+      class="box-card"
+      shadow="never"
+      :bordered="false"
+      :body-style="{ padding: 0 }"
+      v-if="checkPermi(['platform:refund:order:status:num'])"
+    >
+      <div class="padding-add">
+        <el-form inline label-position="right" @submit.native.prevent>
+          <el-form-item label="退款单号:">
+            <el-input
+              v-model.trim="tableFrom.refundOrderNo"
+              placeholder="请输入退款单号"
+              class="selWidth"
+              size="small"
+              clearable
+              @keyup.enter.native="handleSearchList"
+            >
+            </el-input>
+          </el-form-item>
+          <el-form-item label="订单编号:" label-width="66px">
+            <el-input
+              v-model.trim="tableFrom.orderNo"
+              placeholder="请输入订单编号"
+              class="selWidth"
+              size="small"
+              clearable
+              @keyup.enter.native="handleSearchList"
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="时间选择:">
+            <el-date-picker
+              v-model="timeVal"
+              value-format="yyyy-MM-dd"
+              format="yyyy-MM-dd"
+              size="small"
+              type="daterange"
+              placement="bottom-end"
+              placeholder="自定义时间"
+              class="selWidth"
+              @change="onchangeTime"
+            />
+          </el-form-item>
+          <el-form-item label="用户搜索:" label-for="nickname">
+            <UserSearchInput v-model="tableFrom" />
+          </el-form-item>
+          <!--el-form-item label="商户名称:">
+            <merchant-name @getMerId="getMerId" :merIdChecked="tableFrom.merId"></merchant-name>
+          </el-form-item-->
+          <el-form-item label="退货物流:" label-width="66px">
+            <el-input
+              v-model.trim="tableFrom.trackingNumber"
+              placeholder="请输入退货物流单号"
+              class="selWidth"
+              size="small"
+              clearable
+              @keyup.enter.native="handleSearchList"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" size="small" @click="handleSearchList">查询</el-button>
+            <el-button size="small" @click="handleReset">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-card>
+    <el-card class="box-card mt14" :body-style="{ padding: '0 20px 20px' }" shadow="never" :bordered="false">
+      <el-tabs class="list-tabs" v-model="tableFrom.refundStatus" @tab-click="handleSearchList">
+        <el-tab-pane name="9" :label="`全部(${orderChartType.all || 0})`"></el-tab-pane>
+        <el-tab-pane name="0" :label="`待审核(${orderChartType.await || 0})`"></el-tab-pane>
+        <el-tab-pane name="2" :label="`退款中(${orderChartType.refunding || 0})`"></el-tab-pane>
+        <el-tab-pane name="4" :label="`用户退货(${orderChartType.awaitReturning || 0})`"></el-tab-pane>
+        <el-tab-pane name="5" :label="`商家待收货(${orderChartType.awaitReceiving || 0})`"></el-tab-pane>
+        <el-tab-pane name="6" :label="`已撤销(${orderChartType.revoke || 0})`"></el-tab-pane>
+        <el-tab-pane name="1" :label="`审核未通过(${orderChartType.reject || 0})`"></el-tab-pane>
+        <el-tab-pane name="3" :label="`已退款(${orderChartType.refunded || 0})`"></el-tab-pane>
+      </el-tabs>
+      <el-table
+        v-loading="listLoading"
+        :data="tableData.data"
+        size="small"
+        class="mt5"
+        highlight-current-row
+        :row-key="
+          (row) => {
+            return row.refundOrderNo;
+          }
+        "
+      >
+        <el-table-column label="退款单号" min-width="185" v-if="checkedCities.includes('退款单号')">
+          <template slot-scope="scope">
+            <div class="acea-row">
+              <span v-show="scope.row.type === 1" class="iconfont icon-shipinhao mr5" style="color: #f6ae02"></span>
+              <span style="display: block" v-text="scope.row.refundOrderNo" />
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="orderNo" label="订单编号" min-width="180" v-if="checkedCities.includes('订单编号')" />
+        <el-table-column
+          prop="userNickName"
+          label="用户昵称"
+          min-width="180"
+          v-if="checkedCities.includes('用户昵称')"
+        />
+        <el-table-column
+          prop="refundPrice"
+          label="退款金额"
+          min-width="100"
+          v-if="checkedCities.includes('退款金额')"
+        />
+        <el-table-column label="退款状态" min-width="100" v-if="checkedCities.includes('退款状态')">
+          <template slot-scope="scope">
+            <span>{{ scope.row.refundStatus | refundStatusFilter }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="售后类型" min-width="100" v-if="checkedCities.includes('售后类型')">
+          <template slot-scope="scope">
+            <span>{{ scope.row.afterSalesType === 1 ? '仅退款' : '退货退款' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="退货类型" min-width="100" v-if="checkedCities.includes('退货类型')">
+          <template slot-scope="scope">
+            <span>{{
+              scope.row.returnGoodsType === 0 ? '不退货' : scope.row.returnGoodsType === 1 ? '快递退回' : '到店退货'
+            }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="强制退款" min-width="100" v-if="checkedCities.includes('强制退款')">
+          <template slot-scope="scope">
+            <span>{{ scope.row.isCompulsoryRefund ? '是' : '不是' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="createTime" label="创建时间" min-width="150" v-if="checkedCities.includes('创建时间')" />
+        <el-table-column width="170" fixed="right">
+          <template slot="header">
+            <p>
+              <span style="padding-right: 5px">操作</span>
+              <i class="el-icon-setting" @click="handleAddItem"></i>
+            </p>
+          </template>
+          <template slot-scope="scope">
+            <a v-hasPermi="['platform:refund:order:detail']" @click="onOrderDetails(scope.row)">详情</a>
+            <el-divider direction="vertical"></el-divider>
+            <a @click="onOrderMark(scope.row)" v-hasPermi="['platform:refund:order:mark']">备注</a>
+            <template
+              v-if="
+                checkPermi(['platform:refund:order:compulsory:refund']) &&
+                (scope.row.refundStatus === 0 || scope.row.refundStatus === 5)
+              "
+            >
+              <el-divider direction="vertical"></el-divider>
+              <a @click="handlerCompulsoryReturn(scope.row)"> 强制退款</a>
+            </template>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="block">
+        <el-pagination
+          background
+          :page-sizes="[20, 40, 60, 80]"
+          :page-size="tableFrom.limit"
+          :current-page="tableFrom.page"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="tableData.total"
+          @size-change="handleSizeChange"
+          @current-change="pageChange"
+        />
+      </div>
+    </el-card>
+    <div class="card_abs" v-show="card_select_show">
+      <template>
+        <div class="cell_ht">
+          <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange"
+            >全选
+          </el-checkbox>
+          <el-button type="text" @click="checkSave()">保存</el-button>
+        </div>
+        <el-checkbox-group v-model="checkedCities" @change="handleCheckedCitiesChange">
+          <el-checkbox v-for="item in columnData" :label="item" :key="item" class="check_cell">{{ item }}</el-checkbox>
+        </el-checkbox-group>
+      </template>
+    </div>
+
+    <!--退款详情-->
+    <refund-order-detail
+      ref="orderDetail"
+      :drawerVisible="drawerVisible"
+      :refundOrderNo="refundOrderNo"
+      v-if="drawerVisible"
+      @onClosedrawerVisible="onClosedrawerVisible"
+      @compulsoryReturnSuccess="handlerCompulsoryReturnSuccess"
+    ></refund-order-detail>
+  </div>
+</template>
+
+<script>
+// +---------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +---------------------------------------------------------------------
+// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
+// +---------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +---------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +---------------------------------------------------------------------
+import {
+  orderDetailApi,
+  refundStatusNumApi,
+  refundListApi,
+  refundMarkApi,
+  orderRefundCompulsoryApi,
+} from '@/api/secondHand';
+import RefundOrderDetail from './components/refundOrderDetail.vue';
+import { orderExcelApi } from '@/api/product';
+import { checkPermi } from '@/utils/permission'; // 权限判断函数
+import merchantName from '@/components/merchantName';
+export default {
+  name: 'orderRefund',
+  components: {
+    RefundOrderDetail,
+    merchantName,
+  },
+  data() {
+    return {
+      RefuseData: {},
+      refundData: {},
+      dialogVisibleJI: false,
+      tableDataLog: {
+        data: [],
+        total: 0,
+      },
+      LogLoading: false,
+      isCreate: 1,
+      editData: null,
+      dialogVisible: false,
+      tableData: {
+        data: [],
+        total: 0,
+      },
+      listLoading: true,
+      tableFrom: {
+        refundStatus: '9',
+        dateLimit: '',
+        orderNo: '',
+        refundOrderNo: '',
+        page: 1,
+        limit: 20,
+        merId: null,
+        searchType: 'all',
+        content: '',
+        trackingNumber: '',
+      },
+      orderChartType: {},
+      timeVal: [],
+      fromList: this.$constants.fromList,
+      selectionList: [],
+      ids: '',
+      orderids: '',
+      cardLists: [],
+      proType: 0,
+      active: false,
+      card_select_show: false,
+      checkAll: false,
+      checkedCities: [
+        '退款单号',
+        '订单编号',
+        '用户昵称',
+        '退款金额',
+        '退款状态',
+        '售后类型',
+        '退货类型',
+        '强制退款',
+        '创建时间',
+      ],
+      columnData: [
+        '退款单号',
+        '订单编号',
+        '用户昵称',
+        '退款金额',
+        '退款状态',
+        '售后类型',
+        '退货类型',
+        '强制退款',
+        '创建时间',
+      ],
+      isIndeterminate: true,
+      drawerVisible: false,
+      refundOrderNo: '', //退款单号
+    };
+  },
+  mounted() {
+    if (checkPermi(['platform:refund:order:page:list'])) this.getList();
+    if (checkPermi(['platform:refund:order:status:num'])) this.getOrderStatusNum();
+  },
+  methods: {
+    checkPermi,
+    getMerId(id) {
+      this.tableFrom.merId = id;
+      this.handleSearchList();
+    },
+    handleReset() {
+      this.tableFrom.refundStatus = '9';
+      this.tableFrom.dateLimit = '';
+      this.tableFrom.orderNo = '';
+      this.tableFrom.refundOrderNo = '';
+      this.tableFrom.page = 1;
+      this.tableFrom.merId = null;
+      this.tableFrom.content = '';
+      this.tableFrom.searchType = 'all';
+      this.tableFrom.trackingNumber = '';
+      this.timeVal = [];
+      this.handleSearchList();
+    },
+    resetForm(formValue) {
+      this.dialogVisible = false;
+    },
+    handleSearchList() {
+      this.tableFrom.page = 1;
+      this.getList();
+      this.getOrderStatusNum();
+    },
+    onClosedrawerVisible() {
+      this.drawerVisible = false;
+    },
+    handlerCompulsoryReturnSuccess() {
+      this.drawerVisible = false;
+      this.getList();
+    },
+    // 详情
+    onOrderDetails(row) {
+      this.refundOrderNo = row.refundOrderNo;
+      this.drawerVisible = true;
+    },
+    getDetail(id) {
+      this.loading = true;
+      orderDetailApi(id)
+        .then((res) => {
+          this.orderDatalist = res;
+          this.loading = false;
+        })
+        .catch(() => {
+          this.orderDatalist = null;
+          this.loading = false;
+        });
+    },
+    // 备注
+    onOrderMark(row) {
+      this.$modalPrompt('textarea', '退款单备注', row.platformRemark).then((V) => {
+        refundMarkApi({ remark: V, refundOrderNo: row.refundOrderNo }).then(() => {
+          this.$message.success('操作成功');
+          this.getList();
+        });
+      });
+    },
+    handlerCompulsoryReturn(row) {
+      this.$confirm(`确定强制退款吗?此操作不可逆,请慎重确认后再操作!`, '强制退款提示', {
+        customClass: 'deleteConfirm',
+        type: 'warning',
+      }).then(async () => {
+        let result = await orderRefundCompulsoryApi(row.refundOrderNo);
+        this.handleSearchList();
+      });
+    },
+    handleSelectionChange(val) {
+      this.selectionList = val;
+      const data = [];
+      this.selectionList.map((item) => {
+        data.push(item.orderNo);
+      });
+      this.ids = data.join(',');
+    },
+    // 选择时间
+    selectChange(tab) {
+      this.timeVal = [];
+      this.tableFrom.page = 1;
+      this.getList();
+      this.getOrderStatusNum();
+    },
+    // 具体日期
+    onchangeTime(e) {
+      this.timeVal = e;
+      this.tableFrom.dateLimit = e ? this.timeVal.join(',') : '';
+      this.tableFrom.page = 1;
+      this.getList();
+      this.getOrderStatusNum();
+    },
+    // 列表
+    getList() {
+      this.listLoading = true;
+      refundListApi(this.tableFrom)
+        .then((res) => {
+          this.tableData.data = res.list || [];
+          this.tableData.total = res.total;
+          this.listLoading = false;
+          this.checkedCities = this.$cache.local.has('order_refund_stroge')
+            ? this.$cache.local.getJSON('order_refund_stroge')
+            : this.checkedCities;
+        })
+        .catch(() => {
+          this.listLoading = false;
+        });
+    },
+    // 获取各状态数量
+    getOrderStatusNum() {
+      let data = Object.assign({}, this.tableFrom);
+      delete data.page;
+      delete data.limit;
+      delete data.refundStatus;
+      refundStatusNumApi(data).then((res) => {
+        this.orderChartType = res;
+      });
+    },
+    pageChange(page) {
+      this.tableFrom.page = page;
+      this.getList();
+    },
+    handleSizeChange(val) {
+      this.tableFrom.limit = val;
+      this.getList();
+    },
+    exports() {
+      let data = {
+        dateLimit: this.tableFrom.dateLimit,
+        orderNo: this.tableFrom.orderNo,
+        refundStatus: this.tableFrom.status,
+        type: this.tableFrom.type,
+      };
+      orderExcelApi(data).then((res) => {
+        window.open(res.fileName);
+      });
+    },
+    handleAddItem() {
+      if (this.card_select_show) {
+        this.$set(this, 'card_select_show', false);
+      } else if (!this.card_select_show) {
+        this.$set(this, 'card_select_show', true);
+      }
+    },
+    handleCheckAllChange(val) {
+      this.checkedCities = val ? this.columnData : [];
+      this.isIndeterminate = false;
+    },
+    handleCheckedCitiesChange(value) {
+      let checkedCount = value.length;
+      this.checkAll = checkedCount === this.columnData.length;
+      this.isIndeterminate = checkedCount > 0 && checkedCount < this.columnData.length;
+    },
+    checkSave() {
+      this.$set(this, 'card_select_show', false);
+      this.$modal.loading('正在保存到本地,请稍候...');
+      this.$cache.local.setJSON('order_refund_stroge', this.checkedCities);
+      setTimeout(this.$modal.closeLoading(), 1000);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.red {
+  color: #ed4014;
+}
+
+.el-table__body {
+  width: 100%;
+  table-layout: fixed !important;
+}
+
+.demo-table-expand {
+  ::v-deeplabel {
+    width: 83px !important;
+  }
+}
+
+.refunding {
+  span {
+    display: block;
+  }
+}
+
+.el-icon-arrow-down {
+  font-size: 12px;
+}
+
+.tabBox_tit {
+  font-size: 12px !important;
+  /*margin: 0 2px 0 10px;*/
+  letter-spacing: 1px;
+  /*padding: 5px 0;*/
+  box-sizing: border-box;
+}
+
+.text_overflow {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  max-width: 400px;
+}
+
+.pup_card {
+  width: 200px;
+  border-radius: 5px;
+  padding: 5px;
+  box-sizing: border-box;
+  font-size: 12px;
+  line-height: 16px;
+}
+
+.flex-column {
+  display: flex;
+  flex-direction: column;
+}
+
+.relative {
+  position: relative;
+}
+
+.card_abs {
+  position: absolute;
+  padding-bottom: 15px;
+  top: 340px;
+  right: 40px;
+  width: 200px;
+  background: #fff;
+  z-index: 99999;
+  box-shadow: 0px 0px 14px 0px rgba(0, 0, 0, 0.1);
+}
+
+.cell_ht {
+  height: 50px;
+  padding: 15px 20px;
+  box-sizing: border-box;
+  border-bottom: 1px solid #eeeeee;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.check_cell {
+  width: 100%;
+  padding: 15px 20px 0;
+}
+
+::v-deep .el-checkbox__input.is-checked + .el-checkbox__label {
+  color: #606266;
+}
+</style>

+ 238 - 0
mer_plat_admin/src/views/secondhand/topics/index.vue

@@ -0,0 +1,238 @@
+<template>
+  <div class="divBox relative">
+    <el-card
+      :bordered="false"
+      shadow="never"
+      class="ivu-mt"
+      :body-style="{ padding: 0 }"
+      v-hasPermi="['platform:community:topic:page:list']"
+    >
+      <div class="padding-add">
+        <el-form :inline="true" @submit.native.prevent>
+          <el-form-item label="话题名称:">
+            <el-input
+              v-model.trim="name"
+              placeholder="请输入话题名称"
+              @keyup.enter.native="getList(1)"
+              class="selWidth"
+              size="small"
+              clearable
+            ></el-input>
+          </el-form-item>
+          <el-form-item label="推荐状态:">
+            <el-select
+              v-model="tableFrom.isHot"
+              placeholder="请选择推荐状态"
+              @change="getList(1)"
+              size="small"
+              class="selWidth"
+              clearable
+            >
+              <el-option label="推荐" value="1"></el-option>
+              <el-option label="不推荐" value="0"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" size="small" @click="getList(1)">查询</el-button>
+            <el-button size="small" @click="reset()">重置</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-card>
+    <el-card class="box-card mt14" :body-style="{ padding: '20px' }" :bordered="false" shadow="never">
+      <el-button type="primary" size="small" v-hasPermi="['platform:community:topic:add']" @click="handlerOpenEdit(0)"
+        >添加社区话题</el-button
+      >
+      <el-table
+        v-loading="listLoading"
+        :data="tableData.data"
+        size="small"
+        height="500px"
+        :highlight-current-row="true"
+        class="mt20"
+      >
+        <el-table-column prop="id" label="ID" min-width="50" />
+        <el-table-column label="话题名称" prop="name" min-width="100" :show-overflow-tooltip="true"> </el-table-column>
+        <el-table-column prop="countUse" label="文章数" min-width="100" />
+        <el-table-column label="添加时间" min-width="120">
+          <template slot-scope="scope">
+            <span>{{ scope.row.createTime }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="是否推荐" fixed="right" min-width="90">
+          <template slot-scope="scope">
+            <el-switch
+              v-if="checkPermi(['platform:community:topic:recommend:switch'])"
+              v-model="scope.row.isHot"
+              :active-value="1"
+              :inactive-value="0"
+              active-text="是"
+              inactive-text="否"
+              @click.native="onchangeIsShow(scope.row)"
+            />
+            <div v-else>{{ scope.row.isHot === 1 ? '推荐' : '不推荐' }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="100" fixed="right">
+          <template slot-scope="scope">
+            <a @click="handlerOpenEdit(1, scope.row)" v-hasPermi="['platform:community:topic:update']">编辑</a>
+            <el-divider direction="vertical"></el-divider>
+            <a @click="handlerOpenDel(scope.row)" v-hasPermi="['platform:community:topic:delete']">删除</a>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="block">
+        <el-pagination
+          background
+          :page-sizes="[20, 40, 60, 80]"
+          :page-size="tableFrom.limit"
+          :current-page="tableFrom.page"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="tableData.total"
+          @size-change="handleSizeChange"
+          @current-change="pageChange"
+        />
+      </div>
+    </el-card>
+  </div>
+</template>
+<script>
+// +---------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +---------------------------------------------------------------------
+// | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
+// +---------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +---------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +---------------------------------------------------------------------
+import * as community from '@/api/community';
+import { checkPermi } from '@/utils/permission'; // 权限判断函数
+export default {
+  data() {
+    return {
+      form: {},
+      rules: {},
+      tableFrom: {
+        page: 1,
+        limit: 20,
+        name: '',
+        isHot: '',
+      },
+      name: '',
+      tableData: {
+        data: [],
+        total: 0,
+      },
+      listLoading: false,
+      keyNum: 0,
+      id: 0,
+    };
+  },
+  mounted() {
+    if (checkPermi(['platform:community:topic:page:list'])) this.getList();
+  },
+  methods: {
+    checkPermi,
+    onchangeIsShow(row) {
+      community.communityTopicRecommendApi(row.id).then((res) => {
+        this.$message.success('操作成功');
+        this.getList();
+      });
+    },
+    // 列表
+    getList(num) {
+      this.tableFrom.page = num ? num : this.tableFrom.page;
+      this.tableFrom.name = encodeURIComponent(this.name);
+      this.listLoading = true;
+      community
+        .communityTopicListApi(this.tableFrom)
+        .then((res) => {
+          this.tableData.data = res.list;
+          this.tableData.total = res.total;
+          this.listLoading = false;
+        })
+        .catch((res) => {
+          this.listLoading = false;
+        });
+    },
+    reset() {
+      this.tableFrom.name = '';
+      this.tableFrom.isHot = '';
+      this.name = '';
+      this.getList(1);
+    },
+    pageChange(page) {
+      this.tableFrom.page = page;
+      this.getList();
+    },
+    handleSizeChange(val) {
+      this.tableFrom.limit = val;
+      this.getList(1);
+    },
+    handlerOpenEdit(isCreate, editDate) {
+      const _this = this;
+      this.id = editDate ? editDate.id : 0;
+      this.$modalParserFrom(
+        isCreate === 0 ? '新建话题' : '编辑话题',
+        'communityTopics',
+        isCreate,
+        isCreate === 0
+          ? {
+              id: 0,
+              name: '',
+              handlingFee: '',
+            }
+          : Object.assign({}, editDate),
+        function (formValue) {
+          _this.submit(formValue);
+          _this.resetForm(formValue);
+        },
+        (this.keyNum = Math.random()),
+      );
+    },
+    submit(formValue) {
+      const data = {
+        id: this.id,
+        name: formValue.name,
+      };
+      !this.id
+        ? community
+            .communityTopicAddApi(data)
+            .then((res) => {
+              this.$message.success('操作成功');
+              this.$msgbox.close();
+              this.getList();
+            })
+            .catch(() => {
+              this.loading = false;
+            })
+        : community
+            .communityTopicUpdateApi(data)
+            .then((res) => {
+              this.$message.success('操作成功');
+              this.$msgbox.close();
+              this.getList();
+            })
+            .catch(() => {
+              this.loading = false;
+            });
+    },
+    handlerOpenDel(rowData) {
+      this.$modalSure('删除当前话题吗?删除话题之后,与此相关的文章将取消关联话题!').then(() => {
+        community.communityTopicDelApi(rowData.id).then((data) => {
+          this.$message.success('删除话题成功');
+          if (this.tableData.data.length === 1 && this.tableFrom.page > 1)
+            this.tableFrom.page = this.tableFrom.page - 1;
+          this.getList();
+        });
+      });
+    },
+  },
+};
+</script>
+<style>
+.alert_title {
+  margin-right: 10px;
+}
+</style>