فهرست منبع

卓美销售端提交

yjwang 2 هفته پیش
والد
کامیت
5aa8bdd711

+ 8 - 1
src/api/hisStore/storeAfterSales.js

@@ -52,7 +52,14 @@ export function exportStoreAfterSales(query) {
   })
 }
 
-
+// 查询售后原因列表
+export function listRefundReason(query) {
+  return request({
+    url: '/store/store/refundReason/list',
+    method: 'get',
+    params: query
+  })
+}
 
 export function cancel(data) {
   return request({

+ 3 - 2
src/views/hisStore/components/productAfterSalesOrder.vue

@@ -213,7 +213,7 @@
             </el-option>
           </el-select>
         </el-form-item>
-        <el-form-item label="二级原因" prop="reasonId2">
+        <el-form-item label="二级原因" v-if="form.reasonId1 != null" prop="reasonId2">
           <el-select v-model="form.reasonId2" placeholder="请选择二级原因" style="width: 100%">
             <el-option
               v-for="item in reason2List"
@@ -227,6 +227,7 @@
           <el-input
             type="textarea"
             :rows="3"
+            maxlength="200"
             placeholder="请输入审核备注"
             v-model="form.auditRemark">
           </el-input>
@@ -266,7 +267,7 @@
 </template>
 
 <script>
-import {getStoreAfterSales,cancel,refund,audit1,audit2,updateStoreAfterSales} from "@/api/hisStore/storeAfterSales";
+import {getStoreAfterSales,cancel,refund,audit1,audit2,updateStoreAfterSales,listRefundReason} from "@/api/hisStore/storeAfterSales";
 
 import productOrder from "./productOrder";
 export default {

+ 310 - 137
src/views/hisStore/refundReason/index.vue

@@ -1,141 +1,176 @@
 <template>
-  <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="一级原因" prop="reasonName">
-        <el-input
-          v-model="queryParams.reasonName"
-          placeholder="请输入一级原因名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
-      </el-form-item>
-    </el-form>
-
-    <el-row :gutter="10" class="mb8">
-      <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['store:refundReason:add']"
-        >新增一级原因</el-button>
-      </el-col>
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
-    </el-row>
+  <div class="app-container refund-reason-page">
+    <el-card shadow="never" class="refund-reason-page__filter">
+      <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="80px">
+        <el-form-item label="一级原因" prop="reasonName">
+          <el-input
+            v-model="queryParams.reasonName"
+            placeholder="请输入一级原因名称"
+            clearable
+            size="small"
+            style="width: 220px"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+      <p v-show="showSearch" class="refund-reason-page__hint">
+        <i class="el-icon-info" />
+        点击每行左侧箭头展开查看二级原因;同一时间仅展开一行,便于逐层浏览。
+      </p>
+    </el-card>
 
-    <el-table
-      v-loading="loading"
-      :data="refundReasonList"
-      row-key="id"
-      @expand-change="handleExpandChange"
-    >
-      <el-table-column type="expand">
-        <template slot-scope="props">
-          <el-table
-            :data="props.row.children"
-            style="margin-left: 50px; width: calc(100% - 50px)"
-            v-loading="props.row.loading"
-          >
-            <el-table-column label="序号" type="index" width="80" align="center" />
-            <el-table-column label="二级原因" prop="reasonName" />
-            <el-table-column label="状态" align="center" prop="status" width="100">
-              <template slot-scope="scope">
-                <el-tag v-if="scope.row.status === 1" type="success">正常</el-tag>
-                <el-tag v-else type="danger">禁用</el-tag>
-              </template>
-            </el-table-column>
-            <el-table-column label="操作" align="center" width="200">
-              <template slot-scope="scope">
-                <el-button
-                  size="mini"
-                  type="text"
-                  icon="el-icon-edit"
-                  @click="handleUpdateChild(scope.row, props.row)"
-                  v-hasPermi="['store:refundReason:edit']"
-                >修改</el-button>
-                <el-button
-                  size="mini"
-                  type="text"
-                  icon="el-icon-delete"
-                  @click="handleDeleteChild(scope.row, props.row)"
-                  v-hasPermi="['store:refundReason:remove']"
-                >删除</el-button>
-              </template>
-            </el-table-column>
-          </el-table>
-        </template>
-      </el-table-column>
-      <el-table-column label="序号" type="index" width="80" align="center" />
-      <el-table-column label="一级原因" prop="reasonName" />
-      <el-table-column label="二级原因数量" align="center" width="120">
-        <template slot-scope="scope">
-          {{ scope.row.childrenCount || 0 }}
-        </template>
-      </el-table-column>
-      <el-table-column label="状态" align="center" prop="status" width="100">
-        <template slot-scope="scope">
-          <el-tag v-if="scope.row.status === 1" type="success">正常</el-tag>
-          <el-tag v-else type="danger">禁用</el-tag>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="280">
-        <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['store:refundReason:edit']"
-          >编辑</el-button>
+    <el-card shadow="never" class="refund-reason-page__table-card">
+      <el-row :gutter="10" class="mb8">
+        <el-col :span="1.5">
           <el-button
-            size="mini"
-            type="text"
+            type="primary"
+            plain
             icon="el-icon-plus"
-            @click="handleAddChild(scope.row)"
-            v-hasPermi="['store:refundReason:add']"
-          >新增二级原因</el-button>
-          <el-button
             size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['store:refundReason:remove']"
-          >删除</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
+            @click="handleAdd"
+            v-hasPermi="['store:refundReason:add']"
+          >新增一级原因</el-button>
+        </el-col>
+        <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      </el-row>
 
-    <pagination
-      v-show="total > 0"
-      :total="total"
-      :page.sync="queryParams.pageNum"
-      :limit.sync="queryParams.pageSize"
-      @pagination="getList"
-    />
+      <el-table
+        ref="refundReasonTable"
+        v-loading="loading"
+        :data="refundReasonList"
+        row-key="id"
+        :expand-row-keys="expandedRowKeys"
+        border
+        stripe
+        size="small"
+        class="refund-reason-table"
+        :header-cell-style="{ background: '#f5f7fa', color: '#606266' }"
+        @expand-change="handleExpandChange"
+      >
+        <el-table-column type="expand" width="46">
+          <template slot-scope="props">
+            <div class="refund-expand-panel">
+              <div class="refund-expand-panel__head">
+                <span class="refund-expand-panel__title">
+                  <i class="el-icon-tickets" />
+                  下属二级原因
+                </span>
+                <span class="refund-expand-panel__parent">「{{ props.row.reasonName }}」</span>
+                <el-tag size="mini" type="info" effect="plain">共 {{ props.row.childrenCount || 0 }} 条</el-tag>
+              </div>
+              <el-table
+                :key="'refund-child-' + props.row.id"
+                class="refund-reason-nested-table"
+                row-key="id"
+                :data="props.row.children"
+                size="mini"
+                border
+                v-loading="props.row.loading"
+                empty-text="暂无二级原因,可在该行操作列点击「新增二级原因」进行维护"
+              >
+                <el-table-column label="序号" type="index" width="56" align="center" />
+                <el-table-column label="二级原因" prop="reasonName" min-width="160" show-overflow-tooltip />
+                <el-table-column label="状态" align="center" prop="status" width="88">
+                  <template slot-scope="scope">
+                    <el-tag v-if="scope.row.status === 1" type="success" size="mini">正常</el-tag>
+                    <el-tag v-else type="danger" size="mini">禁用</el-tag>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center" width="168" fixed="right">
+                  <template slot-scope="scope">
+                    <el-button
+                      size="mini"
+                      type="text"
+                      icon="el-icon-edit"
+                      @click="handleUpdateChild(scope.row, props.row)"
+                      v-hasPermi="['store:refundReason:edit']"
+                    >修改</el-button>
+                    <el-button
+                      size="mini"
+                      type="text"
+                      icon="el-icon-delete"
+                      class="refund-text-danger"
+                      @click="handleDeleteChild(scope.row, props.row)"
+                      v-hasPermi="['store:refundReason:remove']"
+                    >删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="序号" type="index" width="60" align="center" />
+        <el-table-column label="一级原因" prop="reasonName" min-width="160" show-overflow-tooltip />
+        <el-table-column label="二级原因数量" align="center" width="110">
+          <template slot-scope="scope">
+            <el-tag size="mini" type="info" effect="plain">{{ scope.row.childrenCount || 0 }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="状态" align="center" prop="status" width="88">
+          <template slot-scope="scope">
+            <el-tag v-if="scope.row.status === 1" type="success" size="small">正常</el-tag>
+            <el-tag v-else type="danger" size="small">禁用</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="280">
+          <template slot-scope="scope">
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-edit"
+              @click="handleUpdate(scope.row)"
+              v-hasPermi="['store:refundReason:edit']"
+            >编辑</el-button>
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-plus"
+              @click="handleAddChild(scope.row)"
+              v-hasPermi="['store:refundReason:add']"
+            >新增二级原因</el-button>
+            <el-button
+              size="mini"
+              type="text"
+              icon="el-icon-delete"
+              class="refund-text-danger"
+              @click="handleDelete(scope.row)"
+              v-hasPermi="['store:refundReason:remove']"
+            >删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
 
-    <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        :page.sync="queryParams.pageNum"
+        :limit.sync="queryParams.pageSize"
+        @pagination="getList"
+      />
+    </el-card>
+
+    <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body custom-class="refund-reason-dialog">
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px" class="refund-reason-form">
         <el-form-item label="原因名称" prop="reasonName">
-          <el-input v-model="form.reasonName" placeholder="请输入原因名称" />
+          <el-input v-model="form.reasonName" placeholder="请输入原因名称" maxlength="100" show-word-limit />
         </el-form-item>
         <el-form-item label="状态" prop="status">
-          <el-select v-model="form.status" placeholder="请选择状态">
+          <el-select v-model="form.status" placeholder="请选择状态" style="width: 100%">
             <el-option label="正常" :value="1" />
             <el-option label="禁用" :value="0" />
           </el-select>
         </el-form-item>
         <el-form-item label="二级原因" v-if="form.typeLevel === 1 && form.id == null">
-          <el-button type="primary" size="mini" @click="addChildReason">添加二级原因</el-button>
-          <div v-for="(item, index) in form.childrenReasons" :key="index" style="margin-top: 10px;">
-            <el-input v-model="item.reasonName" placeholder="请输入二级原因名称" style="width: 400px;" />
-            <el-button type="danger" size="mini" @click="removeChildReason(index)" style="margin-left: 10px;">删除</el-button>
+          <div class="refund-dialog-children">
+            <el-button type="primary" size="mini" icon="el-icon-plus" @click="addChildReason">添加二级原因</el-button>
+            <div v-for="(item, index) in form.childrenReasons" :key="index" class="refund-dialog-children__row">
+              <el-input v-model="item.reasonName" placeholder="请输入二级原因名称" />
+              <el-button type="danger" size="mini" icon="el-icon-delete" @click="removeChildReason(index)">删除</el-button>
+            </div>
           </div>
         </el-form-item>
       </el-form>
@@ -167,6 +202,7 @@ export default {
         typeLevel: 1
       },
       form: {},
+      expandedRowKeys: [],
       rules: {
         reasonName: [
           { required: true, message: "原因名称不能为空", trigger: "blur" }
@@ -181,7 +217,14 @@ export default {
     this.getList();
   },
   methods: {
-    getList() {
+    normalizeGetListArg(arg) {
+      if (arg != null && typeof arg === "object") {
+        return null;
+      }
+      return arg != null ? arg : null;
+    },
+    getList(arg) {
+      const syncChildrenParentId = this.normalizeGetListArg(arg);
       this.loading = true;
       listRefundReason(this.queryParams).then(response => {
         this.refundReasonList = response.rows.map(item => {
@@ -193,16 +236,43 @@ export default {
         });
         this.total = response.total;
         this.loading = false;
+        if (syncChildrenParentId != null) {
+          const r = this.refundReasonList.find(x => x.id == syncChildrenParentId);
+          this.expandedRowKeys = r ? [r.id] : [];
+          this.$nextTick(() => {
+            this.reloadRowChildren(syncChildrenParentId);
+          });
+        } else {
+          this.expandedRowKeys = [];
+        }
       });
     },
-    handleExpandChange(row, expandedRows) {
-      if (expandedRows.find(item => item.id === row.id)) {
-        row.loading = true;
-        getChildrenByParentId(row.id).then(response => {
-          row.children = response.data;
-          row.childrenCount = response.data.length;
+    reloadRowChildren(parentId) {
+      const row = this.refundReasonList.find(r => r.id == parentId);
+      if (!row) {
+        return;
+      }
+      row.loading = true;
+      getChildrenByParentId(parentId)
+        .then(response => {
+          const list = response.data || [];
+          row.children = list;
+          row.childrenCount = list.length;
+        })
+        .finally(() => {
           row.loading = false;
         });
+    },
+    handleExpandChange(row, expandedRows) {
+      const isExpanded = expandedRows.some(r => r.id == row.id);
+      if (isExpanded) {
+        this.expandedRowKeys = [row.id];
+        this.reloadRowChildren(row.id);
+      } else {
+        this.expandedRowKeys = [];
+        this.$nextTick(() => {
+          row.children = [];
+        });
       }
     },
     cancel() {
@@ -273,7 +343,8 @@ export default {
             updateRefundReason(this.form).then(response => {
               this.msgSuccess("修改成功");
               this.open = false;
-              this.getList();
+              const syncId = this.form.typeLevel === 2 ? this.form.parentId : this.form.id;
+              this.getList(syncId);
             });
           } else {
             addRefundReason(this.form).then(response => {
@@ -293,7 +364,7 @@ export default {
                   Promise.all(promises).then(() => {
                     this.msgSuccess("新增成功");
                     this.open = false;
-                    this.getList();
+                    this.getList(parentId);
                   });
                 } else {
                   this.msgSuccess("新增成功");
@@ -303,7 +374,8 @@ export default {
               } else {
                 this.msgSuccess("新增成功");
                 this.open = false;
-                this.getList();
+                const syncId = this.form.typeLevel === 2 ? this.form.parentId : null;
+                this.getList(syncId);
               }
             });
           }
@@ -330,13 +402,114 @@ export default {
       }).then(() => {
         return delRefundReason(row.id);
       }).then(() => {
-        getChildrenByParentId(parent.id).then(response => {
-          parent.children = response.data;
-          parent.childrenCount = response.data.length;
-        });
+        this.reloadRowChildren(parent.id);
         this.msgSuccess("删除成功");
       }).catch(() => {});
     }
   }
 };
 </script>
+
+<style scoped>
+.refund-reason-page__filter {
+  margin-bottom: 12px;
+}
+
+.refund-reason-page__filter >>> .el-card__body {
+  padding-bottom: 8px;
+}
+
+.refund-reason-page__hint {
+  margin: 0 0 4px;
+  padding: 8px 12px;
+  font-size: 12px;
+  line-height: 1.5;
+  color: #909399;
+  background: #f4f8ff;
+  border-radius: 4px;
+  border: 1px solid #d9ecff;
+}
+
+.refund-reason-page__hint .el-icon-info {
+  margin-right: 6px;
+  color: #409eff;
+}
+
+.refund-reason-page__table-card >>> .el-card__body {
+  padding-top: 16px;
+}
+
+.refund-reason-table >>> .el-table__expanded-cell {
+  padding: 0;
+  background: transparent;
+}
+
+.refund-expand-panel {
+  padding: 14px 16px 16px 20px;
+  margin: 4px 12px 12px 8px;
+  background: linear-gradient(180deg, #f8fafc 0%, #f0f4f8 100%);
+  border-radius: 6px;
+  border: 1px solid #e4e7ed;
+  border-left: 3px solid #409eff;
+  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8);
+}
+
+.refund-expand-panel__head {
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+  gap: 10px;
+  margin-bottom: 12px;
+}
+
+.refund-expand-panel__title {
+  font-size: 13px;
+  font-weight: 600;
+  color: #303133;
+}
+
+.refund-expand-panel__title .el-icon-tickets {
+  margin-right: 6px;
+  color: #409eff;
+}
+
+.refund-expand-panel__parent {
+  font-size: 12px;
+  color: #606266;
+}
+
+.refund-reason-nested-table {
+  border-radius: 4px;
+  overflow: hidden;
+}
+
+/* 避免展开行内嵌套表格误渲染展开列,出现「多一个小箭头」 */
+.refund-reason-nested-table >>> .el-table__expand-column {
+  display: none !important;
+  width: 0 !important;
+  min-width: 0 !important;
+}
+
+.refund-text-danger {
+  color: #f56c6c !important;
+}
+
+.refund-dialog-children__row {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  margin-top: 10px;
+}
+
+.refund-dialog-children__row .el-input {
+  flex: 1;
+  max-width: 400px;
+}
+</style>
+
+<style>
+.refund-reason-dialog .el-dialog__body {
+  padding-top: 10px;
+  padding-bottom: 8px;
+}
+</style>

+ 1 - 4
src/views/hisStore/storeAfterSales/index.vue

@@ -188,9 +188,6 @@
               <div prop="serviceType" v-for="(item, index) in serviceTypeOptions"    v-if="scope.row.serviceType==item.dictValue">{{item.dictLabel}}</div>
           </template>
       </el-table-column>
-      <el-table-column label="售后原因一级" align="center" prop="reasonValue1" />
-      <el-table-column label="售后原因二级" align="center" prop="reasonValue2" />
-      <el-table-column label="售后备注" align="center" prop="auditRemark" />
       <el-table-column label="申请原因" align="center" prop="reasons" />
       <el-table-column label="说明" align="center" prop="explains" />
       <el-table-column label="状态" align="center" prop="status" >
@@ -200,7 +197,7 @@
       </el-table-column>
       <el-table-column label="售后状态" align="center" prop="salesStatus" >
           <template slot-scope="scope">
-              <div prop="status" v-for="(item, index) in salesStatusOptions"    v-if="scope.row.salesStatus==item.dictValue">{{item.dictLabel}}</div>
+              <div prop="status" v-for="(item, index) in  salesStatusOptions"    v-if="scope.row.salesStatus==item.dictValue">{{item.dictLabel}}</div>
           </template>
       </el-table-column>
       <el-table-column label="订单状态" align="center" prop="orderStatus" >