Ver código fonte

修改订单发货清单

YY 2 anos atrás
pai
commit
f0ccc0d77e

+ 69 - 0
src/components/orderParts/card-3.vue

@@ -0,0 +1,69 @@
+<template>
+  <div id="card-1">
+    <el-row>
+      <el-col :span="24" class="main">
+        <detail-1 v-if="num == '1'" @toDeliver="toDeliver" :statusList="statusList" @toDetails="toDetails" @toSaless="toSaless"></detail-1>
+        <detail-2 v-else-if="num == '2'" :deliverList="list" @toBack="toBack"></detail-2>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+const _ = require('lodash');
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'card-1',
+  props: { statusList: { type: Array } },
+  components: {
+    detail1: () => import('./parts/detail-1.vue'),
+    detail2: () => import('./parts/detail-2.vue'),
+  },
+  data: function () {
+    return {
+      num: '1',
+      list: [],
+    };
+  },
+  async created() {},
+  methods: {
+    // 生成发货清单
+    toDeliver({ data }) {
+      if (data.length == '0') {
+        this.$message('请选择订单');
+      } else {
+        this.$set(this, 'list', data);
+        this.$set(this, 'num', '2');
+      }
+    },
+    toBack() {
+      this.$set(this, 'num', '1');
+    },
+    toDetails(val) {
+      this.$emit('toDetails', val);
+    },
+    toSaless(val) {
+      this.$emit('toSaless', { id: val.id, status: val.status });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.one {
+  margin: 0 0 10px 0;
+}
+</style>

+ 148 - 0
src/components/orderParts/parts/detail-1.vue

@@ -0,0 +1,148 @@
+<template>
+  <div id="card-1">
+    <el-row>
+      <el-col :span="24" class="main" v-loading="loadings" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
+        <el-col :span="24" v-if="num == '1'">
+          <el-col :span="24" class="one">
+            <search-1 :form="searchForm" @onSubmit="search" @querySearch="querySearch" @toReset="toClose" :shopList="shopList"> </search-1>
+          </el-col>
+          <el-col :span="24" class="one">
+            <el-button type="primary" size="mini" @click="toDeliver()">生成发货清单</el-button>
+            <p>(发货清单里不显示售后的订单)</p>
+          </el-col>
+          <data-table
+            :select="true"
+            :selected="selected"
+            @handleSelect="handleSelect"
+            :fields="fields"
+            :opera="opera"
+            @query="search"
+            :data="list"
+            :total="total"
+            @detail="toDetail"
+            @sales="toSales"
+          >
+          </data-table>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+const _ = require('lodash');
+
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions } = createNamespacedHelpers('orderDetail');
+const { mapActions: shop } = createNamespacedHelpers('shop');
+export default {
+  name: 'card-1',
+  props: { statusList: { type: Array } },
+  components: { search1: () => import('../search-1.vue') },
+  data: function () {
+    return {
+      loadings: true,
+      num: '1',
+      searchForm: {},
+      list: [],
+      total: 0,
+      opera: [
+        { label: '详情', method: 'detail' },
+        { label: '售后', method: 'sales', type: 'danger' },
+      ],
+      fields: [
+        { label: '订单号', model: 'no', showTip: false },
+        { label: '下单时间', model: 'buy_time' },
+        { label: '顾客', model: 'customer.name' },
+        { label: '收货人', model: 'address', showTip: false, format: (i) => this.getAddress(i) },
+        // { label: '店铺名称', model: 'shop.name' },
+        { label: '支付金额', model: 'real_pay' },
+        { label: '商品数量', model: 'buy_num_total' },
+        { label: '是否售后', model: 'is_afterSale', format: (i) => (i === true ? '该订单有商品申请售后' : '未申请售后') },
+      ],
+      // 多选值
+      selected: [],
+      shopList: [],
+      // 发货清单
+      deliverList: [],
+      deliver: '0',
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...shop({ shopQuery: 'query' }),
+    ...mapActions(['query', 'fetch', 'create', 'update', 'delete']),
+    // 查询
+    async search({ skip = 0, limit = this.$limit, ...info } = {}) {
+      let condition = _.cloneDeep(this.searchForm);
+      if (condition.buy_time) {
+        condition[`buy_time@start`] = _.head(condition.buy_time);
+        condition[`buy_time@end`] = _.last(condition.buy_time);
+        delete condition.buy_time;
+      }
+      info.status = '1';
+      let res = await this.query({ skip, limit, ...condition, ...info, shop: this.user.shop.id });
+      if (this.$checkRes(res)) {
+        this.$set(this, 'list', res.data);
+        this.$set(this, 'total', res.total);
+      }
+      this.loadings = false;
+    },
+    getAddress(i) {
+      let name = i.name + ',' + i.phone;
+      return name;
+    },
+    // 详情
+    toDetail({ data }) {
+      this.$emit('toDetails', data._id);
+    },
+    toSales({ data }) {
+      this.$emit('toSaless', { id: data._id, status: '1' });
+    },
+    toClose() {
+      this.searchForm = {};
+      this.search();
+    },
+    // 多选
+    handleSelect(data) {
+      this.$set(this, 'deliverList', data);
+    },
+    // 生成发货清单
+    toDeliver() {
+      this.$emit('toDeliver', { data: this.deliverList });
+    },
+    // 店铺名称远程查询
+    async querySearch(value) {
+      let res = await this.shopQuery({ name: value });
+      if (this.$checkRes(res)) {
+        this.$set(this, 'shopList', res.data);
+      }
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.one {
+  margin: 0 0 10px 0;
+  p {
+    font-size: 12px;
+    color: #777;
+  }
+}
+</style>

+ 263 - 0
src/components/orderParts/parts/detail-2.vue

@@ -0,0 +1,263 @@
+<template>
+  <div id="form-1">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col class="top_btn"><el-button type="primary" size="mini" @click="toBack()">返回</el-button></el-col>
+        <el-col :span="24" class="one"> <span>发货清单</span> </el-col>
+        <el-col class="top_btn"> <el-button type="primary" @click="toFile()">导出清单</el-button></el-col>
+        <el-col :span="24" class="two">
+          <el-col :span="15" v-for="(item, index) in list" :key="index">
+            <el-card class="box-card">
+              <el-col class="clearfix">
+                <el-col>收货人:{{ item.address.name }},{{ item.address.phone }}</el-col>
+                <el-col>收货人地址:{{ item.address.province }},{{ item.address.city }},{{ item.address.area }},{{ item.address.address }}</el-col>
+              </el-col>
+              <el-col class="two_1">
+                <data-table
+                  :select="true"
+                  :selected="selected"
+                  @handleSelect="(e) => handleSelect(e, item.address)"
+                  rowKey="index"
+                  :usePage="false"
+                  :fields="fields"
+                  :data="item.goodsList"
+                >
+                </data-table>
+              </el-col>
+            </el-card>
+          </el-col>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+const _ = require('lodash');
+import FileSaver from 'file-saver';
+const ExcelJS = require('exceljs');
+import { mapState, mapGetters, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'form-1',
+  props: { deliverList: { type: Array } },
+  components: {},
+  data: function () {
+    return {
+      list: [],
+      fields: [
+        { label: '订单编号', model: 'order_no' },
+        { label: '商品名称', model: 'goods.name' },
+        { label: '商品规格', model: 'name' },
+        { label: '商品数量', model: 'buy_num' },
+      ],
+      selected: [],
+      fileList: [],
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    // 查询
+    async search() {
+      let data = this.deliverList;
+      if (data) {
+        let test = _(data).groupBy('address._id').values().value();
+        let list = [];
+        for (const p1 of test) {
+          let goodsList = [];
+          for (const p2 of p1) {
+            if (p2.is_afterSale == false) {
+              for (let p3 of p2.goods) {
+                // _.pick(p3, ['goods', 'name', 'buy_num']);
+                // let p3_2 = (({ goods, name, buy_num }) => ({ goods, name, buy_num }))(p3);
+                delete p3.flow_money;
+                delete p3.freight;
+                delete p3.id;
+                delete p3.status;
+                delete p3._id;
+                delete p3.meta;
+                delete p3.num;
+                delete p3.sell_money;
+                delete p3.__v;
+                delete p3.tags;
+                delete p3.cart_id;
+                delete p3.can_group;
+                delete p3.group_config;
+                delete p3.url;
+                let good = (({ name }) => ({ name }))(p3.goods);
+                p3.goods = good;
+                p3.order_no = p2.no;
+              }
+              goodsList.push(...p2.goods);
+              let i = 0;
+              for (const p4 of goodsList) {
+                p4.index = i;
+                i++;
+              }
+            }
+          }
+          let address = _.pick(p1[0].address, ['name', 'phone', 'province', 'city', 'area', 'address', '_id']);
+          // let address = (({ name, phone, province, city, area, address, _id }) => ({ name, phone, province, city, area, address, _id }))(p1[0].address);
+          list.push({ goodsList, address });
+        }
+        this.$set(this, 'list', list);
+      }
+    },
+    // 选中要导出的商品
+    handleSelect(goodsList, address) {
+      let fileList = this.fileList;
+      if (fileList.length == 0) {
+        fileList.push({ goodsList, address });
+      } else {
+        if (goodsList.length > 0) {
+          for (const val of fileList) {
+            if (address._id == val.address._id) {
+              val.goodsList = goodsList;
+            } else {
+              fileList.push({ goodsList, address });
+            }
+          }
+        } else {
+          let p1 = fileList.filter((i) => i.address._id != address._id);
+          fileList = p1;
+        }
+      }
+      let list = _.uniqBy(fileList, 'address._id');
+      this.$set(this, 'fileList', list);
+    },
+    // 导出清单
+    toFile() {
+      const workbook = new ExcelJS.Workbook();
+      let list = this.fileList;
+      for (let [index, p1] of list.entries()) {
+        let name = p1.address.name + index;
+        const worksheet = workbook.addWorksheet(name);
+        // 设置标题-start
+        // 获取单元格位置
+        let titleCell = worksheet.getCell('A1');
+        // 合并单元格
+        worksheet.mergeCells('A1:D1');
+        // 单元格内容
+        titleCell.value = '发货清单';
+        worksheet.columns.forEach(function (column, i) {
+          column.font = {
+            size: 14,
+          };
+          column.width = 38;
+          column.alignment = {
+            wrapText: true,
+            vertical: 'middle',
+            horizontal: 'left',
+          };
+          column.border = {
+            top: { style: 'thin' },
+            left: { style: 'thin' },
+            bottom: { style: 'thin' },
+            right: { style: 'thin' },
+          };
+        });
+        // 单元格内容样式
+        titleCell.style = {
+          alignment: {
+            vertical: 'middle',
+            horizontal: 'center',
+          },
+          font: {
+            size: 20,
+            bold: true,
+          },
+          border: {
+            top: { style: 'thin' },
+            left: { style: 'thin' },
+            bottom: { style: 'thin' },
+            right: { style: 'thin' },
+          },
+        };
+        // 设置标题-end
+        let data = [
+          ['收获人', p1.address.name],
+          ['联系电话', p1.address.phone],
+          ['收货地址', p1.address.province + p1.address.city + p1.address.area + p1.address.address],
+          ['订单号', '产品名称', '产品规格', '购买数量'],
+        ];
+        for (const p2 of p1.goodsList) {
+          let p4 = [[p2.order_no, p2.goods.name, p2.name, p2.buy_num]];
+          data.push(...p4);
+        }
+        const row = worksheet.getRow(1);
+        row.height = 40;
+        for (const val of data) {
+          worksheet.addRow(val);
+        }
+      }
+      workbook.xlsx.writeBuffer().then((buffer) => {
+        FileSaver.saveAs(
+          new Blob([buffer], {
+            type: 'application/octet-stream',
+          }),
+          `发货清单.xlsx`
+        );
+      });
+    },
+    // 返回
+    toBack() {
+      this.$emit('toBack');
+    },
+  },
+  computed: {
+    data() {
+      return this.$route.query.data;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  .top_btn {
+    margin: 0 0 10px 0;
+  }
+  .one {
+    margin: 0 0 10px 0;
+    span:nth-child(1) {
+      font-size: 20px;
+      font-weight: 700;
+      margin-right: 10px;
+    }
+  }
+  .two {
+    margin: 5px 10%;
+    .data-table {
+      margin: 5px 0;
+    }
+    .clearfix {
+      margin: 4px 0;
+      .el-col {
+        margin: 4px 0;
+      }
+    }
+    .box-card {
+      margin: 5px;
+      padding: 5px 0 20px 0;
+    }
+    .shop {
+      text-align: center;
+      font-size: 18px;
+    }
+    .item {
+      margin-bottom: 18px;
+    }
+  }
+}
+</style>

+ 2 - 5
src/views/selfShop/order/index.vue

@@ -15,12 +15,8 @@
               <el-tab-pane label="待付款" name="1">
                 <card-1 :statusList="statusList" @toDetail="toDetail" @toSales="toSales"></card-1>
               </el-tab-pane>
-
               <el-tab-pane label="待发货" name="2">
-                <el-col :span="24" class="one">
-                  <search-1 :form="searchForm" @onSubmit="search" @querySearch="querySearch" @toReset="toClose" :shopList="shopList"> </search-1>
-                </el-col>
-                <data-table :fields="fields" :opera="opera" @query="search" :data="list" :total="total" @detail="toDetails" @sales="toSaless"> </data-table>
+                <card-2 :statusList="statusList" @toDetail="toDetails" @toSales="toSaless"></card-2>
               </el-tab-pane>
               <el-tab-pane label="部分发货" name="3">
                 <el-col :span="24" class="one">
@@ -87,6 +83,7 @@ export default {
   props: {},
   components: {
     card1: () => import('@/components/orderParts/card-2.vue'),
+    card2: () => import('@/components/orderParts/card-3.vue'),
     detail_order: () => import('@/components/orderParts/detail/detail_order.vue'),
     detail_orderDetail: () => import('@/components/orderParts/detail/detail_orderDetail.vue'),
     detail_sales_order: () => import('@/components/orderParts/detail/detail_sales_order.vue'),