浏览代码

Merge branch 'test' into 'master'

Test

See merge request quanshu/mp-ui-pc!92
zhong chunping 3 年之前
父节点
当前提交
79be83529d

+ 93 - 0
src/api/business/order.js

@@ -0,0 +1,93 @@
+import request from '@/utils/request'
+
+// 经销商订单
+export function getOrderList(urlParams, data) {
+    return request({
+        url: '/api/v1/mp/admin/channel/order/list',
+        method: 'post',
+        data,
+        urlParams
+    })
+}
+
+// 快递下拉
+export function companyList(data) {
+  return request({
+    url: '/api/v1/mp/delivery/company/list',
+    method: 'post',
+    data
+  })
+}
+
+// 经销商盲票组列表
+export function channelList(data) {
+  return request({
+    url: '/api/v1/mp/admin/channel/order/item/list',
+    method: 'post',
+    data
+  })
+}
+
+// 经销商订单发货查询筛选待售的盲票包列表
+export function ticketPkgList(data) {
+  return request({
+    url: '/api/v1/mp/admin/channel/order/ticket/pkg/list',
+    method: 'post',
+    data
+  })
+}
+
+// 经销商订单详情
+export function orderDetail(data) {
+  return request({
+    url: '/api/v1/mp/admin/channel/order/detail',
+    method: 'post',
+    data
+  })
+}
+
+// 经销商订单发货
+export function channelOrderShip(data) {
+  return request({
+    url: '/api/v1/mp/admin/channel/order/ship',
+    method: 'post',
+    data
+  })
+}
+
+// 用户订单
+export function getDeliverList(urlParams, data) {
+  return request({
+      url: '/api/v1/mp/admin/deliver/order/list',
+      method: 'post',
+      data,
+      urlParams
+  })
+}
+
+// 用户订单详情
+export function deliverDetail(data) {
+  return request({
+    url: '/api/v1/mp/admin/deliver/order/detail',
+    method: 'post',
+    data
+  })
+}
+
+// 用户订单发货
+export function deliverOrderShip(data) {
+  return request({
+    url: '/api/v1/mp/admin/deliver/order/ship',
+    method: 'post',
+    data
+  })
+}
+
+// 用户订单导出
+export function deliverOrderExport(data) {
+  return request({
+    url: '/api/v1/mp/admin/deliver/order/export',
+    method: 'post',
+    data
+  })
+}

+ 29 - 0
src/api/finance/withdraw.js

@@ -0,0 +1,29 @@
+import request from '@/utils/request'
+
+// 提现申请列表
+export function withdrawList(urlParams, data) {
+  return request({
+    url: '/api/v1/mp/admin/channel/withdraw/list',
+    method: 'post',
+    data,
+    urlParams
+  })
+}
+
+// 提现申请详情
+export function withdrawDetail(data) {
+  return request({
+    url: '/api/v1/mp/admin/channel/withdraw/detail',
+    method: 'post',
+    data
+  })
+}
+
+// 审核提现申请
+export function withdrawVerify(data) {
+  return request({
+    url: '/api/v1/mp/admin/channel/withdraw/verify',
+    method: 'post',
+    data
+  })
+}

+ 142 - 0
src/views/finance/withdraw/components/Detail.vue

@@ -0,0 +1,142 @@
+<template>
+  <div>
+    <el-dialog
+      title="提现申请"
+      :visible.sync="dialogShow"
+      width="800px"
+      :before-close="close"
+    >
+      <el-form label-width="130px">
+        <div class="form-flex">
+          <el-form-item label="渠道/经销商名称:">
+            <span>{{ info.name || "--" }}</span>
+          </el-form-item>
+          <el-form-item label="手机号码:">
+            <span>{{ info.mobile || "--" }}</span>
+          </el-form-item>
+        </div>
+        <div class="form-flex">
+          <el-form-item label="渠道类型:">
+            <span>{{ info.level == 0 ? "经销商" : "渠道" }}</span>
+          </el-form-item>
+          <el-form-item label="提现状态:">
+            <span>{{ JSON.parse(info.status).desc || "--" }}</span>
+          </el-form-item>
+        </div>
+        <div class="form-flex">
+          <el-form-item label="申请时间:">
+            <span>{{ parseTime(info.createTime) || "--" }}</span>
+          </el-form-item>
+          <el-form-item label="处理时间:">
+            <span>{{ parseTime(info.transferTime) || "--" }}</span>
+          </el-form-item>
+        </div>
+        <div class="form-flex">
+          <el-form-item label="提现金额:">
+            <span>¥{{ $numberFormat(info.money) || "--" }}</span>
+          </el-form-item>
+          <el-form-item label="银行卡号:">
+            <span>{{ info.cardNo || "--" }}</span>
+          </el-form-item>
+        </div>
+        <div class="form-flex">
+          <el-form-item label="持卡人:">
+            <span>{{ info.userName || "--" }}</span>
+          </el-form-item>
+          <el-form-item label="开户行:">
+            <span>{{ info.branchName || "--" }}</span>
+          </el-form-item>
+        </div>
+      </el-form>
+      <div
+        slot="footer"
+        class="dialog-footer"
+        v-if="JSON.parse(info.status).value == 1"
+      >
+        <el-button :disabled="loading" @click="toWithdrawal(3)"
+          >提现失败</el-button
+        >
+        <el-button type="primary" :disabled="loading" @click="toWithdrawal(2)"
+          >提现成功</el-button
+        >
+      </div>
+      <div slot="footer" class="dialog-footer" v-else>
+        <el-button @click="close">关闭</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { withdrawVerify } from "@/api/finance/withdraw";
+export default {
+  props: {
+    // 弹框显示
+    dialogShow: {
+      type: Boolean,
+      default: false,
+    },
+    // 提现id
+    info: {
+      type: Object,
+      default: {},
+    },
+  },
+  mounted() {
+    this.getDetail;
+  },
+  data() {
+    return {
+      loading: false,
+    };
+  },
+  methods: {
+    // 订单详情
+    getDetail() {
+      withdrawDetail({ id: this.detailId }).then((res) => {
+        console.log("res", res);
+      });
+    },
+
+    // 关闭弹框
+    close() {
+      this.$emit("close");
+    },
+
+    toWithdrawal(status) {
+      this.loading = true;
+      withdrawVerify({
+        id: this.info.id,
+        status,
+        verifyContent: "",
+      })
+        .then((res) => {
+          this.loading = false;
+          if (res.code == 0) {
+            if (status == 2) {
+              this.msgSuccess("操作成功");
+              this.close();
+            } else {
+              this.msgSuccess("操作成功");
+              this.close();
+            }
+          }
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.form-flex {
+  padding: 0 50px;
+  display: flex;
+  align-items: center;
+  // justify-content: space-between;
+  span {
+    display: inline-block;
+    width: 200px;
+  }
+}
+</style>

+ 258 - 0
src/views/finance/withdraw/index.vue

@@ -0,0 +1,258 @@
+<template>
+  <div class="app-container">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      :inline="true"
+      v-show="showSearch"
+      label-width="120px"
+    >
+      <el-form-item label="渠道/经销商名称">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入渠道/经销商名称"
+          clearable
+          size="small"
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="申请时间">
+        <el-date-picker
+          v-model="tradeTimeArr"
+          type="datetimerange"
+          size="small"
+          value-format="timestamp"
+          range-separator="至"
+          start-placeholder="时间选择"
+          end-placeholder="时间选择"
+          @change="tardeTime"
+        >
+        </el-date-picker>
+      </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">
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
+    </el-row>
+    <!-- 列表状态 -->
+    <el-tabs type="card" v-model="state" @tab-click="handleClick">
+      <el-tab-pane label="全部" name="null"></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-tabs>
+    <!-- 列表 -->
+    <el-table ref="table" v-loading="loading" :data="list">
+      <!-- 不展开列表 -->
+      <el-table-column label="申请时间" min-width="100">
+        <template slot-scope="{ row }">
+          <div>
+            {{ parseTime(row.createTime) }}
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="处理时间" min-width="100">
+        <template slot-scope="{ row }">
+          <div v-if="row.status.value === 3">{{ parseTime(row.updateTime) || "--" }}</div>
+          <div v-else>{{ parseTime(row.transferTime) || "--" }}</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="渠道名称" prop="name" min-width="85" />
+      <el-table-column label="手机号码" prop="mobile" min-width="85" />
+      <el-table-column label="渠道类型" prop="addr" min-width="80">
+        <template slot-scope="{ row }">
+          <div>{{ row.level == 0 ? "经销商" : "渠道" }}</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="提现金额(元)" align="center">
+        <template slot-scope="{ row }">
+          <div>{{ $numberFormat(row.money) }}</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="提现状态" prop="addr" min-width="80">
+        <template slot-scope="{ row }">
+          <div>
+            <el-tag type="success" v-if="row.status.value === 1">待提现</el-tag>
+            <el-tag type="info" v-else>{{ row.status.desc }}</el-tag>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="80">
+        <template slot-scope="{ row }">
+          <div>
+            <el-button
+              v-hasPermi="['finance:withdraw:query']"
+              type="text"
+              @click="getDetail(row)"
+              >查看</el-button
+            >
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="pageParams.pageNum"
+      :limit.sync="pageParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 订单详情 -->
+    <withdraw-detail v-if="detailShow" :dialog-show="detailShow" :info="detailInfo" @close="close" />
+  </div>
+</template>
+<script>
+import { withdrawList, withdrawDetail } from "@/api/finance/withdraw";
+import WithdrawDetail from './components/Detail'
+export default {
+  name: "Withdraw",
+  components: {
+    WithdrawDetail
+  },
+  data() {
+    return {
+      loading: false,
+      showSearch: true,
+      // 筛选
+      queryParams: {
+        name: "",
+        startDay: "",
+        startTime: "",
+        channelId: "",
+        status: null,
+      },
+      // 分页
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+      // 总条数
+      total: 0,
+      list: [],
+      // 列表状态
+      state: "null",
+      // 申请时间
+      tradeTimeArr: [],
+      // 弹框显示
+      detailShow: false,
+      // 提现id
+      id: ''
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    // 提现列表
+    getList() {
+      this.loading = true;
+      withdrawList(
+        "pageNum=" +
+          this.pageParams.pageNum +
+          "&pageSize=" +
+          this.pageParams.pageSize +
+          "&",
+        this.queryParams
+      )
+        .then((res) => {
+          this.loading = false;
+          if (res.code == 0) {
+            res.rows.forEach((item) => {
+              item.status = JSON.parse(item.status);
+            });
+            this.total = res.total;
+            this.list = res.rows;
+          }
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+
+    // 搜索
+    handleQuery() {
+      this.getList()
+    },
+
+    // 重置
+    resetQuery() {
+      this.queryParams = {
+        name: "",
+        startDay: "",
+        startTime: "",
+        channelId: "",
+        status: null,
+      };
+      this.state = "null";
+      this.tradeTimeArr = [];
+      this.getList();
+    },
+
+    // 列表状态切换
+    handleClick(e) {
+      this.queryParams.status = Number(e.name);
+      this.getList();
+    },
+
+    // 选择申请时间
+    tardeTime(e) {
+      if (e) {
+        this.queryParams.startDay = e[0];
+        this.queryParams.startTime = e[1];
+        this.handleQuery();
+      } else {
+        this.queryParams.startDay = "";
+        this.queryParams.startTime = "";
+        this.handleQuery();
+      }
+    },
+
+    // 查看详情
+    getDetail(row) {
+      this.id = row.id
+      this.getDetailInfo()
+    },
+
+    // 订单详情
+    getDetailInfo() {
+      withdrawDetail({ id: this.id }).then(res=>{
+        console.log('res', res)
+        if(res.code == 0){
+          this.detailInfo = res.data
+          this.detailShow = true;
+        }
+      })
+    },
+
+    // 弹框关闭
+    close() {
+      this.detailShow = false;
+      this.getList();
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+::v-deep .el-tabs--border-card > .el-tabs__content {
+  padding: 0;
+}
+</style>

+ 278 - 0
src/views/order/channel/components/SendGoods.vue

@@ -0,0 +1,278 @@
+<template>
+  <div>
+    <el-dialog
+      title="订单发货"
+      :visible.sync="sendShow"
+      width="800px"
+      :before-close="close"
+    >
+      <el-form
+        :model="shipForm"
+        ref="shipForm"
+        :rules="rules"
+        label-width="100px"
+      >
+        <el-form-item label="订单号:">
+          <span>{{ goodsInfo.orderId }}</span>
+        </el-form-item>
+        <el-form-item label="收货地址:">
+          <span>{{
+            `${goodsInfo.receiver},${goodsInfo.tel},${goodsInfo.province}${goodsInfo.city}${goodsInfo.area}${goodsInfo.address}`
+          }}</span>
+        </el-form-item>
+        <el-form-item label="快递公司:" prop="companyName">
+          <el-select
+            v-model="shipForm.companyName"
+            placeholder="请选择快递公司"
+            clearable
+            size="small"
+            style="width: 500px"
+          >
+            <el-option
+              v-for="item in companyData"
+              :key="item.areaId"
+              :label="item.companyName"
+              :value="item.companyName"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="快递单号:" prop="deliveryFlowId">
+          <el-input
+            v-model="shipForm.deliveryFlowId"
+            placeholder="输入快递单号"
+            clearable
+            size="small"
+            style="width: 500px"
+          />
+        </el-form-item>
+        <el-form-item label="盲票组:">
+          <el-select
+            v-model="shipForm.boxId"
+            placeholder="请选择盲票组"
+            clearable
+            size="small"
+            style="width: 500px"
+          >
+            <el-option
+              v-for="item in channelList"
+              :key="item.areaId"
+              :label="item.title"
+              :value="item.boxId"
+            >
+              <div class="channel">
+                <div>{{ item.boxNo }}</div>
+                <div>{{ item.title }}</div>
+                <div>{{ item.orderNum }}包</div>
+              </div>
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="盲票包序号:">
+          <el-autocomplete
+            v-model="pkgNo"
+            :fetch-suggestions="querySearch"
+            placeholder="输入盲票包序号"
+            size="small"
+            :disabled="shipForm.boxId ? false : true"
+            style="width: 500px"
+            @select="handleSelect"
+          >
+            <template slot-scope="{ item }">
+              <div class="channel">
+                <div>{{ item.startSn }}至{{ item.endSn }}</div>
+                <div>{{ item.title }}</div>
+              </div>
+            </template>
+          </el-autocomplete>
+        </el-form-item>
+      </el-form>
+      <!-- 选中盲票组列表 -->
+      <div class="table">
+        <el-table ref="table" :data="list">
+          <el-table-column label="盲票组" prop="title" />
+          <el-table-column label="盲票包系列号范围" min-width="100">
+            <template slot-scope="{ row }">
+              <div>
+                <div>{{ row.startSn }}至{{ row.endSn }}</div>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" width="50">
+            <template slot-scope="scope">
+              <div>
+                <el-button
+                  type="text"
+                  size="small"
+                  @click="delList(scope.$index, scope.row)"
+                  >删除</el-button
+                >
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <!-- 按钮 -->
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="close">取 消</el-button>
+        <el-button type="primary" :disabled="loading" @click="saveClick"
+          >确 定</el-button
+        >
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import CustomFieldsMixin from "@/mixins/CustomFields";
+import {
+  companyList,
+  ticketPkgList,
+  channelOrderShip,
+} from "@/api/business/order";
+export default {
+  mixins: [CustomFieldsMixin],
+  props: {
+    // 发货弹框显示
+    sendShow: {
+      type: Boolean,
+      default: false,
+    },
+    // 订单详情
+    goodsInfo: {
+      type: Object,
+      default: {},
+    },
+    // 盲票组下拉列表
+    channelList: {
+      type: Array,
+      default: [],
+    },
+  },
+  created() {
+    this.getCompanyList();
+  },
+  data() {
+    return {
+      loading: false,
+      shipForm: {
+        companyName: "",
+        deliveryFlowId: "",
+        boxId: "",
+      },
+      // 快递下拉列表
+      companyData: [],
+      // 盲票组序列号
+      pkgNo: "",
+      // 选中盲票组列表
+      list: [],
+      rules: {
+        companyName: [
+          { required: true, message: "请选择快递公司", trigger: "change" },
+        ],
+        deliveryFlowId: [
+          { required: true, message: "请输入快递单号", trigger: "blur" },
+        ],
+      },
+    };
+  },
+  methods: {
+    // 关闭发货弹框
+    close() {
+      this.$emit("close");
+      this.loading = false;
+      this.list = [];
+      this.shipForm.boxId = "";
+      this.$refs["shipForm"].resetFields();
+    },
+
+    // 快递下拉列表
+    getCompanyList() {
+      companyList({}).then((res) => {
+        this.companyData = res.data;
+      });
+    },
+
+    // 查询盲票组序列号
+    querySearch(queryString, cb) {
+      ticketPkgList({
+        orderId: this.goodsInfo.orderId,
+        boxId: this.shipForm.boxId,
+        pkgNo: this.pkgNo,
+      }).then((res) => {
+        cb(res.data);
+      });
+    },
+
+    // 选中盲票组序列号
+    handleSelect(item) {
+      let index = this.list.findIndex(ele=>{
+        return item.pkgId == ele.pkgId
+      })
+      if(index != -1){
+        this.msgError("当前票包已选!");
+        return
+      }
+      this.list.push(item);
+    },
+
+    // 删除选中盲票组序列号
+    delList(index, row) {
+      this.list.splice(index, 1);
+    },
+
+    // 确认
+    saveClick() {
+      this.loading = true;
+      const subForm = this.$refs["shipForm"];
+      subForm.validate((valid) => {
+        if (valid) {
+          this.submitForm(this.shipForm);
+        } else {
+          this.loading = false;
+          // 提示第一个error
+          this.getFormErrorMessage(subForm);
+          return false;
+        }
+      });
+    },
+
+    // 提交
+    submitForm(form) {
+      let ids = this.list.map((item) => item.pkgId);
+      if (!ids.length) {
+        this.msgError("请选择发货的票包");
+        this.loading = false;
+        return;
+      }
+      if (this.goodsInfo.pkgNum != ids.length) {
+        this.msgError(
+          `应发${this.goodsInfo.pkgNum}包,实际选中${ids.length}包`
+        );
+        this.loading = false;
+        return;
+      }
+      let data = {
+        ...form,
+        orderId: this.goodsInfo.orderId,
+        pkgIds: ids,
+      };
+      channelOrderShip(data)
+        .then((res) => {
+          if (res.code == 0) {
+            this.msgSuccess("发货成功");
+            this.close();
+          }
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+  },
+};
+</script>
+<style scoped>
+.channel {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+</style>

+ 257 - 0
src/views/order/channel/detail.vue

@@ -0,0 +1,257 @@
+<template>
+  <div class="app-container">
+    <!-- 订单信息 -->
+    <div class="info">
+      <div class="info-title">订单信息</div>
+      <div class="info-item">
+        <div class="info-item-content">
+          <div class="info-item-content-one">
+            <div class="title">订单编号:</div>
+            <div class="txt">{{ info.orderId }}</div>
+          </div>
+          <div class="info-item-content-one">
+            <div class="title">订单类型:</div>
+            <div class="txt">经销商订单</div>
+          </div>
+        </div>
+        <div class="info-item-content">
+          <div class="info-item-content-one">
+            <div class="title">下单时间:</div>
+            <div class="txt">{{ parseTime(info.createdTime) }}</div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 卖家信息 -->
+    <div class="info">
+      <div class="info-title">买家信息</div>
+      <div class="info-item">
+        <div class="info-item-content">
+          <div class="info-item-content-one">
+            <div class="title">经销商:</div>
+            <div class="txt">{{ info.channel && info.channel.name }}</div>
+          </div>
+          <div class="info-item-content-one">
+            <div class="title">收货人:</div>
+            <div class="txt">{{ info.receiver || "--" }}</div>
+          </div>
+          <div class="info-item-content-one">
+            <div class="title">联系电话:</div>
+            <div class="txt">{{ info.tel || "--" }}</div>
+          </div>
+        </div>
+        <div class="info-item-content">
+          <div class="info-item-content-one">
+            <div class="title">收货地址:</div>
+            <div class="">
+              {{
+                `${info.province || "--"}${info.city || "--"}${
+                  info.area || "--"
+                }${info.address || "--"}`
+              }}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 订单状态 -->
+    <div class="info">
+      <div class="info-title">订单状态</div>
+      <div class="info-item">
+        <div class="info-item-content">
+          <div class="info-item-content-one">
+            <div class="title">订单状态:</div>
+            <div class="txt" v-if="status.value == 2">已发货</div>
+            <div class="txt" v-else>{{ status.desc || "--" }}</div>
+          </div>
+          <div class="info-item-content-one" v-if="status.value === 2">
+            <div class="title">发货时间:</div>
+            <div class="txt">{{ parseTime(info.deliveryTime) || "--" }}</div>
+          </div>
+        </div>
+        <div class="info-item-content">
+          <el-button
+            v-if="status.value === 1"
+            v-hasPermi="['business:ticket:on']"
+            type="primary"
+            @click="toGoods()"
+            >发货</el-button
+          >
+          <div class="info-item-content-one" v-if="status.value === 2">
+            <div class="title">快递公司:</div>
+            <div class="txt">{{ delivery.companyName || "--" }}</div>
+          </div>
+          <div class="info-item-content-one" v-if="status.value === 2">
+            <div class="title">快递单号:</div>
+            <div class="txt">{{ info.deliveryFlowId || "--" }}</div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 商品信息 -->
+    <div class="info">
+      <div class="info-title">商品信息</div>
+      <div class="info-table">
+        <el-table :data="list">
+          <el-table-column label="商品信息">
+            <div slot-scope="{ row }" class="flex">
+              <el-image
+                style="width: 100px; height: 100px"
+                :src="row.picUrl"
+                :preview-src-list="[row.picUrl]"
+              />
+              <div class="txt">{{ row.title }}</div>
+            </div>
+          </el-table-column>
+          <el-table-column label="单价(元)">
+            <template slot-scope="{ row }">
+              <div>{{ $numberFormat(row.pkgSalePrice) }}</div>
+            </template>
+          </el-table-column>
+          <el-table-column label="数量" prop="orderNum">
+            <template slot-scope="{ row }">
+              <div>{{ row.orderNum }}包</div>
+            </template>
+          </el-table-column>
+          <el-table-column label="小计(元)">
+            <template slot-scope="{ row }">
+              <div>{{ $numberFormat(row.pkgSalePrice * row.orderNum) }}</div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="info-amt">
+        <div class="info-amt-price">
+          <span>运费:</span>{{ $numberFormat(info.freightAmt) }}元
+        </div>
+        <div class="info-amt-price">
+          <span>共计金额:</span>{{ $numberFormat(info.orderAmt) }}元
+        </div>
+      </div>
+    </div>
+
+    <!-- 发货 -->
+    <send-goods
+      :send-show="goodsShow"
+      :goods-info="info"
+      :channel-list="boxData"
+      @close="close"
+    />
+  </div>
+</template>
+<script>
+import { orderDetail, channelList } from "@/api/business/order";
+import { publicFileGetUrl } from "@/api/common";
+import { accMul } from "@/utils/util";
+import SendGoods from "./components/SendGoods";
+export default {
+  name: "Detail",
+  components: {
+    SendGoods,
+  },
+  data() {
+    return {
+      // 订单ID
+      orderId: "",
+      // 订单详情
+      info: {},
+      // 订单状态
+      status: {},
+      // 物流信息
+      delivery: {},
+      // 商品列表
+      list: [],
+      // 发货弹框显示
+      goodsShow: false,
+      // 盲票组列表
+      boxData: [],
+    };
+  },
+  created() {
+    this.orderId = this.$route.query.id;
+    this.getDetail();
+    this.getChannelList();
+  },
+  methods: {
+    // 盲票组列表
+    getChannelList(row) {
+      channelList({ orderId: this.orderId }).then((res) => {
+        this.boxData = res.data;
+      });
+    },
+
+    // 订单详情
+    getDetail() {
+      orderDetail({ orderId: this.orderId }).then((res) => {
+        if (res.code == 0) {
+          this.info = res.data;
+          this.status = JSON.parse(res.data.status);
+          this.delivery = res.data.deliveryCompany;
+          res.data.items.forEach((item) => {
+            let picUrlArr = item.picUrl.split(",");
+            item.picUrl = publicFileGetUrl + picUrlArr[0];
+          });
+          this.list = res.data.items;
+        }
+      });
+    },
+
+    // 点击发货
+    toGoods() {
+      this.goodsShow = true;
+    },
+
+    // 发货弹框关闭
+    close() {
+      this.goodsShow = false;
+      this.getDetail();
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.info {
+  margin-bottom: 10px;
+  &-title {
+    font-size: 14px;
+    margin-bottom: 10px;
+    font-weight: bold;
+  }
+  &-item {
+    padding-left: 50px;
+    &-content {
+      display: flex;
+
+      &-one {
+        display: flex;
+        margin-bottom: 10px;
+
+        .title {
+          width: 100px;
+        }
+
+        .txt {
+          width: 200px;
+        }
+      }
+    }
+  }
+  &-amt {
+    margin-top: 10px;
+    &-price {
+      span {
+        display: inline-block;
+        width: 80px;
+        margin-bottom: 20px;
+      }
+    }
+  }
+}
+.flex {
+  display: flex;
+  align-items: center;
+  .txt {
+    margin-left: 20px;
+  }
+}
+</style>

+ 344 - 0
src/views/order/channel/index.vue

@@ -0,0 +1,344 @@
+<template>
+  <div class="app-container">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      :inline="true"
+      v-show="showSearch"
+      label-width="90px"
+    >
+      <el-form-item label="盲票组名称">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入盲票组名称"
+          clearable
+          size="small"
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="订单号">
+        <el-input
+          v-model="queryParams.orderId"
+          placeholder="输入订单编号"
+          clearable
+          size="small"
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <!-- <el-form-item label="经销商">
+        <el-select
+          v-model="queryParams.channelId"
+          placeholder="可输入经销商名称/手机号码搜索"
+          clearable
+          filterable
+          size="small"
+          style="width: 240px"
+          @change="handleQuery"
+        >
+          <el-option
+            v-for="item in merchantArr"
+            :key="item.areaId"
+            :label="item.areaName"
+            :value="item.areaId"
+          />
+        </el-select>
+      </el-form-item> -->
+      <el-form-item label="下单时间">
+        <el-date-picker
+          v-model="tradeTimeArr"
+          type="datetimerange"
+          size="small"
+          value-format="timestamp"
+          range-separator="至"
+          start-placeholder="时间选择"
+          end-placeholder="时间选择"
+          @change="tardeTime"
+        >
+        </el-date-picker>
+      </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">
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
+    </el-row>
+    <!-- 订单状态 -->
+    <el-tabs type="card" v-model="state" @tab-click="handleClick">
+      <el-tab-pane label="全部订单" name="null"></el-tab-pane>
+      <el-tab-pane label="待付款" name="0"></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="-1"></el-tab-pane>
+    </el-tabs>
+    <!-- 列表 -->
+    <el-table ref="table" v-loading="loading" :data="list">
+      <!-- 展开 -->
+      <el-table-column type="expand">
+        <template slot-scope="{ row }">
+          <el-table :data="row.items">
+            <el-table-column label="盲票组图片" min-width="80">
+              <div slot-scope="{ row }">
+                <el-image
+                  style="width: 100px; height: 100px"
+                  :src="row.picUrl"
+                  :preview-src-list="[row.picUrl]"
+                />
+              </div>
+            </el-table-column>
+            <el-table-column label="盲票组名称" prop="title" min-width="80" />
+            <el-table-column label="采购单价(元)" min-width="100">
+              <template slot-scope="{ row }">
+                <div>{{ $numberFormat(row.pkgSalePrice) }}</div>
+              </template>
+            </el-table-column>
+            <el-table-column label="数量" prop="orderNum" min-width="85">
+              <template slot-scope="{ row }">
+                <div>{{ row.orderNum }}包</div>
+              </template>
+            </el-table-column>
+          </el-table>
+        </template>
+      </el-table-column>
+      <el-table-column label="订单号" prop="orderId" min-width="80" />
+      <el-table-column label="下单时间" min-width="100">
+        <template slot-scope="{ row }">
+          <div>
+            {{ parseTime(row.createdTime) }}
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="数量" prop="pkgNum" min-width="85">
+        <template slot-scope="{ row }">
+          <div>{{ row.pkgNum }}包</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="实付金额(元)" min-width="85">
+        <template slot-scope="{ row }">
+          <div>{{ $numberFormat(row.payAmt) }}</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="经销商" prop="channelName" min-width="80" />
+      <el-table-column label="收货人/收货地址" prop="addr" min-width="120">
+        <template slot-scope="{ row }">
+          <div>
+            {{
+              `${row.receiver},${row.tel},${row.province}${row.city}${row.area}${row.address}`
+            }}
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="订单状态" align="center">
+        <template slot-scope="{ row }">
+          <div>
+            <el-tag :type="row.status.value === 1 ? 'success' : 'info'" v-if="row.status.value !== 2">{{
+              row.status.desc
+            }}</el-tag>
+            <el-tag type="info" v-else>已发货</el-tag>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="80">
+        <template slot-scope="{ row }">
+          <div>
+            <el-button
+              v-hasPermi="['order:channel:query']"
+              type="text"
+              @click="getDetail(row)"
+              >查看详情</el-button
+            >
+            <el-button
+              v-if="row.status.value === 1"
+              v-hasPermi="['order:channel:ship']"
+              type="text"
+              @click="toGoods(row)"
+              >发货</el-button
+            >
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="pageParams.pageNum"
+      :limit.sync="pageParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 发货 -->
+    <send-goods
+      :send-show="goodsShow"
+      :goods-info="goodsInfo"
+      :channel-list="boxData"
+      @close="close"
+    />
+  </div>
+</template>
+<script>
+import { getOrderList, companyList, channelList } from "@/api/business/order";
+import { publicFileGetUrl } from "@/api/common";
+import SendGoods from "./components/SendGoods";
+export default {
+  name: "Channel",
+  components: {
+    SendGoods,
+  },
+  data() {
+    return {
+      loading: false,
+      showSearch: true,
+      // 筛选
+      queryParams: {
+        title: "",
+        orderId: "",
+        startTime: "",
+        endTime: "",
+        channelId: "",
+        status: null,
+      },
+      // 分页
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+      // 总条数
+      total: 0,
+      list: [],
+      // 经销商
+      merchantArr: [],
+      // 下单时间
+      tradeTimeArr: [],
+      // 订单列表状态
+      state: "null",
+      // 弹框显示
+      goodsShow: false,
+      // 订单详情
+      goodsInfo: {},
+      // 盲票组下拉列表
+      boxData: [],
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    // 订单列表
+    getList() {
+      this.loading = true;
+      getOrderList(
+        "pageNum=" +
+          this.pageParams.pageNum +
+          "&pageSize=" +
+          this.pageParams.pageSize +
+          "&",
+        this.queryParams
+      )
+        .then((res) => {
+          this.loading = false;
+          if (res.code == 0) {
+            res.rows.forEach((item) => {
+              let items = item.items;
+              items.forEach((item) => {
+                let picUrlArr = item.picUrl.split(",");
+                item.picUrl = publicFileGetUrl + picUrlArr[0];
+              });
+              item.status = JSON.parse(item.status);
+            });
+            this.total = res.total;
+            this.list = res.rows;
+          }
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+
+    // 盲票组列表
+    getChannelList(row) {
+      channelList({ orderId: row.orderId }).then((res) => {
+        this.boxData = res.data;
+      });
+    },
+
+    //搜索
+    handleQuery() {
+      this.getList();
+    },
+
+    // 重置
+    resetQuery() {
+      this.queryParams = {
+        title: "",
+        orderId: "",
+        startTime: "",
+        endTime: "",
+        channelId: "",
+        status: null,
+      };
+      this.state = "null"
+      this.tradeTimeArr = [];
+      this.getList();
+    },
+
+    // 选择下单时间
+    tardeTime(e) {
+      if (e) {
+        this.queryParams.startTime = e[0];
+        this.queryParams.endTime = e[1];
+        this.handleQuery();
+      } else {
+        this.queryParams.startTime = "";
+        this.queryParams.endTime = "";
+        this.handleQuery();
+      }
+    },
+
+    // 订单切换
+    handleClick(e) {
+      this.queryParams.status = Number(e.name);
+      this.getList();
+    },
+
+    // 查看详情
+    getDetail(row) {
+      this.$router.push({ name: "Detail", query: { id: row.orderId } });
+    },
+
+    // 点击发货
+    toGoods(row) {
+      this.goodsShow = true;
+      this.goodsInfo = row;
+      this.getChannelList(row);
+    },
+
+    // 关闭发货弹框
+    close() {
+      this.goodsShow = false;
+      this.getList();
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+::v-deep .el-tabs--border-card > .el-tabs__content {
+  padding: 0;
+}
+</style>

+ 214 - 0
src/views/order/deliver/components/SendGoods.vue

@@ -0,0 +1,214 @@
+<template>
+  <div>
+    <el-dialog
+      title="订单发货"
+      :visible.sync="sendShow"
+      width="1000px"
+      :before-close="close"
+    >
+      <el-form
+        :model="shipForm"
+        ref="shipForm"
+        :rules="rules"
+        label-width="100px"
+      >
+        <el-form-item label="订单号:">
+          <span>{{ goodsInfo.orderId }}</span>
+        </el-form-item>
+        <el-form-item label="收货地址:">
+          <span>{{
+            `${goodsInfo.receiver},${goodsInfo.tel},${goodsInfo.province}${goodsInfo.city}${goodsInfo.area}${goodsInfo.address}`
+          }}</span>
+        </el-form-item>
+        <el-form-item label="快递公司:" prop="companyName">
+          <el-select
+            v-model="shipForm.companyName"
+            placeholder="请选择快递公司"
+            clearable
+            size="small"
+            style="width: 300px"
+          >
+            <el-option
+              v-for="item in companyData"
+              :key="item.areaId"
+              :label="item.companyName"
+              :value="item.companyName"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="快递单号:" prop="deliveryFlowId">
+          <el-input
+            v-model="shipForm.deliveryFlowId"
+            placeholder="输入快递单号"
+            clearable
+            size="small"
+            style="width: 300px"
+          />
+        </el-form-item>
+      </el-form>
+      <!-- 商品 -->
+      <el-table
+        ref="table"
+        :data="goodsInfo.items"
+        @selection-change="handleSelectionGoods"
+        class="ticket-table"
+      >
+        <el-table-column
+          type="selection"
+          width="55"
+          align="center"
+          fixed="left"
+        />
+        <el-table-column label="商品名称" prop="title" />
+        <el-table-column label="规格">
+          <template slot-scope="{ row }">
+            <div>{{ row.properties || "--" }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="数量">
+          <template slot-scope="{ row }">
+            <div>{{ row.goodsNum }}件</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="快递公司">
+          <template slot-scope="{ row }">
+            <div>{{ row.companyName || "--" }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="快递单号">
+          <template slot-scope="{ row }">
+            <div>{{ row.deliveryFlowId || "--" }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="发货状态">
+          <template slot-scope="{ row }">
+            <div>{{ row.deliveryFlowId ? "已发货" : "未发货" }}</div>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="close">取 消</el-button>
+        <el-button type="primary" :disabled="loading" @click="saveClick"
+          >确 定</el-button
+        >
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import CustomFieldsMixin from "@/mixins/CustomFields";
+import { companyList, deliverOrderShip } from "@/api/business/order";
+export default {
+  mixins: [CustomFieldsMixin],
+  props: {
+    // 弹框显示
+    sendShow: {
+      type: Boolean,
+      default: false,
+    },
+    // 订单详情
+    goodsInfo: {
+      type: Object,
+      default: {},
+    },
+  },
+  created() {
+    this.getCompanyList();
+  },
+  data() {
+    return {
+      loading: false,
+      shipForm: {
+        companyName: "",
+        deliveryFlowId: "",
+      },
+      // 快递下拉列表
+      companyData: [],
+      // 选中sp
+      goodsList: [],
+      // 选中商品ID
+      ids: [],
+      rules: {
+        companyName: [
+          { required: true, message: "请选择快递公司", trigger: "change" },
+        ],
+        deliveryFlowId: [
+          { required: true, message: "请输入快递单号", trigger: "blur" },
+        ],
+      },
+    };
+  },
+  methods: {
+    // 关闭发货弹框
+    close() {
+      this.$emit("close");
+      this.loading = false;
+      this.ids = [];
+      this.$refs["shipForm"].resetFields();
+    },
+
+    // 快递下拉列表
+    getCompanyList() {
+      companyList({}).then((res) => {
+        this.companyData = res.data;
+      });
+    },
+
+    // 选中商品
+    handleSelectionGoods(e) {
+      this.goodsList = e
+    },
+
+    // 确认
+    saveClick() {
+      this.loading = true;
+      const subForm = this.$refs["shipForm"];
+      subForm.validate((valid) => {
+        if (valid) {
+          this.submitForm(this.shipForm);
+        } else {
+          this.loading = false;
+          // 提示第一个error
+          this.getFormErrorMessage(subForm);
+          return false;
+        }
+      });
+    },
+
+    // 提交
+    submitForm(form) {
+      if (!this.goodsList.length) {
+        this.msgError("请选择发货的商品");
+        this.loading = false;
+        return;
+      }
+      let index = this.goodsList.findIndex(item=>{
+        return item.deliveryFlowId
+      })
+      if(index != -1){
+        this.msgError(`${ this.goodsList[index].title }已发货!`);
+        this.loading = false;
+        return
+      }
+      this.ids = this.goodsList.map((item) => item.itemId);
+      let data = {
+        ...form,
+        orderId: this.goodsInfo.orderId,
+        itemIds: this.ids,
+      };
+      deliverOrderShip(data)
+        .then((res) => {
+          if (res.code == 0) {
+            this.msgSuccess("发货成功");
+            this.close();
+          }
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+  },
+};
+</script>
+<style>
+</style>

+ 315 - 0
src/views/order/deliver/detail.vue

@@ -0,0 +1,315 @@
+<template>
+  <div class="app-container">
+    <!-- 订单信息 -->
+    <div class="info">
+      <div class="info-title">订单信息</div>
+      <div class="info-item">
+        <div class="info-item-content">
+          <div class="info-item-content-one">
+            <div class="title">订单编号:</div>
+            <div class="txt">{{ info.orderId }}</div>
+          </div>
+          <div class="info-item-content-one">
+            <div class="title">订单类型:</div>
+            <div class="txt">用户提货订单</div>
+          </div>
+        </div>
+        <div class="info-item-content">
+          <div class="info-item-content-one">
+            <div class="title">下单时间:</div>
+            <div class="txt">{{ parseTime(info.createdTime) }}</div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 买家信息 -->
+    <div class="info">
+      <div class="info-title">买家信息</div>
+      <div class="info-item">
+        <div class="info-item-content">
+          <div class="info-item-content-one">
+            <div class="title">用户昵称:</div>
+            <div class="txt">{{ info.nickName || "--" }}</div>
+          </div>
+          <div class="info-item-content-one">
+            <div class="title">收货人:</div>
+            <div class="txt">{{ info.receiver || "--" }}</div>
+          </div>
+          <div class="info-item-content-one">
+            <div class="title">联系电话:</div>
+            <div class="txt">{{ info.tel || "--" }}</div>
+          </div>
+        </div>
+        <div class="info-item-content">
+          <div class="info-item-content-one">
+            <div class="title">收货地址:</div>
+            <div class="">
+              {{
+                `${info.province || "--"}${info.city || "--"}${
+                  info.area || "--"
+                }${info.address || "--"}`
+              }}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 订单状态 -->
+    <div class="info">
+      <div class="info-title">订单状态</div>
+      <div class="info-item">
+        <div class="info-item-content">
+          <div class="info-item-content-one">
+            <div class="title">订单状态:</div>
+            <div class="txt" v-if="status.value == 2">已发货</div>
+            <div class="txt" v-else>{{ status.desc || "--" }}</div>
+          </div>
+        </div>
+        <div class="info-item-content">
+          <el-button
+            v-if="status.value === 1 || status.value === 4"
+            v-hasPermi="['business:ticket:on']"
+            type="primary"
+            @click="toGoods()"
+            >发货</el-button
+          >
+        </div>
+      </div>
+    </div>
+    <!-- 物流信息 -->
+    <div class="info" v-if="status.value === 2 || status.value === 4">
+      <div class="info-title">物流信息</div>
+      <div class="info-item">
+        <div
+          class="info-item-logistics"
+          v-for="(item, index) in deliverList"
+          :key="index"
+        >
+          <div class="logistics-title">快递{{ index + 1 }}</div>
+          <div class="info">
+            <div class="info-one">
+              <div class="tit">快递公司:</div>
+              <div class="txt">{{ item.companyName || "--" }}</div>
+            </div>
+            <div class="info-one">
+              <div class="tit">快递单号:</div>
+              <div class="txt">{{ item.deliveryFlowId || "--" }}</div>
+            </div>
+            <div class="info-one">
+              <div class="tit">发货时间:</div>
+              <div class="txt">{{ parseTime(item.deliveryTime) || "--" }}</div>
+            </div>
+          </div>
+          <div class="goods">
+            <div class="goods-item" v-for="(ele, ins) in item.items" :key="ins">
+              <img :src="ele.picUrl" alt="" />
+              <div class="info">
+                <div>{{ ele.title || "--" }}</div>
+                <div>{{ ele.properties || "--" }}</div>
+                <div>{{ ele.goodsNum }}件</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- 商品信息 -->
+    <div class="info">
+      <div class="info-title">商品信息</div>
+      <div class="info-table">
+        <el-table :data="list">
+          <el-table-column label="商品信息" min-width="200">
+            <div slot-scope="{ row }" class="flex">
+              <el-image
+                style="width: 100px; height: 100px"
+                :src="row.picUrl"
+                :preview-src-list="[row.picUrl]"
+              />
+              <div class="txt">{{ row.title }}</div>
+            </div>
+          </el-table-column>
+          <el-table-column label="规格" min-width="100">
+            <template slot-scope="{ row }">
+              <div>{{ row.properties || "--" }}</div>
+            </template>
+          </el-table-column>
+          <el-table-column label="数量" prop="orderNum">
+            <template slot-scope="{ row }">
+              <div>{{ row.goodsNum }}件</div>
+            </template>
+          </el-table-column>
+          <el-table-column label="状态">
+            <template slot-scope="{ row }">
+              <div>{{ row.deliveryFlowId ? "已发货" : "未发货" }}</div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <!-- 按钮 -->
+      <div class="info-amt">
+        <div class="info-amt-price">
+          <span>运费:</span>{{ $numberFormat(info.freightAmt) }}元
+        </div>
+        <div class="info-amt-price">
+          <span>共计金额:</span>{{ $numberFormat(info.orderAmt) }}元
+        </div>
+      </div>
+    </div>
+
+    <!-- 发货 -->
+    <send-goods :send-show="goodsShow" :goods-info="info" @close="close" />
+  </div>
+</template>
+<script>
+import { deliverDetail } from "@/api/business/order";
+import { publicFileGetUrl } from "@/api/common";
+import SendGoods from "./components/SendGoods";
+export default {
+  name: "UserDetail",
+  components: {
+    SendGoods,
+  },
+  data() {
+    return {
+      // 订单ID
+      orderId: "",
+      // 订单详情
+      info: {},
+      // 订单状态
+      status: {},
+      // 商品信息列表
+      list: [],
+      // 物流信息性别
+      deliverList: [],
+      // 发货显示
+      goodsShow: false,
+    };
+  },
+  created() {
+    this.orderId = this.$route.query.id;
+    this.getDetail();
+  },
+  methods: {
+    // 订单详情
+    getDetail() {
+      deliverDetail({ orderId: this.orderId }).then((res) => {
+        if (res.code == 0) {
+          this.info = res.data;
+          this.status = JSON.parse(res.data.status);
+          res.data.deliverList &&
+            res.data.deliverList.forEach((item) => {
+              item.items.forEach((ele) => {
+                let picUrlArr = ele.picUrl.split(",");
+                ele.picUrl = publicFileGetUrl + picUrlArr[0];
+              });
+            });
+          this.deliverList = res.data.deliverList;
+          res.data.items &&
+            res.data.items.forEach((item) => {
+              let picUrlArr = item.picUrl.split(",");
+              item.picUrl = publicFileGetUrl + picUrlArr[0];
+            });
+          this.list = res.data.items;
+        }
+      });
+    },
+
+    // 点击发货
+    toGoods() {
+      this.goodsShow = true;
+    },
+
+    // 发货关闭
+    close() {
+      this.goodsShow = false;
+      this.getDetail();
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.info {
+  margin-bottom: 10px;
+  &-title {
+    font-size: 14px;
+    margin-bottom: 20px;
+    font-weight: bold;
+  }
+  &-item {
+    padding-left: 50px;
+    &-content {
+      display: flex;
+
+      &-one {
+        display: flex;
+        margin-bottom: 10px;
+
+        .title {
+          width: 100px;
+        }
+
+        .txt {
+          width: 200px;
+        }
+      }
+    }
+
+    &-logistics {
+      margin-bottom: 20px;
+      .logistics-title {
+        text-align: left;
+        font-weight: bold;
+        margin-bottom: 20px;
+      }
+      .info {
+        display: flex;
+        margin-bottom: 10px;
+        &-one {
+          display: flex;
+        }
+        .tit {
+          width: 100px;
+        }
+        .txt {
+          width: 200px;
+        }
+      }
+      .goods {
+        margin: 10px 0;
+        &-item {
+          display: flex;
+          border-bottom: 1px solid #f3eeee;
+          img {
+            width: 100px;
+            height: 100px;
+          }
+          .info {
+            padding-left: 20px;
+            display: flex;
+            flex-direction: column;
+            height: 100px;
+            justify-content: space-between;
+          }
+        }
+      }
+    }
+  }
+  &-amt {
+    margin-top: 10px;
+    &-price {
+      span {
+        display: inline-block;
+        width: 80px;
+        margin-bottom: 20px;
+      }
+    }
+  }
+}
+.flex {
+  display: flex;
+  align-items: center;
+  .txt {
+    margin-left: 20px;
+  }
+}
+</style>

+ 370 - 0
src/views/order/deliver/index.vue

@@ -0,0 +1,370 @@
+<template>
+  <div class="app-container">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      :inline="true"
+      v-show="showSearch"
+      label-width="90px"
+    >
+      <el-form-item label="用户昵称">
+        <el-input
+          v-model="queryParams.nickName"
+          placeholder="请输入用户昵称"
+          clearable
+          size="small"
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="商品名称">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入商品名称"
+          clearable
+          size="small"
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="订单号">
+        <el-input
+          v-model="queryParams.orderId"
+          placeholder="输入订单编号"
+          clearable
+          size="small"
+          style="width: 240px"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="下单时间">
+        <el-date-picker
+          v-model="tradeTimeArr"
+          type="datetimerange"
+          size="small"
+          value-format="timestamp"
+          range-separator="至"
+          start-placeholder="时间选择"
+          end-placeholder="时间选择"
+          @change="tardeTime"
+        >
+        </el-date-picker>
+      </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">
+      <el-col :span="1.5">
+        <el-button
+          type="infor"
+          plain
+          icon="el-icon-printer"
+          size="small"
+          @click="handleExportDraw"
+          v-hasPermi="['order:deliver:export']"
+          >导出订单</el-button
+        >
+      </el-col>
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
+    </el-row>
+    <div class="ge"></div>
+    <!-- 订单状态 -->
+    <el-tabs type="card" v-model="state" @tab-click="handleClick">
+      <el-tab-pane label="全部订单" name="no"></el-tab-pane>
+      <el-tab-pane label="待付款" name="0"></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="4"></el-tab-pane>
+      <el-tab-pane label="已完成" name="3"></el-tab-pane>
+      <el-tab-pane label="已取消" name="-1"></el-tab-pane>
+    </el-tabs>
+    <!-- 列表 -->
+    <el-table ref="table" v-loading="loading" :data="list">
+      <!-- 展开盲票组列表 -->
+      <el-table-column type="expand">
+        <template slot-scope="{ row }">
+          <el-table :data="row.items">
+            <el-table-column label="商品图片" min-width="80">
+              <div slot-scope="{ row }">
+                <el-image
+                  style="width: 100px; height: 100px"
+                  :src="row.picUrl"
+                  :preview-src-list="[row.picUrl]"
+                />
+              </div>
+            </el-table-column>
+            <el-table-column label="商品名称" prop="title" min-width="80" />
+            <el-table-column label="规格" min-width="100">
+              <template slot-scope="{ row }">
+                <div>{{ row.properties || "--" }}</div>
+              </template>
+            </el-table-column>
+            <el-table-column label="数量" prop="orderNum" min-width="85">
+              <template slot-scope="{ row }">
+                <div>{{ row.goodsNum }}件</div>
+              </template>
+            </el-table-column>
+          </el-table>
+        </template>
+      </el-table-column>
+      <!-- 不展开列表 -->
+      <el-table-column label="订单号" prop="orderId" min-width="80" />
+      <el-table-column label="下单时间" min-width="100">
+        <template slot-scope="{ row }">
+          <div>
+            {{ parseTime(row.createdTime) }}
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="数量" prop="pkgNum" min-width="85">
+        <template slot-scope="{ row }">
+          <div>{{ row.orderNum }}件</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="支付金额(元)" min-width="85">
+        <template slot-scope="{ row }">
+          <div>{{ $numberFormat(row.payAmt) }}</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="用户昵称" prop="nickName" min-width="80" />
+      <el-table-column label="收货人/收货地址" prop="addr" min-width="120">
+        <template slot-scope="{ row }">
+          <div>
+            {{
+              `${row.receiver},${row.tel},${row.province}${row.city}${row.area}${row.address}`
+            }}
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="订单状态" align="center">
+        <template slot-scope="{ row }">
+          <div>
+            <el-tag :type="row.status.value === 1 ? 'success' : 'info'" v-if="row.status.value !== 2">{{
+              row.status.desc
+            }}</el-tag>
+            <el-tag type="info" v-else>已发货</el-tag>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="80">
+        <template slot-scope="{ row }">
+          <div>
+            <el-button
+              v-hasPermi="['order:deliver:query']"
+              type="text"
+              @click="getDetail(row)"
+              >查看详情</el-button
+            >
+            <el-button
+              v-if="row.status.value === 1 || row.status.value === 4"
+              v-hasPermi="['order:deliver:ship']"
+              type="text"
+              @click="toGoods(row)"
+              >发货</el-button
+            >
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="pageParams.pageNum"
+      :limit.sync="pageParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 发货 -->
+    <send-goods :send-show="goodsShow" :goods-info="goodsInfo" @close="close" />
+  </div>
+</template>
+<script>
+import {
+  getDeliverList,
+  deliverOrderExport,
+} from "@/api/business/order";
+import { publicFileGetUrl } from "@/api/common";
+import SendGoods from "./components/SendGoods";
+export default {
+  name: "Deliver",
+  components: {
+    SendGoods,
+  },
+  data() {
+    return {
+      loading: false,
+      showSearch: true,
+      // 筛选
+      queryParams: {
+        nickName: "",
+        title: "",
+        orderId: "",
+        startTime: "",
+        endTime: "",
+        status: "",
+      },
+      // 分页
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+      // 总条数
+      total: 0,
+      list: [],
+      // 经销商
+      merchantArr: [],
+      // 下单时间
+      tradeTimeArr: [],
+      // 订单列表状态
+      state: "no",
+      // 发货显示
+      goodsShow: false,
+      // 订单详情
+      goodsInfo: {},
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    // 订单列表
+    getList() {
+      this.loading = true;
+      getDeliverList(
+        "pageNum=" +
+          this.pageParams.pageNum +
+          "&pageSize=" +
+          this.pageParams.pageSize +
+          "&",
+        this.queryParams
+      )
+        .then((res) => {
+          this.loading = false;
+          if (res.code == 0) {
+            res.rows.forEach((item) => {
+              let items = item.items;
+              items.forEach((item) => {
+                let picUrlArr = item.picUrl.split(",");
+                item.picUrl = publicFileGetUrl + picUrlArr[0];
+              });
+              item.status = JSON.parse(item.status);
+            });
+            this.total = res.total;
+            this.list = res.rows;
+          }
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+
+    //搜索
+    handleQuery() {
+      this.getList();
+    },
+
+    // 重置
+    resetQuery() {
+      this.queryParams = {
+        nickName: "",
+        title: "",
+        orderId: "",
+        startTime: "",
+        endTime: "",
+        status: "",
+      };
+      this.state = "no"
+      this.tradeTimeArr = [];
+      this.getList();
+    },
+
+    // 选择下单时间
+    tardeTime(e) {
+      if (e) {
+        this.queryParams.startTime = e[0];
+        this.queryParams.endTime = e[1];
+        this.handleQuery();
+      } else {
+        this.queryParams.startTime = "";
+        this.queryParams.endTime = "";
+        this.handleQuery();
+      }
+    },
+
+    // 订单切换
+    handleClick(e) {
+      if (e.name == "no") {
+        this.queryParams.status = "";
+      } else {
+        this.queryParams.status = Number(e.name);
+      }
+      this.getList();
+    },
+
+    // 查看详情
+    getDetail(row) {
+      this.$router.push({ name: "UserDetail", query: { id: row.orderId } });
+    },
+
+    // 点击发货
+    toGoods(row) {
+      this.goodsShow = true;
+      this.goodsInfo = row;
+    },
+
+    // 关闭发货
+    close() {
+      this.goodsShow = false;
+      this.getList();
+    },
+
+    // 导出订单
+    handleExportDraw() {
+      this.$confirm("是否确认导出订单?", "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.vloading = this.$loading({
+            lock: true,
+            text: "正在导出订单.....",
+            background: "rgba(0, 0, 0, 0.7)",
+          });
+          return deliverOrderExport(this.queryParams);
+        })
+        .then((response) => {
+          this.vloading.close();
+          this.download(response.msg);
+        })
+        .catch(() => {
+          this.vloading.close();
+        });
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+::v-deep .el-tabs--border-card > .el-tabs__content {
+  padding: 0;
+}
+.ge {
+  height: 20px;
+}
+</style>