فهرست منبع

外部订单财务管理

wangxy 3 روز پیش
والد
کامیت
7976f2f8e6

+ 8 - 0
src/api/company/companyDept.js

@@ -41,6 +41,14 @@ export function selectDeptTree(query) {
   })
 }
 
+export function selectDeptTreeByCompanyId(companyId) {
+  return request({
+    url: '/company/companyDept/selectDeptTreeByCompanyId',
+    method: 'get',
+    params: { companyId }
+  })
+}
+
 export function myDeptTreeselect() {
   return request({
     url: '/company/companyDept/myDeptTreeselect',

+ 8 - 0
src/api/store/externalOrder.js

@@ -67,3 +67,11 @@ export function syncExternalOrderExpress(orderId) {
   })
 }
 
+export function editExternalOrder(data) {
+  return request({
+    url: '/store/externalOrder/edit',
+    method: 'post',
+    data: data
+  })
+}
+

+ 43 - 0
src/api/store/financeOrder.js

@@ -0,0 +1,43 @@
+import request from '@/utils/request'
+
+export function listFinanceOrder(query) {
+  return request({
+    url: '/store/financeOrder/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function editFinanceOrder(data) {
+  return request({
+    url: '/store/financeOrder/edit',
+    method: 'post',
+    data: data
+  })
+}
+
+export function exportFinanceOrder(query) {
+  return request({
+    url: '/store/financeOrder/export',
+    method: 'get',
+    params: query
+  })
+}
+
+// 下载导入模板
+export function downloadFinanceImportTemplate() {
+  return request({
+    url: '/store/financeOrder/importTemplate',
+    method: 'get'
+  })
+}
+
+// 导入回款数据
+export function importFinanceOrder(data) {
+  return request({
+    url: '/store/financeOrder/importData',
+    method: 'post',
+    data: data,
+    headers: { 'Content-Type': 'multipart/form-data' }
+  })
+}

+ 19 - 0
src/api/store/rejectNoReturn.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+// 查询拒收未还货列表
+export function listRejectNoReturn(query) {
+  return request({
+    url: '/store/rejectNoReturn/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 导出拒收未还货
+export function exportRejectNoReturn(query) {
+  return request({
+    url: '/store/rejectNoReturn/export',
+    method: 'get',
+    params: query
+  })
+}

+ 37 - 0
src/api/store/rejectReport.js

@@ -0,0 +1,37 @@
+import request from '@/utils/request'
+
+// 查询拒收明细报表订单维度列表
+export function listRejectOrderReport(query) {
+  return request({
+    url: '/store/rejectReport/orderList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 导出拒收明细报表订单维度
+export function exportRejectOrderReport(query) {
+  return request({
+    url: '/store/rejectReport/orderExport',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询拒收明细报表产品维度列表
+export function listRejectProductReport(query) {
+  return request({
+    url: '/store/rejectReport/productList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 导出拒收明细报表产品维度
+export function exportRejectProductReport(query) {
+  return request({
+    url: '/store/rejectReport/productExport',
+    method: 'get',
+    params: query
+  })
+}

+ 37 - 0
src/api/store/returnReport.js

@@ -0,0 +1,37 @@
+import request from '@/utils/request'
+
+// 回款明细 - 订单维度列表
+export function listReturnOrderReport(query) {
+  return request({
+    url: '/store/returnReport/orderList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 回款明细 - 订单维度导出
+export function exportReturnOrderReport(query) {
+  return request({
+    url: '/store/returnReport/orderExport',
+    method: 'get',
+    params: query
+  })
+}
+
+// 回款明细 - 产品维度列表
+export function listReturnProductReport(query) {
+  return request({
+    url: '/store/returnReport/productList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 回款明细 - 产品维度导出
+export function exportReturnProductReport(query) {
+  return request({
+    url: '/store/returnReport/productExport',
+    method: 'get',
+    params: query
+  })
+}

+ 19 - 0
src/api/store/signDetailReport.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+// 查询签收情况明细列表
+export function listSignDetailReport(query) {
+  return request({
+    url: '/store/signDetailReport/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 导出签收情况明细表
+export function exportSignDetailReport(query) {
+  return request({
+    url: '/store/signDetailReport/export',
+    method: 'get',
+    params: query
+  })
+}

+ 19 - 0
src/api/store/signReport.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+// 查询签收未回款列表
+export function listSignOrderReport(query) {
+  return request({
+    url: '/store/signReport/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 导出签收未回款报表
+export function exportSignOrderReport(query) {
+  return request({
+    url: '/store/signReport/export',
+    method: 'get',
+    params: query
+  })
+}

+ 29 - 2
src/views/store/components/addExternalUser.vue

@@ -7,6 +7,21 @@
       <el-form-item label="手机号码" prop="phone">
         <el-input v-model="form.phone" placeholder="请输入手机号码" />
       </el-form-item>
+      <el-form-item label="生日" prop="birthday">
+        <el-date-picker
+          v-model="form.birthday"
+          type="date"
+          placeholder="请选择生日"
+          value-format="timestamp"
+          style="width: 100%;"
+        />
+      </el-form-item>
+      <el-form-item label="性别" prop="sex">
+        <el-radio-group v-model="form.sex">
+          <el-radio :label="1">男</el-radio>
+          <el-radio :label="2">女</el-radio>
+        </el-radio-group>
+      </el-form-item>
       <el-form-item label="状态">
         <el-radio-group v-model="form.status">
           <el-radio :label="item.dictValue" v-for="item in statusOptions" :key="item.dictValue">{{item.dictLabel}}</el-radio>
@@ -28,7 +43,9 @@ export default {
     return {
       statusOptions: [],
       form: {
-        status: "1"
+        status: "1",
+        birthday: null,
+        sex: null
       },
       rules: {
         phone: [
@@ -41,6 +58,12 @@ export default {
         ],
         nickName: [
           { required: true, message: "用户昵称不能为空", trigger: "blur" }
+        ],
+        birthday: [
+          { required: true, message: "生日不能为空", trigger: "change" }
+        ],
+        sex: [
+          { required: true, message: "性别不能为空", trigger: "change" }
         ]
       }
     };
@@ -54,10 +77,14 @@ export default {
     submitForm() {
       this.$refs["form"].validate(valid => {
         if (valid) {
+          const data = { ...this.form };
+          if (data.birthday) {
+            data.birthday = Math.floor(data.birthday / 1000);
+          }
           request({
             url: '/store/user/addExternalUser',
             method: 'post',
-            data: this.form
+            data: data
           }).then(response => {
             if (response.code === 200) {
               this.msgSuccess("新增成功");

+ 4 - 0
src/views/store/components/addExternalUserAddress.vue

@@ -16,6 +16,9 @@
           style="width: 100%;">
         </el-cascader>
       </el-form-item>
+      <el-form-item label="乡镇">
+        <el-input v-model="form.township" placeholder="请输入乡镇(选填)" />
+      </el-form-item>
       <el-form-item label="详细地址" prop="detail">
         <el-input v-model="form.detail" placeholder="请输入收货人详细地址" />
       </el-form-item>
@@ -46,6 +49,7 @@ export default {
         province: null,
         city: null,
         district: null,
+        township: null,
         cityId: null,
         isDefault: '0'
       },

+ 288 - 84
src/views/store/externalOrder/index.vue

@@ -2,12 +2,11 @@
   <div class="app-container">
     <el-tabs v-model="activeStatus" @tab-click="handleTabClick">
       <el-tab-pane label="全部" name="all"></el-tab-pane>
-      <el-tab-pane
-        v-for="item in statusOptions"
-        :key="item.dictValue"
-        :label="item.dictLabel"
-        :name="item.dictValue"
-      ></el-tab-pane>
+      <el-tab-pane label="未审核" name="1"></el-tab-pane>
+      <el-tab-pane label="审核通过" name="2"></el-tab-pane>
+      <el-tab-pane label="已发货" name="3"></el-tab-pane>
+      <el-tab-pane label="已回款" name="4"></el-tab-pane>
+      <el-tab-pane label="已取消" name="-3"></el-tab-pane>
     </el-tabs>
 
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
@@ -96,74 +95,88 @@
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-    <el-table v-loading="loading" border :data="orderList">
-      <el-table-column label="外部订单号" align="center" prop="orderCode" width="180px" />
-      <el-table-column label="所属公司" align="center" prop="companyName" />
-      <el-table-column label="员工" align="center" prop="companyUserName" />
-      <el-table-column label="收货人" align="center" prop="userName" />
-      <el-table-column label="商品名称" align="center" prop="productNames" show-overflow-tooltip />
-      <el-table-column label="应收金额" align="center" prop="receivablePrice" />
-      <el-table-column label="实收金额" align="center" prop="payPrice" />
-      <el-table-column label="支付方式" align="center" prop="payType">
+    <el-table v-loading="loading" border :data="orderList" style="width:100%">
+      <el-table-column label="外部订单号" align="center" prop="orderCode" width="170" fixed="left" />
+      <el-table-column label="会员ID" align="center" prop="userId" width="90" />
+      <el-table-column label="订单状态" align="center" prop="status" width="100">
         <template slot-scope="scope">
-          <dict-tag :options="payTypeOptions" :value="scope.row.payType" />
+          <el-tag v-if="scope.row.status==1" type="warning" size="mini">未审核</el-tag>
+          <el-tag v-else-if="scope.row.status==2" type="success" size="mini">审核通过</el-tag>
+          <el-tag v-else-if="scope.row.status==3" type="primary" size="mini">已发货</el-tag>
+          <el-tag v-else-if="scope.row.status==4" size="mini">已回款</el-tag>
+          <el-tag v-else-if="scope.row.status==-3" type="danger" size="mini">已取消</el-tag>
+          <span v-else>-</span>
         </template>
       </el-table-column>
-      <el-table-column label="创建时间" align="center" prop="externalCreateTime" width="180" />
-      <el-table-column label="订单状态" align="center" prop="status">
+      <el-table-column label="订单类型" align="center" prop="orderType" width="100">
         <template slot-scope="scope">
-          <dict-tag :options="statusOptions" :value="scope.row.status" />
+          <span v-if="scope.row.orderType==1">外部订单</span>
+          <span v-else-if="scope.row.orderType==2">套餐包</span>
+          <span v-else-if="scope.row.orderType==3">问诊</span>
+          <span v-else-if="scope.row.orderType==4">积分</span>
+          <span v-else>-</span>
         </template>
       </el-table-column>
-      <el-table-column label="物流单号" align="center" prop="deliverySn" width="150" show-overflow-tooltip />
-      <el-table-column label="物流状态" align="center" prop="deliveryStatus">
+      <el-table-column label="所属公司" align="center" prop="companyName" width="120" show-overflow-tooltip />
+      <el-table-column label="部门" align="center" prop="deptName" width="120" show-overflow-tooltip />
+      <el-table-column label="员工" align="center" prop="companyUserName" width="100" />
+      <el-table-column label="收货人" align="center" prop="userName" width="90" />
+      <el-table-column label="会员手机号" align="center" prop="memberPhone" width="130" />
+      <el-table-column label="会员年龄" align="center" prop="memberAge" width="80" />
+      <el-table-column label="会员性别" align="center" prop="memberSex" width="80">
         <template slot-scope="scope">
-          <dict-tag v-if="scope.row.deliveryStatus != null" :options="deliveryStatusOptions" :value="scope.row.deliveryStatus" />
+          <span v-if="scope.row.memberSex==1">男</span>
+          <span v-else-if="scope.row.memberSex==2">女</span>
           <span v-else>-</span>
         </template>
       </el-table-column>
-      <el-table-column label="物流跟踪状态" align="center" prop="deliveryType" width="120">
+      <el-table-column label="复购次数" align="center" prop="memberBuyCount" width="80" />
+      <el-table-column label="省" align="center" prop="province" width="80" />
+      <el-table-column label="二级市" align="center" prop="city" width="90" />
+      <el-table-column label="区县" align="center" prop="district" width="90" />
+      <el-table-column label="乡镇" align="center" prop="township" width="90" />
+      <el-table-column label="病名" align="center" prop="diseaseName" width="100" show-overflow-tooltip />
+      <el-table-column label="商品名称" align="center" prop="productNames" width="200" show-overflow-tooltip />
+      <el-table-column label="商品总额" align="center" prop="totalPrice" width="100" />
+      <el-table-column label="应收金额" align="center" prop="receivablePrice" width="100" />
+      <el-table-column label="定金(实收)" align="center" prop="payPrice" width="100" />
+      <el-table-column label="代收金额" align="center" prop="collectionPrice" width="100" />
+      <el-table-column label="支付方式" align="center" prop="payType" width="100">
+        <template slot-scope="scope">
+          <dict-tag :options="payTypeOptions" :value="scope.row.payType" />
+        </template>
+      </el-table-column>
+      <el-table-column label="定金回款时间" align="center" width="160">
         <template slot-scope="scope">
-          <dict-tag v-if="scope.row.deliveryType != null" :options="deliveryTypeOptions" :value="scope.row.deliveryType" />
+          <span>{{ scope.row.status == 4 ? scope.row.updateTime : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="externalCreateTime" width="160" />
+      <el-table-column label="快递单号" align="center" prop="deliverySn" width="150" show-overflow-tooltip />
+      <el-table-column label="快递公司" align="center" prop="deliveryCode" width="100" />
+      <el-table-column label="快递类型" align="center" prop="deliveryName" width="100" />
+      <el-table-column label="发货日期" align="center" prop="deliveryTime" width="160" />
+      <el-table-column label="签收状态" align="center" prop="deliveryStatus" width="100">
+        <template slot-scope="scope">
+          <dict-tag v-if="scope.row.deliveryStatus != null" :options="deliveryStatusOptions" :value="scope.row.deliveryStatus" />
           <span v-else>-</span>
         </template>
       </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="280px">
+      <el-table-column label="跟单时间" align="center" prop="followTime" width="160" />
+      <el-table-column label="退款金额" align="center" prop="refundPrice" width="100" />
+      <el-table-column label="退款日期" align="center" prop="refundTime" width="160" />
+      <el-table-column label="拒收回退时间" align="center" prop="rejectReturnTime" width="160" />
+      <el-table-column label="备注" align="center" prop="remark" width="150" show-overflow-tooltip />
+      <el-table-column label="审核人" align="center" prop="auditor" width="90" />
+      <el-table-column label="审核时间" align="center" prop="auditTime" width="160" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
         <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            v-hasPermi="['store:externalOrder:query']"
-            @click="handleView(scope.row)"
-          >查看</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            v-hasPermi="['store:externalOrder:audit']"
-            @click="handleAudit(scope.row)"
-            v-if="scope.row.status == 1"
-          >审核</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            v-hasPermi="['store:externalOrder:approveOrder']"
-            @click="handleApprove(scope.row)"
-            v-if="scope.row.status == 3 && !scope.row.isApplyAudit && isAbnormalDelivery(scope.row.deliveryType)"
-          >申请审核</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            v-hasPermi="['store:externalOrder:express']"
-            @click="handleExpress(scope.row)"
-            v-if="scope.row.deliverySn"
-          >查看物流</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            v-hasPermi="['store:externalOrder:cancel']"
-            @click="handleCancel(scope.row)"
-            v-if="scope.row.status != 4"
-          >取消订单</el-button>
+          <el-button size="mini" type="text" v-hasPermi="['store:externalOrder:query']" @click="handleView(scope.row)">查看</el-button>
+          <el-button size="mini" type="text" v-hasPermi="['store:externalOrder:audit']" @click="handleAudit(scope.row)" v-if="scope.row.status == 1">审核</el-button>
+          <el-button size="mini" type="text" v-hasPermi="['store:externalOrder:approveOrder']" @click="handleApprove(scope.row)" v-if="scope.row.status == 3 && !scope.row.isApplyAudit && isAbnormalDelivery(scope.row.deliveryType)">申请审核</el-button>
+          <el-button size="mini" type="text" v-hasPermi="['store:externalOrder:express']" @click="handleExpress(scope.row)" v-if="scope.row.deliverySn">查看物流</el-button>
+          <el-button size="mini" type="text" v-hasPermi="['store:externalOrder:cancel']" @click="handleCancel(scope.row)" v-if="scope.row.status != -3">取消订单</el-button>
+          <el-button size="mini" type="text" v-hasPermi="['store:externalOrder:edit']" @click="handleEdit(scope.row)">订单修改</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -204,6 +217,19 @@
               </el-table-column>
               <el-table-column label="昵称" align="center" prop="nickName" />
               <el-table-column label="手机号" align="center" prop="phone" />
+              <el-table-column label="年龄" align="center">
+                <template slot-scope="scope">
+                  <span v-if="scope.row.birthday">{{ Math.floor((Date.now() / 1000 - scope.row.birthday) / 31536000) }}</span>
+                  <span v-else>-</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="性别" align="center" prop="sex">
+                <template slot-scope="scope">
+                  <span v-if="scope.row.sex == 1">男</span>
+                  <span v-else-if="scope.row.sex == 2">女</span>
+                  <span v-else>-</span>
+                </template>
+              </el-table-column>
               <el-table-column label="状态" align="center" prop="status" >
                 <template slot-scope="scope">
                   <el-tag prop="status" v-for="(item, index) in userStatusOptions" :key="index" v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
@@ -235,6 +261,7 @@
               <el-table-column label="收货人所在省" align="center" prop="province" />
               <el-table-column label="收货人所在市" align="center" prop="city" />
               <el-table-column label="收货人所在区" align="center" prop="district" />
+              <el-table-column label="乡镇" align="center" prop="township" />
               <el-table-column label="收货人详细地址" align="center" prop="detail" />
             </el-table>
           </el-radio-group>
@@ -291,10 +318,10 @@
             />
           </el-select>
         </el-form-item>
-        <el-form-item label="应收金额" prop="totalPrice">
-          <el-input v-model="form.totalPrice" placeholder="请输入应收金额" clearable size="small" style="width: 200px;" />
+        <el-form-item label="商品总额" prop="totalPrice">
+          <el-input v-model="form.totalPrice" placeholder="请输入商品总额" clearable size="small" style="width: 200px;" />
         </el-form-item>
-        <el-form-item label="支付金额" prop="payMoney">
+        <el-form-item :label="form.payType == 3 ? '定金' : '支付金额'" prop="payMoney">
           <el-input v-model="form.payMoney" placeholder="请输入支付金额" clearable size="small" style="width: 200px;" />
         </el-form-item>
       </el-form>
@@ -304,35 +331,72 @@
       </div>
     </el-dialog>
 
-    <el-dialog title="订单详情" v-if="detailOpen" :visible.sync="detailOpen" width="800px" append-to-body>
-      <el-descriptions :column="2" border>
+    <el-dialog title="订单详情" v-if="detailOpen" :visible.sync="detailOpen" width="1000px" append-to-body>
+      <el-descriptions :column="3" border size="small">
         <el-descriptions-item label="外部订单号">{{ detailData.orderCode }}</el-descriptions-item>
+        <el-descriptions-item label="订单状态">
+          <el-tag v-if="detailData.status==1" type="warning" size="mini">未审核</el-tag>
+          <el-tag v-else-if="detailData.status==2" type="success" size="mini">审核通过</el-tag>
+          <el-tag v-else-if="detailData.status==3" type="primary" size="mini">已发货</el-tag>
+          <el-tag v-else-if="detailData.status==4" size="mini">已回款</el-tag>
+          <el-tag v-else-if="detailData.status==-3" type="danger" size="mini">已取消</el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="订单类型">
+          <span v-if="detailData.orderType==1">外部订单</span>
+          <span v-else-if="detailData.orderType==2">套餐包</span>
+          <span v-else-if="detailData.orderType==3">问诊</span>
+          <span v-else-if="detailData.orderType==4">积分</span>
+          <span v-else>-</span>
+        </el-descriptions-item>
         <el-descriptions-item label="所属公司">{{ detailData.companyName }}</el-descriptions-item>
+        <el-descriptions-item label="部门">{{ detailData.deptName || '-' }}</el-descriptions-item>
         <el-descriptions-item label="员工">{{ detailData.companyUserName }}</el-descriptions-item>
         <el-descriptions-item label="收货人">{{ detailData.userName }}</el-descriptions-item>
         <el-descriptions-item label="收货人电话">{{ detailData.userPhone }}</el-descriptions-item>
-        <el-descriptions-item label="收货地址">{{ detailData.userAddress }}</el-descriptions-item>
-        <el-descriptions-item label="实收金额">{{ detailData.payPrice }}</el-descriptions-item>
+        <el-descriptions-item label="会员ID">{{ detailData.userId || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="会员手机号">{{ detailData.memberPhone || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="会员年龄">{{ detailData.memberAge || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="会员性别">
+          <span v-if="detailData.memberSex==1">男</span>
+          <span v-else-if="detailData.memberSex==2">女</span>
+          <span v-else>-</span>
+        </el-descriptions-item>
+        <el-descriptions-item label="复购次数">{{ detailData.memberBuyCount != null ? detailData.memberBuyCount : '-' }}</el-descriptions-item>
+        <el-descriptions-item label="病名">{{ detailData.diseaseName || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="省">{{ detailData.province || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="二级市">{{ detailData.city || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="区县">{{ detailData.district || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="乡镇">{{ detailData.township || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="收货地址" :span="2">{{ detailData.userAddress }}</el-descriptions-item>
+        <el-descriptions-item label="商品总额">{{ detailData.totalPrice }}</el-descriptions-item>
+        <el-descriptions-item label="应收金额">{{ detailData.receivablePrice }}</el-descriptions-item>
+        <el-descriptions-item label="定金(实收)">{{ detailData.payPrice }}</el-descriptions-item>
+        <el-descriptions-item label="代收金额">{{ detailData.collectionPrice != null ? detailData.collectionPrice : '-' }}</el-descriptions-item>
         <el-descriptions-item label="支付方式">
           <dict-tag :options="payTypeOptions" :value="detailData.payType" />
         </el-descriptions-item>
-        <el-descriptions-item label="订单状态">
-          <dict-tag :options="statusOptions" :value="detailData.status" />
-        </el-descriptions-item>
-        <el-descriptions-item label="物流单号">{{ detailData.deliverySn || '-' }}</el-descriptions-item>
-        <el-descriptions-item label="物流状态">
+        <el-descriptions-item label="定金回款时间">{{ detailData.status == 4 ? detailData.updateTime : '-' }}</el-descriptions-item>
+        <el-descriptions-item label="创建时间">{{ detailData.externalCreateTime }}</el-descriptions-item>
+        <el-descriptions-item label="快递单号">{{ detailData.deliverySn || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="快递公司">{{ detailData.deliveryCode || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="快递类型">{{ detailData.deliveryName || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="发货日期">{{ detailData.deliveryTime || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="签收状态">
           <dict-tag v-if="detailData.deliveryStatus != null" :options="deliveryStatusOptions" :value="detailData.deliveryStatus" />
           <span v-else>-</span>
         </el-descriptions-item>
-        <el-descriptions-item label="物流跟踪状态">
-          <dict-tag v-if="detailData.deliveryType != null" :options="deliveryTypeOptions" :value="detailData.deliveryType" />
-          <span v-else>-</span>
-        </el-descriptions-item>
-        <el-descriptions-item label="创建时间">{{ detailData.externalCreateTime }}</el-descriptions-item>
+        <el-descriptions-item label="跟单时间">{{ detailData.followTime || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="退款金额">{{ detailData.refundPrice != null ? detailData.refundPrice : '-' }}</el-descriptions-item>
+        <el-descriptions-item label="退款日期">{{ detailData.refundTime || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="拒收回退时间">{{ detailData.rejectReturnTime || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="审核人">{{ detailData.auditor || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="审核时间">{{ detailData.auditTime || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="备注" :span="3">{{ detailData.remark || '-' }}</el-descriptions-item>
       </el-descriptions>
       <el-divider content-position="left">商品信息</el-divider>
-      <el-table border :data="detailData.productList || []">
+      <el-table border :data="detailData.productList || []" size="small">
         <el-table-column label="商品名称" align="center" prop="productName" />
+        <el-table-column label="规格" align="center" prop="productSpec" />
         <el-table-column label="商品价格" align="center" prop="price" />
         <el-table-column label="数量" align="center" prop="num" />
         <el-table-column label="小计" align="center">
@@ -439,11 +503,83 @@
         @pagination="getProductDialogList"
       />
     </el-dialog>
+
+    <el-dialog title="订单修改" v-if="editOpen" :visible.sync="editOpen" width="600px" append-to-body :close-on-click-modal="false">
+      <el-form ref="editForm" :model="editForm" label-width="120px">
+        <el-form-item label="订单状态">
+          <el-select v-model="editForm.status" placeholder="请选择订单状态" clearable size="small" style="width:200px;">
+            <el-option label="未审核" :value="1" />
+            <el-option label="审核通过" :value="2" />
+            <el-option label="已发货" :value="3" />
+            <el-option label="已回款" :value="4" />
+            <el-option label="已取消" :value="-3" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="跟单时间">
+          <el-date-picker v-model="editForm.followTime" type="datetime" placeholder="请选择跟单时间" size="small" style="width:200px;" value-format="yyyy-MM-dd HH:mm:ss" />
+        </el-form-item>
+        <el-form-item label="快递类型">
+          <el-input v-model="editForm.deliveryName" placeholder="请输入快递类型" clearable size="small" style="width:200px;" />
+        </el-form-item>
+        <el-form-item label="签收状态">
+          <el-select v-model="editForm.deliveryStatus" placeholder="请选择签收状态" clearable size="small" style="width:200px;">
+            <el-option
+              v-for="item in deliveryStatusOptions"
+              :key="item.dictValue"
+              :label="item.dictLabel"
+              :value="Number(item.dictValue)"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="代收金额">
+          <el-input-number v-model="editForm.collectionPrice" :precision="2" :min="0" size="small" style="width:200px;" />
+        </el-form-item>
+        <el-form-item label="定金回款时间" v-if="editForm.status == 4">
+          <el-date-picker v-model="editForm.updateTime" type="datetime" placeholder="请选择回款时间" size="small" style="width:200px;" value-format="yyyy-MM-dd HH:mm:ss" />
+        </el-form-item>
+        <el-form-item label="备注">
+          <el-input v-model="editForm.remark" type="textarea" :rows="3" placeholder="请输入备注" style="width:350px;" />
+        </el-form-item>
+        <el-form-item label="快递公司">
+          <el-input v-model="editForm.deliveryCode" placeholder="请输入快递公司编号" clearable size="small" style="width:200px;" />
+        </el-form-item>
+        <el-form-item label="退款金额">
+          <el-input-number v-model="editForm.refundPrice" :precision="2" :min="0" size="small" style="width:200px;" />
+        </el-form-item>
+        <el-form-item label="退款日期">
+          <el-date-picker v-model="editForm.refundTime" type="datetime" placeholder="请选择退款日期" size="small" style="width:200px;" value-format="yyyy-MM-dd HH:mm:ss" />
+        </el-form-item>
+        <el-form-item label="拒收回退时间" v-if="showRejectReturnTime">
+          <el-date-picker v-model="editForm.rejectReturnTime" type="datetime" placeholder="请选择拒收回退时间" size="small" style="width:200px;" value-format="yyyy-MM-dd HH:mm:ss" />
+        </el-form-item>
+        <el-form-item label="是否还货" v-if="showReturnGoods">
+          <el-select v-model="editForm.isReturnGoods" placeholder="请选择是否还货" clearable size="small" style="width:200px;">
+            <el-option label="是" :value="1" />
+            <el-option label="否" :value="2" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="病名">
+          <el-input v-model="editForm.diseaseName" placeholder="请输入病名" clearable size="small" style="width:200px;" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="editOpen = false">取 消</el-button>
+        <el-button type="primary" @click="submitEditConfirm">确 定</el-button>
+      </div>
+    </el-dialog>
+
+    <el-dialog title="确认修改" :visible.sync="editConfirmOpen" width="360px" append-to-body>
+      <span>确认修改该订单信息吗?</span>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="editConfirmOpen = false">取 消</el-button>
+        <el-button type="primary" @click="submitEdit">确 认</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { listExternalOrder, createExternalOrder, getExternalOrder, auditExternalOrder, cancelExternalOrder, approveExternalOrder, exportExternalOrder, getExternalOrderExpress, syncExternalOrderExpress } from "@/api/store/externalOrder";
+import { listExternalOrder, createExternalOrder, getExternalOrder, auditExternalOrder, cancelExternalOrder, approveExternalOrder, exportExternalOrder, getExternalOrderExpress, syncExternalOrderExpress, editExternalOrder } from "@/api/store/externalOrder";
 import { getCompanyList } from "@/api/company/company";
 import { listUserAddress } from "@/api/store/userAddress";
 import { listStoreProduct, listStore } from "@/api/store/storeProduct";
@@ -556,21 +692,54 @@ export default {
       uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload",
       headers: { Authorization: "Bearer " + this.$store.getters.token },
       payTypeOptions: [],
-      statusOptions: [],
       deliveryStatusOptions: [],
       deliveryTypeOptions: [],
-      userStatusOptions: []
+      userStatusOptions: [],
+      editOpen: false,
+      editConfirmOpen: false,
+      editForm: {
+        orderId: null,
+        status: null,
+        followTime: null,
+        deliveryName: null,
+        deliveryStatus: null,
+        collectionPrice: null,
+        updateTime: null,
+        remark: null,
+        deliveryCode: null,
+        refundPrice: null,
+        refundTime: null,
+        rejectReturnTime: null,
+        diseaseName: null,
+        isReturnGoods: null
+      }
     };
   },
+  computed: {
+    showRejectReturnTime() {
+      if (this.editForm.deliveryStatus == null) return false;
+      const statusItem = this.deliveryStatusOptions.find(item => Number(item.dictValue) === this.editForm.deliveryStatus);
+      if (statusItem) {
+        const label = statusItem.dictLabel;
+        return ['已拒收', '已退回', '退回签收'].includes(label);
+      }
+      return false;
+    },
+    showReturnGoods() {
+      if (this.editForm.deliveryStatus == null) return false;
+      const statusItem = this.deliveryStatusOptions.find(item => Number(item.dictValue) === this.editForm.deliveryStatus);
+      if (statusItem) {
+        return statusItem.dictLabel === '已拒收';
+      }
+      return false;
+    }
+  },
   created() {
     this.getList();
     this.getCompanyList();
     this.getDicts("sys_package_pay_type").then(response => {
       this.payTypeOptions = response.data;
     });
-    this.getDicts("sys_externalOrder_status").then(response => {
-      this.statusOptions = response.data;
-    });
     this.getDicts("sys_store_order_delivery_status").then(response => {
       this.deliveryStatusOptions = response.data;
     });
@@ -856,7 +1025,7 @@ export default {
       }).catch(function() {});
     },
     handleAudit(row) {
-      this.$confirm("确认审核该订单?审核后订单将变为待发货状态", "提示", {
+      this.$confirm("确认审核该订单?审核后订单将变为审核通过状态", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
@@ -942,6 +1111,41 @@ export default {
         this.download(response.msg);
         this.exportLoading = false;
       }).catch(() => {});
+    },
+    handleEdit(row) {
+      getExternalOrder(row.orderId).then(response => {
+        const d = response.data;
+        this.editForm = {
+          orderId: d.orderId,
+          status: d.status,
+          followTime: d.followTime || null,
+          deliveryName: d.deliveryName || null,
+          deliveryStatus: d.deliveryStatus != null ? d.deliveryStatus : null,
+          collectionPrice: d.collectionPrice != null ? Number(d.collectionPrice) : null,
+          updateTime: d.updateTime || null,
+          remark: d.remark || null,
+          deliveryCode: d.deliveryCode || null,
+          refundPrice: d.refundPrice != null ? Number(d.refundPrice) : null,
+          refundTime: d.refundTime || null,
+          rejectReturnTime: d.rejectReturnTime || null,
+          diseaseName: d.diseaseName || null,
+          isReturnGoods: d.isReturnGoods != null ? d.isReturnGoods : null
+        };
+        this.editOpen = true;
+      });
+    },
+    submitEditConfirm() {
+      this.editConfirmOpen = true;
+    },
+    submitEdit() {
+      editExternalOrder(this.editForm).then(response => {
+        if (response.code === 200) {
+          this.msgSuccess("修改成功");
+          this.editConfirmOpen = false;
+          this.editOpen = false;
+          this.getList();
+        }
+      });
     }
   }
 };

+ 356 - 0
src/views/store/financeOrder/index.vue

@@ -0,0 +1,356 @@
+<template>
+  <div class="app-container">
+
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="90px">
+      <el-form-item label="回款状态" prop="returnStatus">
+        <el-select v-model="queryParams.returnStatus" placeholder="请选择回款状态" clearable size="small" style="width:140px;">
+          <el-option label="未回款" value="0" />
+          <el-option label="已回款" value="1" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="订单编号" prop="orderCode">
+        <el-input v-model="queryParams.orderCode" placeholder="请输入订单编号" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="会员姓名" prop="userName">
+        <el-input v-model="queryParams.userName" placeholder="请输入会员姓名" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="会员电话" prop="userPhone">
+        <el-input v-model="queryParams.userPhone" placeholder="请输入会员电话" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="快递单号" prop="deliverySn">
+        <el-input v-model="queryParams.deliverySn" placeholder="请输入快递单号" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="发货时间" prop="deliveryTime">
+        <el-date-picker
+          v-model="deliveryTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="handleDeliveryTimeChange"
+        />
+      </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"
+          icon="el-icon-upload"
+          size="mini"
+          @click="handleImport"
+          v-hasPermi="['store:financeOrder:import']"
+        >导入</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['store:financeOrder:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" border :data="orderList" style="width:100%">
+      <el-table-column label="订单编号" align="center" prop="orderCode" width="170" fixed="left" />
+      <el-table-column label="订单日期" align="center" prop="externalCreateTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.externalCreateTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="回款日期" align="center" prop="returnTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ scope.row.returnTime ? parseTime(scope.row.returnTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="回款人" align="center" prop="returnUser" width="100">
+        <template slot-scope="scope">
+          <span>{{ scope.row.returnUser || '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="会员姓名" align="center" prop="userName" width="90" />
+      <el-table-column label="快递公司" align="center" prop="deliveryName" width="100" />
+      <el-table-column label="运单号" align="center" prop="deliverySn" width="150" show-overflow-tooltip />
+      <el-table-column label="订单金额" align="center" prop="totalPrice" width="100" />
+      <el-table-column label="代收金额" align="center" prop="collectionPrice" width="100" />
+      <el-table-column label="回款金额" align="center" prop="returnPrice" width="100" />
+      <el-table-column label="收件人电话" align="center" prop="receiverPhone" width="130" show-overflow-tooltip />
+      <el-table-column label="订购产品" align="center" prop="productNames" width="180" show-overflow-tooltip />
+      <el-table-column label="付款方式" align="center" prop="payType" width="90">
+        <template slot-scope="scope">
+          <dict-tag :options="payTypeOptions" :value="scope.row.payType" />
+        </template>
+      </el-table-column>
+      <el-table-column label="回款状态" align="center" prop="returnStatus" width="90">
+        <template slot-scope="scope">
+          <el-tag :type="scope.row.returnStatus == 1 ? 'success' : 'info'">
+            {{ scope.row.returnStatus == 1 ? '已回款' : '未回款' }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="备注" align="center" prop="remark" width="150" show-overflow-tooltip />
+      <el-table-column label="发货日期" align="center" prop="deliveryTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ scope.row.deliveryTime ? parseTime(scope.row.deliveryTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="销售姓名" align="center" prop="companyUserName" width="100" />
+      <el-table-column label="公司" align="center" prop="companyName" width="120" show-overflow-tooltip />
+      <el-table-column label="部门" align="center" prop="deptName" width="100" show-overflow-tooltip />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="100">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleEdit(scope.row)"
+            v-hasPermi="['store:financeOrder:edit']"
+            v-if="scope.row.returnStatus == 1"
+          >修改</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <el-dialog :title="editTitle" :visible.sync="editOpen" width="450px" append-to-body>
+      <el-form ref="editForm" :model="editForm" :rules="editRules" label-width="100px">
+        <el-form-item label="订单编号">
+          <span>{{ editForm.orderCode }}</span>
+        </el-form-item>
+        <el-form-item label="订单金额">
+          <span>{{ editForm.totalPrice }}</span>
+        </el-form-item>
+        <el-form-item label="代收金额">
+          <span>{{ editForm.collectionPrice }}</span>
+        </el-form-item>
+        <el-form-item label="回款金额" prop="returnPrice">
+          <el-input v-model="editForm.returnPrice" placeholder="请输入回款金额" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitEdit">确 定</el-button>
+        <el-button @click="editOpen = false">取 消</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 导入对话框 -->
+    <el-dialog title="导入回款数据" :visible.sync="importOpen" width="450px" append-to-body>
+      <el-form label-width="80px">
+        <el-form-item label="选择文件">
+          <el-upload
+            ref="upload"
+            :action="importAction"
+            :headers="importHeaders"
+            :auto-upload="false"
+            :limit="1"
+            accept=".xls,.xlsx"
+            :on-change="handleImportFileChange"
+            :on-remove="handleImportFileRemove"
+          >
+            <el-button size="small" type="primary">选择文件</el-button>
+            <div slot="tip" class="el-upload__tip">仅支持 .xls/.xlsx 文件</div>
+          </el-upload>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="success" icon="el-icon-download" size="mini" @click="downloadImportTemplate">模板下载</el-button>
+        <el-button type="primary" @click="submitImport" :loading="importLoading" :disabled="importDisableUpload">开 始</el-button>
+        <el-button @click="importOpen = false">关 闭</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listFinanceOrder, editFinanceOrder, exportFinanceOrder, downloadFinanceImportTemplate, importFinanceOrder } from '@/api/store/financeOrder'
+import { getToken } from '@/utils/auth'
+
+export default {
+  name: 'FinanceOrder',
+  data() {
+    return {
+      loading: false,
+      exportLoading: false,
+      showSearch: true,
+      total: 0,
+      orderList: [],
+      deliveryTime: null,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        userName: null,
+        userPhone: null,
+        deliverySn: null
+      },
+      payTypeOptions: [],
+      editOpen: false,
+      editTitle: '',
+      editForm: {
+        orderId: null,
+        orderCode: null,
+        totalPrice: null,
+        collectionPrice: null,
+        returnPrice: null
+      },
+      editRules: {
+        returnPrice: [
+          { required: true, message: '回款金额不能为空', trigger: 'blur' }
+        ]
+      },
+      importOpen: false,
+      importLoading: false,
+      importAction: process.env.VUE_APP_BASE_API + '/store/financeOrder/importData',
+      importHeaders: { Authorization: 'Bearer ' + getToken() },
+      importDisableUpload: true
+    }
+  },
+  created() {
+    this.getList()
+    this.getDicts('sys_package_pay_type').then(response => {
+      this.payTypeOptions = response.data
+    })
+  },
+  methods: {
+    getList() {
+      this.loading = true
+      listFinanceOrder(this.queryParams).then(response => {
+        this.orderList = response.rows || []
+        this.total = response.total || 0
+        this.loading = false
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    handleDeliveryTimeChange(val) {
+      if (val) {
+        this.queryParams.deliveryStartTime = val[0]
+        this.queryParams.deliveryEndTime = val[1]
+      } else {
+        delete this.queryParams.deliveryStartTime
+        delete this.queryParams.deliveryEndTime
+      }
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.resetForm('queryForm')
+      this.deliveryTime = null
+      delete this.queryParams.deliveryStartTime
+      delete this.queryParams.deliveryEndTime
+      this.handleQuery()
+    },
+    handleExport() {
+      this.$confirm('是否确认导出财务外部订单数据?', '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.exportLoading = true
+        return exportFinanceOrder(this.queryParams)
+      }).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => {
+        this.exportLoading = false
+      })
+    },
+    handleEdit(row) {
+      this.resetForm('editForm')
+      this.editForm = {
+        orderId: row.orderId,
+        orderCode: row.orderCode,
+        totalPrice: row.totalPrice,
+        collectionPrice: row.collectionPrice,
+        returnPrice: row.returnPrice
+      }
+      this.editTitle = '修改回款金额 - ' + row.orderCode
+      this.editOpen = true
+    },
+    submitEdit() {
+      this.$refs.editForm.validate(valid => {
+        if (!valid) return
+        editFinanceOrder(this.editForm).then(response => {
+          if (response.code === 200) {
+            this.msgSuccess('修改成功')
+            this.editOpen = false
+            this.getList()
+          }
+        })
+      })
+    },
+    handleImport() {
+      this.importDisableUpload = true
+      this.importOpen = true
+      this.$nextTick(() => {
+        this.$refs.upload && this.$refs.upload.clearFiles()
+      })
+    },
+    downloadImportTemplate() {
+      downloadFinanceImportTemplate().then(response => {
+        this.download(response.msg)
+      })
+    },
+    handleImportFileChange(file) {
+      this.importDisableUpload = false
+    },
+    handleImportFileRemove() {
+      this.importDisableUpload = true
+    },
+    submitImport() {
+      const uploadFiles = this.$refs.upload.uploadFiles
+      if (!uploadFiles || uploadFiles.length === 0) {
+        this.msgError('请选择文件')
+        return
+      }
+      const formData = new FormData()
+      formData.append('file', uploadFiles[0].raw)
+      this.importLoading = true
+      importFinanceOrder(formData).then(response => {
+        this.$refs.upload.clearFiles()
+        this.importDisableUpload = true
+        this.importLoading = false
+        this.importOpen = false
+        // msg 中包含"失败"表示有失败记录,data 中存了失败文件下载名
+        const hasFail = response.msg && response.msg.indexOf('失败') !== -1
+        const failFile = response.data
+        if (hasFail && failFile) {
+          this.$confirm(response.msg + ',是否下载失败记录?', '提示', {
+            confirmButtonText: '下载',
+            cancelButtonText: '关闭',
+            type: 'warning'
+          }).then(() => {
+            this.download(failFile)
+          }).catch(() => {})
+        } else {
+          this.msgSuccess(response.msg)
+        }
+        this.getList()
+      }).catch(() => {
+        this.importLoading = false
+      })
+    }
+  }
+}
+</script>

+ 1 - 1
src/views/store/orderDetailSummary/index.vue

@@ -73,7 +73,7 @@
           icon="el-icon-upload2"
           size="mini"
           @click="handleImport"
-          v-hasPermi="['store:orderDetailSummary:import']"
+          v-hasPermi="['his:orderDetailSummary:import']"
         >导入</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>

+ 146 - 0
src/views/store/rejectNoReturn/index.vue

@@ -0,0 +1,146 @@
+<template>
+  <div class="app-container">
+    <!-- 查询条件 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="80px">
+      <el-form-item label="订单编号" prop="orderCode">
+        <el-input v-model="queryParams.orderCode" placeholder="请输入订单编号" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="运单号" prop="deliverySn">
+        <el-input v-model="queryParams.deliverySn" placeholder="请输入运单号" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="会员姓名" prop="userName">
+        <el-input v-model="queryParams.userName" placeholder="请输入会员姓名" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="地址" prop="userAddress">
+        <el-input v-model="queryParams.userAddress" placeholder="请输入地址" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="发货日期" prop="deliveryTime">
+        <el-date-picker
+          v-model="deliveryTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="handleDeliveryTimeChange"
+        />
+      </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="warning" plain icon="el-icon-download" size="mini" :loading="exportLoading" @click="handleExport">导出</el-button>
+      </el-col>
+    </el-row>
+
+    <!-- 拒收未还货列表 -->
+    <el-table v-loading="loading" border :data="tableList" style="width:100%">
+      <el-table-column label="订单编号" align="center" prop="orderCode" min-width="160" />
+      <el-table-column label="运单号" align="center" prop="deliverySn" min-width="140" show-overflow-tooltip />
+      <el-table-column label="会员姓名" align="center" prop="userName" min-width="80" />
+      <el-table-column label="地址" align="center" prop="userAddress" min-width="180" show-overflow-tooltip />
+      <el-table-column label="发货日期" align="center" prop="deliveryTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.deliveryTime ? parseTime(scope.row.deliveryTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="金额" align="center" prop="totalPrice" min-width="100" />
+      <el-table-column label="跟单时间" align="center" prop="followTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.followTime ? parseTime(scope.row.followTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="快递公司" align="center" prop="deliveryName" min-width="120" />
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </div>
+</template>
+
+<script>
+import { listRejectNoReturn, exportRejectNoReturn } from '@/api/store/rejectNoReturn'
+
+export default {
+  name: 'RejectNoReturn',
+  data() {
+    return {
+      loading: false,
+      exportLoading: false,
+      total: 0,
+      tableList: [],
+      deliveryTime: null,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        deliverySn: null,
+        userName: null,
+        userAddress: null
+      }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    getList() {
+      this.loading = true
+      listRejectNoReturn(this.queryParams).then(response => {
+        this.tableList = response.rows || []
+        this.total = response.total || 0
+        this.loading = false
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    handleDeliveryTimeChange(val) {
+      if (val) {
+        this.queryParams.deliveryStartTime = val[0]
+        this.queryParams.deliveryEndTime = val[1]
+      } else {
+        delete this.queryParams.deliveryStartTime
+        delete this.queryParams.deliveryEndTime
+      }
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.deliveryTime = null
+      delete this.queryParams.deliveryStartTime
+      delete this.queryParams.deliveryEndTime
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    handleExport() {
+      this.$confirm('确认导出拒收未还货报表?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.exportLoading = true
+        return exportRejectNoReturn(this.queryParams)
+      }).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => {
+        this.exportLoading = false
+      })
+    }
+  }
+}
+</script>

+ 253 - 0
src/views/store/rejectReport/index.vue

@@ -0,0 +1,253 @@
+<template>
+  <div class="app-container">
+    <el-tabs v-model="activeTab">
+      <el-tab-pane label="拒收退回日期时间维度" name="order"></el-tab-pane>
+      <el-tab-pane label="拒收产品维度" name="product"></el-tab-pane>
+    </el-tabs>
+
+    <!-- 拒收时间维度查询条件 -->
+    <el-form v-show="activeTab === 'order'" :model="orderQuery" ref="orderQueryForm" :inline="true" label-width="80px">
+      <el-form-item label="订单编号" prop="orderCode">
+        <el-input v-model="orderQuery.orderCode" placeholder="请输入订单编号" clearable size="small" @keyup.enter.native="handleOrderQuery" />
+      </el-form-item>
+      <el-form-item label="运单号" prop="deliverySn">
+        <el-input v-model="orderQuery.deliverySn" placeholder="请输入运单号" clearable size="small" @keyup.enter.native="handleOrderQuery" />
+      </el-form-item>
+      <el-form-item label="会员姓名" prop="userName">
+        <el-input v-model="orderQuery.userName" placeholder="请输入会员姓名" clearable size="small" @keyup.enter.native="handleOrderQuery" />
+      </el-form-item>
+      <el-form-item label="地址" prop="userAddress">
+        <el-input v-model="orderQuery.userAddress" placeholder="请输入地址" clearable size="small" @keyup.enter.native="handleOrderQuery" />
+      </el-form-item>
+      <el-form-item label="发货日期" prop="deliveryTime">
+        <el-date-picker
+          v-model="orderDeliveryTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="handleOrderDeliveryTimeChange"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleOrderQuery">查询</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetOrderQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8" v-show="activeTab === 'order'">
+      <el-col :span="1.5">
+        <el-button type="warning" plain icon="el-icon-download" size="mini" :loading="orderExportLoading" @click="handleOrderExport">导出</el-button>
+      </el-col>
+    </el-row>
+
+    <!-- 拒收时间维度列表 -->
+    <el-table v-show="activeTab === 'order'" v-loading="orderLoading" border :data="orderList" style="width:100%">
+      <el-table-column label="订单编号" align="center" prop="orderCode" min-width="160" />
+      <el-table-column label="快递单号" align="center" prop="deliverySn" min-width="140" show-overflow-tooltip />
+      <el-table-column label="会员姓名" align="center" prop="userName" min-width="80" />
+      <el-table-column label="订单日期" align="center" prop="externalCreateTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.externalCreateTime ? parseTime(scope.row.externalCreateTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="发货日期" align="center" prop="deliveryTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.deliveryTime ? parseTime(scope.row.deliveryTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="金额" align="center" prop="totalPrice" min-width="90" />
+      <el-table-column label="快递公司" align="center" prop="deliveryName" min-width="100" />
+      <el-table-column label="跟单时间" align="center" prop="followTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.followTime ? parseTime(scope.row.followTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="拒收退回日期" align="center" prop="rejectReturnTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.rejectReturnTime ? parseTime(scope.row.rejectReturnTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="拒收人" align="center" prop="rejectUser" min-width="90" />
+      <el-table-column label="电话1" align="center" prop="userPhone" min-width="120" />
+      <el-table-column label="电话2" align="center" prop="memberPhone" min-width="120" />
+      <el-table-column label="销售姓名" align="center" prop="companyUserName" min-width="90" />
+      <el-table-column label="订购产品" align="center" prop="productNames" min-width="180" show-overflow-tooltip />
+      <el-table-column label="地址" align="center" prop="userAddress" min-width="180" show-overflow-tooltip />
+    </el-table>
+
+    <pagination
+      v-show="activeTab === 'order' && orderTotal > 0"
+      :total="orderTotal"
+      :page.sync="orderQuery.pageNum"
+      :limit.sync="orderQuery.pageSize"
+      @pagination="getOrderList"
+    />
+
+    <!-- 拒收产品维度查询条件 -->
+    <el-form v-show="activeTab === 'product'" :model="productQuery" ref="productQueryForm" :inline="true" label-width="80px">
+      <el-form-item label="产品名" prop="productName">
+        <el-input v-model="productQuery.productName" placeholder="请输入产品名" clearable size="small" @keyup.enter.native="handleProductQuery" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleProductQuery">查询</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetProductQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 拒收产品维度按钮 -->
+    <el-row :gutter="10" class="mb8" v-show="activeTab === 'product'">
+      <el-col :span="1.5">
+        <el-button type="warning" plain icon="el-icon-download" size="mini" :loading="productExportLoading" @click="handleProductExport">导出</el-button>
+      </el-col>
+    </el-row>
+
+    <el-table v-show="activeTab === 'product'" v-loading="productLoading" border :data="productList" style="width:100%">
+      <el-table-column label="订购产品" align="center" prop="productName" min-width="200" show-overflow-tooltip />
+      <el-table-column label="快递公司" align="center" prop="deliveryName" min-width="120" />
+      <el-table-column label="数量" align="center" prop="num" min-width="100" />
+      <el-table-column label="金额" align="center" prop="totalPrice" min-width="120" />
+    </el-table>
+
+    <pagination
+      v-show="activeTab === 'product' && productTotal > 0"
+      :total="productTotal"
+      :page.sync="productQuery.pageNum"
+      :limit.sync="productQuery.pageSize"
+      @pagination="getProductList"
+    />
+  </div>
+</template>
+
+<script>
+import { listRejectOrderReport, exportRejectOrderReport, listRejectProductReport, exportRejectProductReport } from '@/api/store/rejectReport'
+
+export default {
+  name: 'RejectReport',
+  data() {
+    return {
+      activeTab: 'order',
+      // 订单维度
+      orderLoading: false,
+      orderExportLoading: false,
+      orderTotal: 0,
+      orderList: [],
+      orderDeliveryTime: null,
+      orderQuery: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        deliverySn: null,
+        userName: null,
+        userAddress: null
+      },
+      // 产品维度
+      productLoading: false,
+      productExportLoading: false,
+      productTotal: 0,
+      productList: [],
+      productQuery: {
+        pageNum: 1,
+        pageSize: 10,
+        productName: null
+      }
+    }
+  },
+  created() {
+    this.getOrderList()
+  },
+  watch: {
+    activeTab(val) {
+      if (val === 'product' && this.productList.length === 0) {
+        this.getProductList()
+      }
+    }
+  },
+  methods: {
+    // ========== 订单维度 ==========
+    getOrderList() {
+      this.orderLoading = true
+      listRejectOrderReport(this.orderQuery).then(response => {
+        this.orderList = response.rows || []
+        this.orderTotal = response.total || 0
+        this.orderLoading = false
+      }).catch(() => {
+        this.orderLoading = false
+      })
+    },
+    handleOrderDeliveryTimeChange(val) {
+      if (val) {
+        this.orderQuery.deliveryStartTime = val[0]
+        this.orderQuery.deliveryEndTime = val[1]
+      } else {
+        delete this.orderQuery.deliveryStartTime
+        delete this.orderQuery.deliveryEndTime
+      }
+    },
+    handleOrderQuery() {
+      this.orderQuery.pageNum = 1
+      this.getOrderList()
+    },
+    resetOrderQuery() {
+      this.orderDeliveryTime = null
+      delete this.orderQuery.deliveryStartTime
+      delete this.orderQuery.deliveryEndTime
+      this.resetForm('orderQueryForm')
+      this.handleOrderQuery()
+    },
+    handleOrderExport() {
+      this.$confirm('确认导出拒收明细订单报表?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.orderExportLoading = true
+        return exportRejectOrderReport(this.orderQuery)
+      }).then(response => {
+        this.download(response.msg)
+        this.orderExportLoading = false
+      }).catch(() => {
+        this.orderExportLoading = false
+      })
+    },
+
+    // ========== 产品维度 ==========
+    getProductList() {
+      this.productLoading = true
+      listRejectProductReport(this.productQuery).then(response => {
+        this.productList = response.rows || []
+        this.productTotal = response.total || 0
+        this.productLoading = false
+      }).catch(() => {
+        this.productLoading = false
+      })
+    },
+    handleProductQuery() {
+      this.productQuery.pageNum = 1
+      this.getProductList()
+    },
+    resetProductQuery() {
+      this.resetForm('productQueryForm')
+      this.handleProductQuery()
+    },
+    handleProductExport() {
+      this.$confirm('确认导出拒收明细产品报表?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.productExportLoading = true
+        return exportRejectProductReport(this.productQuery)
+      }).then(response => {
+        this.download(response.msg)
+        this.productExportLoading = false
+      }).catch(() => {
+        this.productExportLoading = false
+      })
+    }
+  }
+}
+</script>

+ 251 - 0
src/views/store/returnReport/index.vue

@@ -0,0 +1,251 @@
+<template>
+  <div class="app-container">
+    <el-tabs v-model="activeTab">
+      <el-tab-pane label="回款时间维度" name="order"></el-tab-pane>
+      <el-tab-pane label="回款产品维度" name="product"></el-tab-pane>
+    </el-tabs>
+
+    <!-- 回款时间维度查询条件 -->
+    <el-form v-show="activeTab === 'order'" :model="orderQuery" ref="orderQueryForm" :inline="true" label-width="80px">
+      <el-form-item label="订单编号" prop="orderCode">
+        <el-input v-model="orderQuery.orderCode" placeholder="请输入订单编号" clearable size="small" @keyup.enter.native="handleOrderQuery" />
+      </el-form-item>
+      <el-form-item label="运单号" prop="deliverySn">
+        <el-input v-model="orderQuery.deliverySn" placeholder="请输入运单号" clearable size="small" @keyup.enter.native="handleOrderQuery" />
+      </el-form-item>
+      <el-form-item label="会员姓名" prop="userName">
+        <el-input v-model="orderQuery.userName" placeholder="请输入会员姓名" clearable size="small" @keyup.enter.native="handleOrderQuery" />
+      </el-form-item>
+      <el-form-item label="地址" prop="userAddress">
+        <el-input v-model="orderQuery.userAddress" placeholder="请输入地址" clearable size="small" @keyup.enter.native="handleOrderQuery" />
+      </el-form-item>
+      <el-form-item label="发货日期" prop="deliveryTime">
+        <el-date-picker
+          v-model="orderDeliveryTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="handleOrderDeliveryTimeChange"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleOrderQuery">查询</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetOrderQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8" v-show="activeTab === 'order'">
+      <el-col :span="1.5">
+        <el-button type="warning" plain icon="el-icon-download" size="mini" :loading="orderExportLoading" @click="handleOrderExport">导出</el-button>
+      </el-col>
+    </el-row>
+
+    <!-- 回款时间维度列表 -->
+    <el-table v-show="activeTab === 'order'" v-loading="orderLoading" border :data="orderList" style="width:100%">
+      <el-table-column label="订单编号" align="center" prop="orderCode" min-width="160" />
+      <el-table-column label="快递单号" align="center" prop="deliverySn" min-width="140" show-overflow-tooltip />
+      <el-table-column label="姓名" align="center" prop="userName" min-width="80" />
+      <el-table-column label="地址" align="center" prop="userAddress" min-width="180" show-overflow-tooltip />
+      <el-table-column label="订单日期" align="center" prop="externalCreateTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.externalCreateTime ? parseTime(scope.row.externalCreateTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="定金" align="center" prop="payPrice" min-width="90" />
+      <el-table-column label="金额" align="center" prop="totalPrice" min-width="90" />
+      <el-table-column label="快递公司" align="center" prop="deliveryName" min-width="100" />
+      <el-table-column label="回款人" align="center" prop="returnUser" min-width="90" />
+      <el-table-column label="回款日期" align="center" prop="returnTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.returnTime ? parseTime(scope.row.returnTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="电话1" align="center" prop="userPhone" min-width="120" />
+      <el-table-column label="电话2" align="center" prop="memberPhone" min-width="120" />
+      <el-table-column label="销售" align="center" prop="companyUserName" min-width="90" />
+      <el-table-column label="部门" align="center" prop="deptName" min-width="110" show-overflow-tooltip />
+      <el-table-column label="订购产品" align="center" prop="productNames" min-width="180" show-overflow-tooltip />
+      <el-table-column label="发货日期" align="center" prop="deliveryTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.deliveryTime ? parseTime(scope.row.deliveryTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="activeTab === 'order' && orderTotal > 0"
+      :total="orderTotal"
+      :page.sync="orderQuery.pageNum"
+      :limit.sync="orderQuery.pageSize"
+      @pagination="getOrderList"
+    />
+
+    <!-- 回款产品维度查询条件 -->
+    <el-form v-show="activeTab === 'product'" :model="productQuery" ref="productQueryForm" :inline="true" label-width="80px">
+      <el-form-item label="产品名" prop="productName">
+        <el-input v-model="productQuery.productName" placeholder="请输入产品名" clearable size="small" @keyup.enter.native="handleProductQuery" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleProductQuery">查询</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetProductQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 回款产品维度按钮 -->
+    <el-row :gutter="10" class="mb8" v-show="activeTab === 'product'">
+      <el-col :span="1.5">
+        <el-button type="warning" plain icon="el-icon-download" size="mini" :loading="productExportLoading" @click="handleProductExport">导出</el-button>
+      </el-col>
+    </el-row>
+
+    <el-table v-show="activeTab === 'product'" v-loading="productLoading" border :data="productList" style="width:100%">
+      <el-table-column label="部门" align="center" prop="deptName" min-width="140" show-overflow-tooltip />
+      <el-table-column label="快递公司" align="center" prop="deliveryName" min-width="120" />
+      <el-table-column label="订购产品" align="center" prop="productName" min-width="200" show-overflow-tooltip />
+      <el-table-column label="数量" align="center" prop="num" min-width="100" />
+      <el-table-column label="金额" align="center" prop="totalPrice" min-width="120" />
+    </el-table>
+
+    <pagination
+      v-show="activeTab === 'product' && productTotal > 0"
+      :total="productTotal"
+      :page.sync="productQuery.pageNum"
+      :limit.sync="productQuery.pageSize"
+      @pagination="getProductList"
+    />
+  </div>
+</template>
+
+<script>
+import { listReturnOrderReport, exportReturnOrderReport, listReturnProductReport, exportReturnProductReport } from '@/api/store/returnReport'
+
+export default {
+  name: 'ReturnReport',
+  data() {
+    return {
+      activeTab: 'order',
+      // 订单维度
+      orderLoading: false,
+      orderExportLoading: false,
+      orderTotal: 0,
+      orderList: [],
+      orderDeliveryTime: null,
+      orderQuery: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        deliverySn: null,
+        userName: null,
+        userAddress: null
+      },
+      // 产品维度
+      productLoading: false,
+      productExportLoading: false,
+      productTotal: 0,
+      productList: [],
+      productQuery: {
+        pageNum: 1,
+        pageSize: 10,
+        productName: null
+      }
+    }
+  },
+  created() {
+    this.getOrderList()
+  },
+  watch: {
+    activeTab(val) {
+      if (val === 'product' && this.productList.length === 0) {
+        this.getProductList()
+      }
+    }
+  },
+  methods: {
+    // ========== 订单维度 ==========
+    getOrderList() {
+      this.orderLoading = true
+      listReturnOrderReport(this.orderQuery).then(response => {
+        this.orderList = response.rows || []
+        this.orderTotal = response.total || 0
+        this.orderLoading = false
+      }).catch(() => {
+        this.orderLoading = false
+      })
+    },
+    handleOrderDeliveryTimeChange(val) {
+      if (val) {
+        this.orderQuery.deliveryStartTime = val[0]
+        this.orderQuery.deliveryEndTime = val[1]
+      } else {
+        delete this.orderQuery.deliveryStartTime
+        delete this.orderQuery.deliveryEndTime
+      }
+    },
+    handleOrderQuery() {
+      this.orderQuery.pageNum = 1
+      this.getOrderList()
+    },
+    resetOrderQuery() {
+      this.orderDeliveryTime = null
+      delete this.orderQuery.deliveryStartTime
+      delete this.orderQuery.deliveryEndTime
+      this.resetForm('orderQueryForm')
+      this.handleOrderQuery()
+    },
+    handleOrderExport() {
+      this.$confirm('确认导出回款明细订单报表?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.orderExportLoading = true
+        return exportReturnOrderReport(this.orderQuery)
+      }).then(response => {
+        this.download(response.msg)
+        this.orderExportLoading = false
+      }).catch(() => {
+        this.orderExportLoading = false
+      })
+    },
+
+    // ========== 产品维度 ==========
+    getProductList() {
+      this.productLoading = true
+      listReturnProductReport(this.productQuery).then(response => {
+        this.productList = response.rows || []
+        this.productTotal = response.total || 0
+        this.productLoading = false
+      }).catch(() => {
+        this.productLoading = false
+      })
+    },
+    handleProductQuery() {
+      this.productQuery.pageNum = 1
+      this.getProductList()
+    },
+    resetProductQuery() {
+      this.resetForm('productQueryForm')
+      this.handleProductQuery()
+    },
+    handleProductExport() {
+      this.$confirm('确认导出回款明细产品报表?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.productExportLoading = true
+        return exportReturnProductReport(this.productQuery)
+      }).then(response => {
+        this.download(response.msg)
+        this.productExportLoading = false
+      }).catch(() => {
+        this.productExportLoading = false
+      })
+    }
+  }
+}
+</script>

+ 227 - 0
src/views/store/signDetailReport/index.vue

@@ -0,0 +1,227 @@
+<template>
+  <div class="app-container">
+    <!-- 查询条件 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="80px">
+      <el-form-item label="公司" prop="companyId">
+        <el-select v-model="queryParams.companyId" placeholder="请选择公司" clearable size="small" style="width: 200px" @change="handleCompanyChange">
+          <el-option v-for="item in companyList" :key="item.companyId" :label="item.companyName" :value="item.companyId" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="订单类型" prop="orderType">
+        <el-select v-model="queryParams.orderType" placeholder="请选择订单类型" clearable size="small" style="width: 160px">
+          <el-option label="外部订单" :value="1" />
+          <el-option label="套餐包" :value="2" />
+          <el-option label="问诊" :value="3" />
+          <el-option label="积分" :value="4" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="部门" prop="deptId">
+        <treeselect v-model="queryParams.deptId" :options="deptOptions" :show-count="true" placeholder="请选择部门" clearable style="width: 200px" />
+      </el-form-item>
+      <el-form-item label="订单时间" prop="orderTime">
+        <el-date-picker
+          v-model="orderTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="handleOrderTimeChange"
+        />
+      </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="warning" plain icon="el-icon-download" size="mini" :loading="exportLoading" @click="handleExport">导出</el-button>
+      </el-col>
+    </el-row>
+
+    <!-- 签收情况明细列表 -->
+    <el-table
+      v-loading="loading"
+      border
+      :data="tableList"
+      style="width:100%"
+      show-summary
+      :summary-method="getSummaries"
+    >
+      <el-table-column label="订单类型" align="center" prop="orderType" min-width="100" sortable>
+        <template slot-scope="scope">
+          <span>{{ formatOrderType(scope.row.orderType) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="发货数量" align="center" prop="deliveryCount" min-width="100" sortable />
+      <el-table-column label="发货金额" align="center" prop="deliveryAmount" min-width="120" sortable />
+      <el-table-column label="签收数量" align="center" prop="signCount" min-width="100" sortable />
+      <el-table-column label="签收金额" align="center" prop="signAmount" min-width="120" sortable />
+      <el-table-column label="单数签收率" align="center" prop="orderSignRate" min-width="110" sortable />
+      <el-table-column label="金额签收率" align="center" prop="amountSignRate" min-width="110" sortable />
+      <el-table-column label="部门" align="center" prop="deptName" min-width="140" show-overflow-tooltip sortable />
+      <el-table-column label="公司" align="center" prop="companyName" min-width="160" show-overflow-tooltip sortable />
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </div>
+</template>
+
+<script>
+import { listSignDetailReport, exportSignDetailReport } from '@/api/store/signDetailReport'
+import { selectDeptTreeByCompanyId } from '@/api/company/companyDept'
+import { getCompanyList } from '@/api/company/company'
+import Treeselect from '@riophae/vue-treeselect'
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+
+export default {
+  name: 'SignDetailReport',
+  components: { Treeselect },
+  data() {
+    return {
+      loading: false,
+      exportLoading: false,
+      total: 0,
+      tableList: [],
+      orderTime: null,
+      companyList: [],
+      deptOptions: [],
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        companyId: null,
+        orderType: null,
+        deptId: null,
+        sTime: null,
+        eTime: null
+      }
+    }
+  },
+  created() {
+    this.getCompanyList()
+    this.getList()
+  },
+  methods: {
+    getList() {
+      this.loading = true
+      listSignDetailReport(this.queryParams).then(response => {
+        this.tableList = response.rows || []
+        this.total = response.total || 0
+        this.loading = false
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    getCompanyList() {
+      getCompanyList().then(response => {
+        this.companyList = response.data || []
+      })
+    },
+    handleCompanyChange(companyId) {
+      this.queryParams.deptId = null
+      this.deptOptions = []
+      if (companyId) {
+        selectDeptTreeByCompanyId(companyId).then(response => {
+          this.deptOptions = response.data || []
+        })
+      }
+    },
+    handleOrderTimeChange(val) {
+      if (val) {
+        this.queryParams.sTime = val[0]
+        this.queryParams.eTime = val[1]
+      } else {
+        this.queryParams.sTime = null
+        this.queryParams.eTime = null
+      }
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.orderTime = null
+      this.queryParams.sTime = null
+      this.queryParams.eTime = null
+      this.queryParams.companyId = null
+      this.queryParams.deptId = null
+      this.deptOptions = []
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    handleExport() {
+      this.$confirm('确认导出签收情况明细表?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.exportLoading = true
+        return exportSignDetailReport(this.queryParams)
+      }).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => {
+        this.exportLoading = false
+      })
+    },
+    formatOrderType(type) {
+      const map = { 1: '外部订单', 2: '套餐包', 3: '问诊', 4: '积分' }
+      return map[type] || '-'
+    },
+    getSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = '总计'
+          return
+        }
+        const prop = column.property
+        if (['deliveryCount', 'deliveryAmount', 'signCount', 'signAmount'].includes(prop)) {
+          const values = data.map(item => Number(item[prop]))
+          if (!values.every(value => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => {
+              const value = Number(curr)
+              if (!isNaN(value)) {
+                return prev + curr
+              } else {
+                return prev
+              }
+            }, 0)
+            sums[index] = Number(sums[index].toFixed(2))
+          } else {
+            sums[index] = ''
+          }
+        } else if (prop === 'orderSignRate') {
+          const totalSign = data.reduce((sum, item) => sum + Number(item.signCount || 0), 0)
+          const totalDelivery = data.reduce((sum, item) => sum + Number(item.deliveryCount || 0), 0)
+          sums[index] = this.calcRate(totalSign, totalDelivery)
+        } else if (prop === 'amountSignRate') {
+          const totalSignAmount = data.reduce((sum, item) => sum + Number(item.signAmount || 0), 0)
+          const totalDeliveryAmount = data.reduce((sum, item) => sum + Number(item.deliveryAmount || 0), 0)
+          sums[index] = this.calcRate(totalSignAmount, totalDeliveryAmount)
+        } else {
+          sums[index] = ''
+        }
+      })
+      return sums
+    },
+    calcRate(numerator, denominator) {
+      if (!denominator || denominator === 0) return '0%'
+      const rate = (Number(numerator) / Number(denominator) * 100).toFixed(2)
+      return rate + '%'
+    }
+  }
+}
+</script>

+ 150 - 0
src/views/store/signReport/index.vue

@@ -0,0 +1,150 @@
+<template>
+  <div class="app-container">
+    <!-- 查询条件 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="80px">
+      <el-form-item label="订单编号" prop="orderCode">
+        <el-input v-model="queryParams.orderCode" placeholder="请输入订单编号" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="运单号" prop="deliverySn">
+        <el-input v-model="queryParams.deliverySn" placeholder="请输入运单号" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="会员姓名" prop="userName">
+        <el-input v-model="queryParams.userName" placeholder="请输入会员姓名" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="地址" prop="userAddress">
+        <el-input v-model="queryParams.userAddress" placeholder="请输入地址" clearable size="small" @keyup.enter.native="handleQuery" />
+      </el-form-item>
+      <el-form-item label="发货日期" prop="deliveryTime">
+        <el-date-picker
+          v-model="deliveryTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="handleDeliveryTimeChange"
+        />
+      </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="warning" plain icon="el-icon-download" size="mini" :loading="exportLoading" @click="handleExport">导出</el-button>
+      </el-col>
+    </el-row>
+
+    <!-- 签收未回款列表 -->
+    <el-table v-loading="loading" border :data="tableList" style="width:100%">
+      <el-table-column label="订单编号" align="center" prop="orderCode" min-width="160" />
+      <el-table-column label="运单号" align="center" prop="deliverySn" min-width="140" show-overflow-tooltip />
+      <el-table-column label="会员姓名" align="center" prop="userName" min-width="80" />
+      <el-table-column label="地址" align="center" prop="userAddress" min-width="180" show-overflow-tooltip />
+      <el-table-column label="发货日期" align="center" prop="deliveryTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.deliveryTime ? parseTime(scope.row.deliveryTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="定金" align="center" prop="payPrice" min-width="90" />
+      <el-table-column label="代收金额" align="center" prop="collectionPrice" min-width="90" />
+      <el-table-column label="订单总金额" align="center" prop="totalPrice" min-width="100" />
+      <el-table-column label="跟单时间" align="center" prop="followTime" min-width="150">
+        <template slot-scope="scope">
+          <span>{{ scope.row.followTime ? parseTime(scope.row.followTime) : '-' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="快递公司" align="center" prop="deliveryName" min-width="100" />
+      <el-table-column label="部门" align="center" prop="deptName" min-width="120" show-overflow-tooltip />
+      <el-table-column label="公司" align="center" prop="companyName" min-width="140" show-overflow-tooltip />
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </div>
+</template>
+
+<script>
+import { listSignOrderReport, exportSignOrderReport } from '@/api/store/signReport'
+
+export default {
+  name: 'SignReport',
+  data() {
+    return {
+      loading: false,
+      exportLoading: false,
+      total: 0,
+      tableList: [],
+      deliveryTime: null,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        deliverySn: null,
+        userName: null,
+        userAddress: null
+      }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    getList() {
+      this.loading = true
+      listSignOrderReport(this.queryParams).then(response => {
+        this.tableList = response.rows || []
+        this.total = response.total || 0
+        this.loading = false
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    handleDeliveryTimeChange(val) {
+      if (val) {
+        this.queryParams.deliveryStartTime = val[0]
+        this.queryParams.deliveryEndTime = val[1]
+      } else {
+        delete this.queryParams.deliveryStartTime
+        delete this.queryParams.deliveryEndTime
+      }
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.deliveryTime = null
+      delete this.queryParams.deliveryStartTime
+      delete this.queryParams.deliveryEndTime
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    handleExport() {
+      this.$confirm('确认导出签收未回款报表?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.exportLoading = true
+        return exportSignOrderReport(this.queryParams)
+      }).then(response => {
+        this.download(response.msg)
+        this.exportLoading = false
+      }).catch(() => {
+        this.exportLoading = false
+      })
+    }
+  }
+}
+</script>