Explorar o código

对接智能补货

chenrui %!s(int64=3) %!d(string=hai) anos
pai
achega
89401e4a66

+ 33 - 0
src/api/predict.js

@@ -0,0 +1,33 @@
+import { axios } from '@/utils/request'
+
+//  智能补货列表  无分页
+export const predictList = (params) => {
+  return axios({
+    url: '/predict/stockPredict/queryList',
+    data: params,
+    method: 'post'
+  })
+}
+//  智能补货  产品范围列表  无分页
+export const predictRangeList = (params) => {
+  const url = `/predict/stockPredict/queryRangeList/${params.sn}`
+  return axios({
+    url: url,
+    method: 'get'
+  })
+}
+//  智能补货  趋势平均列表
+export const predictTrendList = (params) => {
+  return axios({
+    url: '/predict/stockPredict/queryTrendList',
+    method: 'get'
+  })
+}
+//  智能补货  保存
+export const predictSave = (params) => {
+  return axios({
+    url: '/predict/stockPredict/save',
+    data: params,
+    method: 'post'
+  })
+}

BIN=BIN
src/assets/explain/def_calculation.png


BIN=BIN
src/assets/explain/icon_example.png


BIN=BIN
src/assets/explain/icon_inventory.png


BIN=BIN
src/assets/explain/icon_mete.png


BIN=BIN
src/assets/explain/icon_sales.png


BIN=BIN
src/assets/explain/pressed_gray.png


+ 85 - 0
src/config/router.config.js

@@ -1012,6 +1012,91 @@ export const asyncRouterMap = [
               icon: 'alert'
               icon: 'alert'
               // permission: 'M_goodsShelves_0'
               // permission: 'M_goodsShelves_0'
             }
             }
+          },
+          {
+            path: '/inventoryManagement/intelligentReplenishment',
+            redirect: '/inventoryManagement/intelligentReplenishment/list',
+            name: 'intelligentReplenishment',
+            component: RouteView,
+            meta: {
+              title: '智能补货',
+              icon: 'monitor'
+              // permission: 'M_intelligentReplenishmentList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'intelligentReplenishmentList',
+                component: () => import(/* webpackChunkName: "shop" */ '@/views/inventoryManagement/intelligentReplenishment/list.vue'),
+                meta: {
+                  title: '智能补货列表',
+                  icon: 'monitor',
+                  hidden: true
+                  // permission: 'M_intelligentReplenishmentList'
+                }
+              },
+              {
+                path: 'add/:sn',
+                name: 'intelligentReplenishmentAdd',
+                component: () => import(/* webpackChunkName: "shop" */ '@/views/inventoryManagement/intelligentReplenishment/edit.vue'),
+                meta: {
+                  title: '新增智能补货',
+                  icon: 'monitor',
+                  hidden: true
+                }
+              },
+              {
+                path: 'edit/:sn',
+                name: 'intelligentReplenishmentEdit',
+                component: () => import(/* webpackChunkName: "shop" */ '@/views/inventoryManagement/intelligentReplenishment/edit.vue'),
+                meta: {
+                  title: '编辑智能补货',
+                  icon: 'monitor',
+                  hidden: true
+                }
+              },
+              {
+                path: 'set/:sn',
+                name: 'intelligentReplenishmentSet',
+                component: () => import(/* webpackChunkName: "shop" */ '@/views/inventoryManagement/intelligentReplenishment/set.vue'),
+                meta: {
+                  title: '基础信息设置',
+                  icon: 'monitor',
+                  hidden: true
+                }
+              },
+              {
+                path: 'import/:sn',
+                name: 'intelligentReplenishmentImport',
+                component: () => import(/* webpackChunkName: "shop" */ '@/views/inventoryManagement/intelligentReplenishment/import.vue'),
+                meta: {
+                  title: '确认导入',
+                  icon: 'monitor',
+                  hidden: true
+                }
+              },
+              {
+                path: 'explainXsbz',
+                name: 'intelligentReplenishmentExplainXsbz',
+                component: () => import(/* webpackChunkName: "shop" */ '@/views/inventoryManagement/intelligentReplenishment/explainXsbz.vue'),
+                meta: {
+                  title: '销售保障法-说明',
+                  icon: 'monitor',
+                  hidden: true
+                }
+              },
+              {
+                path: 'explainQspj',
+                name: 'intelligentReplenishmentExplainQspj',
+                component: () => import(/* webpackChunkName: "shop" */ '@/views/inventoryManagement/intelligentReplenishment/explainQspj.vue'),
+                meta: {
+                  title: '趋势平均法-说明',
+                  icon: 'monitor',
+                  hidden: true
+                }
+              }
+            ]
           }
           }
           // 二期
           // 二期
           // {
           // {

+ 174 - 0
src/views/inventoryManagement/intelligentReplenishment/detailModal.vue

@@ -0,0 +1,174 @@
+<template>
+  <a-modal
+    centered
+    class="intelligentReplenishmentDetail-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="预测单详情"
+    v-model="isShow"
+    @cancle="isShow=false"
+    :width="800">
+    <div>
+      <a-alert type="info" showIcon style="margin-bottom:15px">
+        <div slot="message">此预测单的各项参数信息如下</div>
+      </a-alert>
+      <div class="module-cont">
+        <p class="title">产品范围</p>
+        <a-tag color="blue" style="margin-bottom: 10px;">自选产品</a-tag>
+        <s-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: 400 }"
+          bordered>
+        </s-table>
+      </div>
+      <div class="module-cont">
+        <p class="title">销售保障法</p>
+        <p class="explain">保障倍数:<span>1.5</span></p>
+      </div>
+      <div class="module-cont">
+        <p class="title">趋势平均法</p>
+        <p class="explain">服务水平:<span>90%(对应的安全系数为1.28)</span></p>
+      </div>
+      <div class="spin-cont">
+        按照以上参数设置,系统正在计算中,请耐心等待...
+        <a-spin style="margin-left: 15px;" />
+      </div>
+      <div class="btn-cont">
+        <a-button type="primary" id="intelligentReplenishmentDetail-save" @click="handleDownload">结果下载</a-button>
+        <a-button id="intelligentReplenishmentDetail-back" @click="isShow = false">关闭</a-button>
+      </div>
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import { STable } from '@/components'
+// import { custTypeSave } from '@/api/custType'
+export default {
+  name: 'IntelligentReplenishmentDetailModal',
+  components: { STable },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    itemId: {
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      detailsData: null, //  详情数据
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 80, align: 'center' },
+        { title: '类型', dataIndex: 'createDate', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '类型名称', dataIndex: 'name', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        // return custTypeList(Object.assign(parameter, this.queryParam)).then(res => {
+        //   const data = res.data
+        //   const no = (data.pageNo - 1) * data.pageSize
+        //   for (var i = 0; i < data.list.length; i++) {
+        //     data.list[i].no = no + i + 1
+        //   }
+        //   return data
+        // })
+        return new Promise(function (resolve, reject) {
+          const data = {
+            pageNo: 1,
+            pageSize: 10,
+            list: [
+              { id: '1', state: 1, purchaseNo: 'jgqp11111111111', creatDate: '产品1', custName: 'jgqp111123545', totalP: '箭冠品牌', totalNums: '产品分类1', totalPrice: '5', payType: '122' },
+              { id: '2', state: 2, purchaseNo: 'jgqp11111111111', creatDate: '产品1', custName: 'jgqp111123545', totalP: '箭冠品牌', totalNums: '产品分类1', totalPrice: '5', payType: '122' },
+              { id: '3', state: 3, purchaseNo: 'jgqp11111111111', creatDate: '产品1', custName: 'jgqp111123545', totalP: '箭冠品牌', totalNums: '产品分类1', totalPrice: '5', payType: '122' },
+              { id: '4', state: 4, purchaseNo: 'jgqp11111111111', creatDate: '产品1', custName: 'jgqp111123545', totalP: '箭冠品牌', totalNums: '产品分类1', totalPrice: '5', payType: '122' },
+              { id: '5', state: 5, purchaseNo: 'jgqp11111111111', creatDate: '产品1', custName: 'jgqp111123545', totalP: '箭冠品牌', totalNums: '产品分类1', totalPrice: '5', payType: '122' }
+            ],
+            count: 10
+          }
+          resolve(data)
+        })
+      }
+    }
+  },
+  methods: {
+    //  结果下载
+    handleDownload () {
+      const params = this.queryParam
+      this.downloadLoading = true
+      // stockExport(params).then(res => {
+      //   this.downloadLoading = false
+      //   this.download(res)
+      // })
+    },
+    download (data) {
+      if (!data) { return }
+      const url = window.URL.createObjectURL(new Blob([data]))
+      const link = document.createElement('a')
+      link.style.display = 'none'
+      link.href = url
+      const a = moment().format('YYYYMMDDHHmmss')
+      const fname = '智能补货' + a
+      link.setAttribute('download', fname + '.xlsx')
+      document.body.appendChild(link)
+      link.click()
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      }
+    },
+    itemId (newValue, oldValue) {
+      if (this.isShow && newValue) {
+
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .intelligentReplenishmentDetail-modal{
+    .module-cont{
+      border: 1px dashed #e8e8e8;
+      border-radius: 12px;
+      position: relative;
+      margin: 30px 0;
+      padding: 20px 15px 15px;
+      .title{
+        position: absolute;
+        left: 50px;
+        top: -12px;
+        padding: 0 10px;
+        background-color: #fff;
+      }
+      .explain{
+        margin-bottom: 5px;
+        font-weight: bold;
+      }
+    }
+    .spin-cont{
+      text-align: center;
+    }
+    .btn-cont {
+      text-align: center;
+      font-weight: bold;
+      margin: 35px 0 10px;
+    }
+  }
+</style>

+ 172 - 0
src/views/inventoryManagement/intelligentReplenishment/edit.vue

@@ -0,0 +1,172 @@
+<template>
+  <div class="intelligentReplenishmentEdit-wrap">
+    <a-page-header :ghost="false" :backIcon="false" class="intelligentReplenishmentEdit-back">
+      <!-- 自定义的二级文字标题 -->
+      <template slot="subTitle">
+        <a id="intelligentReplenishmentEdit-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+      </template>
+    </a-page-header>
+    <a-card size="small" :bordered="false" class="intelligentReplenishmentEdit-cont">
+      <div class="steps-cont">
+        <a-steps :current="current" size="small">
+          <a-step title="参数设置" />
+          <a-step title="系统计算" />
+        </a-steps>
+      </div>
+      <!-- 参数设置 -->
+      <div v-if="current==0">
+        <a-form-model
+          id="intelligentReplenishmentEdit-form"
+          ref="ruleForm"
+          :model="form"
+          :rules="rules"
+          :label-col="formItemLayout.labelCol"
+          :wrapper-col="formItemLayout.wrapperCol"
+        >
+          <div class="module-cont">
+            <p class="title">产品范围</p>
+            <a-form-model-item label=" " :colon="false" prop="stockPredictRange" class="form-item">
+              <a-radio-group name="radioGroup" v-model="form.stockPredictRange" placeholder="请选择">
+                <a-radio :value="1">全部产品</a-radio>
+                <a-radio :value="0">自选产品</a-radio>
+              </a-radio-group>
+            </a-form-model-item>
+            <productRange :itemSn="$route.params.sn" />
+          </div>
+          <div class="module-cont">
+            <p class="title">销售保障法<a-button type="link" size="small" class="link-btn" @click="handleExplain('xsbz')">算法说明</a-button></p>
+            <a-form-model-item label="保障倍数" prop="saleEnsureNum" class="form-item">
+              <a-input-number
+                id="intelligentReplenishmentEdit-saleEnsureNum"
+                v-model="form.saleEnsureNum"
+                :precision="2"
+                :min="1"
+                :max="3"
+                placeholder="请输入1~3之间的数字,最多两位小数"
+                style="width: 100%;" />
+            </a-form-model-item>
+          </div>
+          <div class="module-cont">
+            <p class="title">趋势平均法<a-button type="link" size="small" class="link-btn" @click="handleExplain('qspj')">算法说明</a-button></p>
+            <a-form-model-item label="服务水平" prop="loginFlag" class="form-item">
+              <a-input id="intelligentReplenishmentEdit-outQty" v-model="form.productOrigCode" placeholder="请选择" read-only @click="chooseFun" />
+            </a-form-model-item>
+          </div>
+        </a-form-model>
+        <div class="btn-cont">
+          <a-button type="primary" class="button-error" id="intelligentReplenishmentLevel-submit" @click="handleSubmit">下一步</a-button>
+        </div>
+      </div>
+      <!-- 系统计算 -->
+      <div v-if="current==1">
+        <div class="item-cont">
+          <img src="@/assets/explain/def_calculation.png" width="200" class="item-pic" />
+          <p class="item-txt">按照上一步的参数设置,系统正在<br/>计算中...点击左上角的返回列表可查看该条预测记录</p>
+        </div>
+      </div>
+    </a-card>
+    <!-- 服务水平 -->
+    <replenishment-service-level-modal :openModal="openModal" @close="openModal=false" @ok="handleOk" />
+  </div>
+</template>
+
+<script>
+import ReplenishmentServiceLevelModal from './serviceLevelModal.vue'
+import productRange from './productRange.vue'
+export default {
+  components: { ReplenishmentServiceLevelModal, productRange },
+  data () {
+    return {
+      formItemLayout: {
+        labelCol: { span: 2 },
+        wrapperCol: { span: 16 }
+      },
+      form: {
+        stockPredictRange: 1,
+        saleEnsureNum: ''
+      },
+      rules: {
+        saleEnsureNum: [ { required: true, message: '请输入保障倍数', trigger: 'blur' } ]
+      },
+      openModal: false,
+      current: 0
+    }
+  },
+  mounted () {
+    console.log(this.$route.params.sn)
+  },
+  methods: {
+    // 返回
+    handleBack () {
+      this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/list` })
+    },
+    // 下一步
+    handleSubmit () {},
+    //  选择
+    chooseFun () {
+      this.openModal = true
+    },
+    // 算法说明
+    handleExplain (type) {
+      if (type == 'xsbz') {
+        this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/explainXsbz` })
+      } else if (type == 'qspj') {
+        this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/explainQspj` })
+      }
+    },
+    // 服务水平选择
+    handleOk (val) {
+      console.log(val)
+      this.openModal = false
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .intelligentReplenishmentEdit-wrap{
+    .intelligentReplenishmentEdit-back{
+      margin-bottom: 10px;
+    }
+    .intelligentReplenishmentEdit-cont{
+      .steps-cont{
+        width: 50%;
+        margin: 30px auto 10px;
+      }
+      .module-cont{
+        border: 1px dashed #e8e8e8;
+        border-radius: 12px;
+        position: relative;
+        margin: 30px 0;
+        padding: 20px 15px 15px;
+        .title{
+          position: absolute;
+          left: 50px;
+          top: -12px;
+          padding: 0 10px;
+          font-size: 15px;
+          background-color: #fff;
+          .link-btn{
+            font-size: 12px;
+          }
+        }
+        .form-item{
+          margin-top: 25px;
+        }
+      }
+      .item-cont{
+        text-align: center;
+        padding: 130px 0 100px;
+        .item-txt{
+          margin: 20px 0 50px;
+          font-size: 12px;
+          line-height: 24px;
+        }
+      }
+      .btn-cont{
+        margin: 30px 0 20px;
+        text-align: center;
+      }
+    }
+  }
+</style>

+ 218 - 0
src/views/inventoryManagement/intelligentReplenishment/explainQspj.vue

@@ -0,0 +1,218 @@
+<template>
+  <a-card size="small" :bordered="false" class="explainQspj-warp">
+    <div class="explainQspj-cont">
+      <p class="explain-tit">趋势平均法</p>
+      <p class="explain-txt margin-b-30">趋势平均法是从过去各期实际销售量中,观察其增减变动的基本趋势并使其平均化,从而排除了某一个别销售期可能存在偶然因素的影响的一种销售预测法。</p>
+      <div class="sub-tit">
+        <img src="@/assets/explain/icon_sales.png" width="16" class="tit-icon" />
+        <p class="txt">预计月销量</p>
+      </div>
+      <div class="item-cont">
+        <p class="item-exp">预计月销量= = A + n×T</p>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">其中 A 表示五期平均值,n 表示距离预测时间的期数,T 表示趋势平均值</p>
+        </div>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">如果是新产品,没有历史销量,则不会进行预测,下载结果的excel中显示为-</p>
+        </div>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">如果产品上线时间不长,历史销售量记录小于12个月,则取有记录的销量平均值作为预计月销量</p>
+        </div>
+      </div>
+      <div class="sub-tit">
+        <img src="@/assets/explain/icon_inventory.png" width="16" class="tit-icon" />
+        <p class="txt">安全库存</p>
+      </div>
+      <div class="item-cont">
+        <p class="item-exp">安全库存=需求的标准偏差 × 安全系数 × 交付前置期开方</p>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">标准偏差是一个统计值,用来衡量一组个体值的离散程度,由希腊字母西格玛(σ)表示。在具体计算时,先计算出每个个体值的方差,加总后再开方便得到标准偏差。</p>
+        </div>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">安全系数与服务水平相关,服务水平越高,对应的安全系数就越大</p>
+        </div>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">交付前置期是订货周期/30</p>
+        </div>
+      </div>
+      <div class="sub-tit">
+        <img src="@/assets/explain/icon_mete.png" width="16" class="tit-icon" />
+        <p class="txt">预计需求量</p>
+      </div>
+      <div class="item-cont">
+        <p class="item-exp">预计需求量=预计月销量 × 交付前置期 + 安全库存</p>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">交付前置期是订货周期/30</p>
+        </div>
+      </div>
+      <div class="sub-tit">
+        <img src="@/assets/explain/icon_example.png" width="16" class="tit-icon" />
+        <p class="txt">示例</p>
+      </div>
+      <div class="item-cont">
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">某产品的订货周期为45天,最近12个月的实际销量如下表</p>
+        </div>
+        <div class="item-table">
+          <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false"></a-table>
+        </div>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">计算预计月销量 = 54.4 + 3 × (-0.2) = 53.8 ≈ 54(四舍五入)</p>
+        </div>
+        <div class="item-table">
+          <a-table :columns="columnsXl" :data-source="dataSourceXl" bordered :pagination="false"></a-table>
+        </div>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">计算安全库存 = 71的开方 × 90%的服务水平对应的安全系数 × 45/30的开方 = 8.43 × 1.28 × 1.22 = 13.16 ≈ 13(四舍五入)</p>
+        </div>
+        <div class="item-table">
+          <a-table :columns="columnsKc" :data-source="dataSourceKc" bordered :pagination="false"></a-table>
+        </div>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">计算预计需求量 = 54 × (45/30) + 13 = 94</p>
+        </div>
+      </div>
+    </div>
+  </a-card>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      columns: [
+        { title: '1月', dataIndex: 'january', align: 'center' },
+        { title: '2月', dataIndex: 'february', align: 'center' },
+        { title: '3月', dataIndex: 'march', align: 'center' },
+        { title: '4月', dataIndex: 'april', align: 'center' },
+        { title: '5月', dataIndex: 'may', align: 'center' },
+        { title: '6月', dataIndex: 'june', align: 'center' },
+        { title: '7月', dataIndex: 'july', align: 'center' },
+        { title: '8月', dataIndex: 'august', align: 'center' },
+        { title: '9月', dataIndex: 'september', align: 'center' },
+        { title: '10月', dataIndex: 'october', align: 'center' },
+        { title: '11月', dataIndex: 'november', align: 'center' },
+        { title: '12月', dataIndex: 'december', align: 'center' }
+      ],
+      dataSource: [
+        { january: 55, february: 53, march: 54, april: 56, may: 58, june: 57, july: 52, august: 52, september: 56, october: 52, november: 53, december: 59 }
+      ],
+      columnsXl: [
+        { title: '月份', dataIndex: 'title', align: 'center' },
+        { title: '1月', dataIndex: 'january', align: 'center' },
+        { title: '2月', dataIndex: 'february', align: 'center' },
+        { title: '3月', dataIndex: 'march', align: 'center' },
+        { title: '4月', dataIndex: 'april', align: 'center' },
+        { title: '5月', dataIndex: 'may', align: 'center' },
+        { title: '6月', dataIndex: 'june', align: 'center' },
+        { title: '7月', dataIndex: 'july', align: 'center' },
+        { title: '8月', dataIndex: 'august', align: 'center' },
+        { title: '9月', dataIndex: 'september', align: 'center' },
+        { title: '10月', dataIndex: 'october', align: 'center' },
+        { title: '11月', dataIndex: 'november', align: 'center' },
+        { title: '12月', dataIndex: 'december', align: 'center' }
+      ],
+      dataSourceXl: [
+        { title: '实际销量', january: 55, february: 53, march: 54, april: 56, may: 58, june: 57, july: 52, august: 52, september: 56, october: 52, november: 53, december: 59 },
+        { title: '五期平均值', january: '-', february: '-', march: 55.2, april: 55.6, may: 55.4, june: 55.0, july: 55.0, august: 53.8, september: 53.0, october: 54.4, november: '-', december: '-' },
+        { title: '变动趋势值', january: '-', february: '-', march: '-', april: 0.4, may: -0.2, june: -0.4, july: 0, august: -1.2, september: -0.8, october: 1.4, november: '-', december: '-' },
+        { title: '三期趋势平均值', january: '-', february: '-', march: '-', april: '-', may: -0.067, june: -0.2, july: -0.533, august: -0.667, september: -0.2, october: '-', november: '-', december: '-' }
+      ],
+      columnsKc: [
+        { title: '月份', dataIndex: 'title', align: 'center' },
+        { title: '1月', dataIndex: 'january', align: 'center' },
+        { title: '2月', dataIndex: 'february', align: 'center' },
+        { title: '3月', dataIndex: 'march', align: 'center' },
+        { title: '4月', dataIndex: 'april', align: 'center' },
+        { title: '5月', dataIndex: 'may', align: 'center' },
+        { title: '6月', dataIndex: 'june', align: 'center' },
+        { title: '7月', dataIndex: 'july', align: 'center' },
+        { title: '8月', dataIndex: 'august', align: 'center' },
+        { title: '9月', dataIndex: 'september', align: 'center' },
+        { title: '10月', dataIndex: 'october', align: 'center' },
+        { title: '11月', dataIndex: 'november', align: 'center' },
+        { title: '12月', dataIndex: 'december', align: 'center' },
+        { title: '求和', dataIndex: 'sum', align: 'center' }
+      ],
+      dataSourceKc: [
+        { title: '实际销量', january: 55, february: 53, march: 54, april: 56, may: 58, june: 57, july: 52, august: 52, september: 56, october: 52, november: 53, december: 59, sum: 657 },
+        { title: '实际销量', january: 54, february: 54, march: 54, april: 54, may: 54, june: 54, july: 54, august: 54, september: 54, october: 54, november: 54, december: 54, sum: 648 },
+        { title: '实际销量', january: 1, february: -1, march: 0, april: 2, may: 4, june: 3, july: -2, august: -2, september: 2, october: -2, november: -1, december: 5, sum: 9 },
+        { title: '实际销量', january: 1, february: 1, march: 0, april: 4, may: 14, june: 9, july: 4, august: 4, september: 4, october: 4, november: 1, december: 25, sum: 71 }
+      ]
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .explainQspj-warp{
+    .explainQspj-cont{
+      width: 960px;
+      margin: 0 auto;
+      p{
+        margin: 0;
+      }
+      .explain-tit{
+        font-size: 18px;
+        font-weight: bold;
+        text-align: center;
+        margin: 20px 0 30px;
+      }
+      .explain-txt{
+        font-size: 13px;
+        color: rgba(0,0,0,0.85);
+      }
+      .margin-b-30{
+        margin-bottom: 30px;
+      }
+      .sub-tit{
+        margin-bottom: 10px;
+        .tit-icon{
+          vertical-align: text-bottom;
+          margin-right: 5px;
+        }
+        .txt{
+          font-size: 16px;
+          color: rgba(0, 21, 41, 1);
+          display: inline-block;
+          margin: 0;
+        }
+      }
+      .item-cont{
+        font-size: 13px;
+        padding-left: 23px;
+        line-height: 26px;
+        margin-bottom: 25px;
+        .item-exp{
+          color: rgba(231, 0, 18, 0.85);
+        }
+        .item-main{
+          position: relative;
+          .item-icon{
+            position: absolute;
+            left: 0;
+            top: 7px;
+          }
+          .item-txt{
+            padding-left: 20px;
+          }
+        }
+        .item-table{
+          margin: 15px 0;
+        }
+      }
+    }
+  }
+</style>

+ 142 - 0
src/views/inventoryManagement/intelligentReplenishment/explainXsbz.vue

@@ -0,0 +1,142 @@
+<template>
+  <a-card size="small" :bordered="false" class="explainXsbz-warp">
+    <div class="explainXsbz-cont">
+      <p class="explain-tit">销售保障法</p>
+      <p class="explain-txt margin-b-30">销售保障法以历史的实际销售量为数据基础,并结合专家经验,得到预计的需求量,以满足销售需求,具体计算公式如下。</p>
+      <div class="sub-tit">
+        <img src="@/assets/explain/icon_sales.png" width="16" class="tit-icon" />
+        <p class="txt">预计月销量</p>
+      </div>
+      <div class="item-cont">
+        <p class="item-exp">预计月销量= {上个月实际销量,最近两个月实际销量平均值,最近半年实际销量平均值,去年同期实际销量} 取大者</p>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">如果是新产品,没有历史销量,则不会进行预测,下载结果的excel中显示为-</p>
+        </div>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">如果产品上线时间不长,历史销售量记录小于12个月,则取有记录的销量平均值作为预计月销量</p>
+        </div>
+      </div>
+      <div class="sub-tit">
+        <img src="@/assets/explain/icon_mete.png" width="16" class="tit-icon" />
+        <p class="txt">预计需求量</p>
+      </div>
+      <div class="item-cont">
+        <p class="item-exp">预计需求量=预计月销量 × 保障倍数</p>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">保障倍数是专家根据经验判断,自行设置的一个数值,取值范围在1~3之间,最多两位小数</p>
+        </div>
+      </div>
+      <div class="sub-tit">
+        <img src="@/assets/explain/icon_example.png" width="16" class="tit-icon" />
+        <p class="txt">示例</p>
+      </div>
+      <div class="item-cont">
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">某产品的订货周期为45天,最近12个月的实际销量如下表</p>
+        </div>
+        <div class="item-table">
+          <a-table :columns="columns" :data-source="dataSource" bordered :pagination="false"></a-table>
+        </div>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">计算预计月销量 = MAX { 59,(53+59)/2,(57+52+52+56+52+53+59)/6,55 } =59</p>
+        </div>
+        <div class="item-main">
+          <img src="@/assets/explain/pressed_gray.png" width="12" class="item-icon" />
+          <p class="item-txt">计算预计需求量 = 59 × 保障倍数1.5 = 88.5 ≈ 89(假设保障倍数为1.5)</p>
+        </div>
+      </div>
+    </div>
+  </a-card>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      columns: [
+        { title: '1月', dataIndex: 'january', align: 'center' },
+        { title: '2月', dataIndex: 'february', align: 'center' },
+        { title: '3月', dataIndex: 'march', align: 'center' },
+        { title: '4月', dataIndex: 'april', align: 'center' },
+        { title: '5月', dataIndex: 'may', align: 'center' },
+        { title: '6月', dataIndex: 'june', align: 'center' },
+        { title: '7月', dataIndex: 'july', align: 'center' },
+        { title: '8月', dataIndex: 'august', align: 'center' },
+        { title: '9月', dataIndex: 'september', align: 'center' },
+        { title: '10月', dataIndex: 'october', align: 'center' },
+        { title: '11月', dataIndex: 'november', align: 'center' },
+        { title: '12月', dataIndex: 'december', align: 'center' }
+      ],
+      dataSource: [
+        { january: 55, february: 53, march: 54, april: 56, may: 58, june: 57, july: 52, august: 52, september: 56, october: 52, november: 53, december: 59 }
+      ]
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .explainXsbz-warp{
+    .explainXsbz-cont{
+      width: 960px;
+      margin: 0 auto;
+      p{
+        margin: 0;
+      }
+      .explain-tit{
+        font-size: 18px;
+        font-weight: bold;
+        text-align: center;
+        margin: 20px 0 30px;
+      }
+      .explain-txt{
+        font-size: 13px;
+        color: rgba(0,0,0,0.85);
+      }
+      .margin-b-30{
+        margin-bottom: 30px;
+      }
+      .sub-tit{
+        margin-bottom: 10px;
+        .tit-icon{
+          vertical-align: text-bottom;
+          margin-right: 5px;
+        }
+        .txt{
+          font-size: 16px;
+          color: rgba(0, 21, 41, 1);
+          display: inline-block;
+          margin: 0;
+        }
+      }
+      .item-cont{
+        font-size: 13px;
+        padding-left: 23px;
+        line-height: 26px;
+        margin-bottom: 25px;
+        .item-exp{
+          color: rgba(231, 0, 18, 0.85);
+        }
+        .item-main{
+          position: relative;
+          .item-icon{
+            position: absolute;
+            left: 0;
+            top: 7px;
+          }
+          .item-txt{
+            padding-left: 20px;
+          }
+        }
+        .item-table{
+          margin: 15px 0;
+        }
+      }
+    }
+  }
+</style>

+ 113 - 0
src/views/inventoryManagement/intelligentReplenishment/import.vue

@@ -0,0 +1,113 @@
+<template>
+  <div class="intelligentReplenishmentImport-wrap">
+    <a-page-header :ghost="false" :backIcon="false" class="intelligentReplenishmentImport-back">
+      <!-- 自定义的二级文字标题 -->
+      <template slot="subTitle">
+        <a id="intelligentReplenishmentImport-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+      </template>
+    </a-page-header>
+    <a-card size="small" :bordered="false" class="intelligentReplenishmentImport-cont">
+      <div>
+        <p class="total">共 <span>50</span> 条数据,红色字体表示数据不符合规范,请返回上一步修改文件后重新上传</p>
+        <s-table
+          class="sTable"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.id"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ x: 1440 }"
+          bordered>
+        </s-table>
+        <div class="btn-cont">
+          <a-button type="primary" class="button-error" id="intelligentReplenishmentLevel-submit" @click="handleSubmit">确认导入</a-button>
+          <a-button type="primary" class="button-error" id="intelligentReplenishmentLevel-back" @click="handleBackSet">上一步</a-button>
+          <a-button id="intelligentReplenishmentLevel-back" @click="isShow = false" class="button-cancel">取消</a-button>
+        </div>
+      </div>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { STable } from '@/components'
+export default {
+  components: { STable },
+  data () {
+    return {
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 80, align: 'center', fixed: 'left' },
+        { title: '产品编码', dataIndex: 'purchaseNo', width: 220, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '产品名称', dataIndex: 'creatDate', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '产品状态', dataIndex: 'purchaseNos', width: 100, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '订货周期(天)', dataIndex: 'purchaseNoa', width: 120, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '是否淘汰', dataIndex: 'purchaseNod', width: 100, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '淘汰描述', dataIndex: 'purchaseNof', width: 200, align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '备注', dataIndex: 'purchaseNog', width: 200, align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '错误原因', dataIndex: 'purchaseNoh', width: 200, align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        // return custTypeList(Object.assign(parameter, this.queryParam)).then(res => {
+        //   const data = res.data
+        //   const no = (data.pageNo - 1) * data.pageSize
+        //   for (var i = 0; i < data.list.length; i++) {
+        //     data.list[i].no = no + i + 1
+        //   }
+        //   return data
+        // })
+        return new Promise(function (resolve, reject) {
+          const data = {
+            pageNo: 1,
+            pageSize: 10,
+            list: [
+              { id: '1', state: 1, purchaseNo: 'jgqp11111111111', creatDate: '产品1', custName: 'jgqp111123545', totalP: '箭冠品牌', totalNums: '产品分类1', totalPrice: '5', payType: '122' },
+              { id: '2', state: 2, purchaseNo: 'jgqp11111111111', creatDate: '产品1', custName: 'jgqp111123545', totalP: '箭冠品牌', totalNums: '产品分类1', totalPrice: '5', payType: '122' },
+              { id: '3', state: 3, purchaseNo: 'jgqp11111111111', creatDate: '产品1', custName: 'jgqp111123545', totalP: '箭冠品牌', totalNums: '产品分类1', totalPrice: '5', payType: '122' },
+              { id: '4', state: 4, purchaseNo: 'jgqp11111111111', creatDate: '产品1', custName: 'jgqp111123545', totalP: '箭冠品牌', totalNums: '产品分类1', totalPrice: '5', payType: '122' },
+              { id: '5', state: 5, purchaseNo: 'jgqp11111111111', creatDate: '产品1', custName: 'jgqp111123545', totalP: '箭冠品牌', totalNums: '产品分类1', totalPrice: '5', payType: '122' }
+            ],
+            count: 10
+          }
+          resolve(data)
+        })
+      }
+    }
+  },
+  methods: {
+    // 返回
+    handleBack () {
+      this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/list` })
+    },
+    // 返回基础设置页
+    handleBackSet () {
+      this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/set/${this.$route.params.sn}` })
+    },
+    // 确认导入
+    handleSubmit () {}
+  }
+}
+</script>
+<style lang="less">
+  .intelligentReplenishmentImport-wrap{
+    .intelligentReplenishmentImport-back{
+      margin-bottom: 10px;
+    }
+    .intelligentReplenishmentImport-cont{
+      .total{
+        margin: 20px 0 30px;
+        span{
+          font-weight: bold;
+        }
+      }
+      .btn-cont{
+        margin: 30px 0 20px;
+        text-align: center;
+        .button-cancel{
+          font-size: 12px;
+          margin-left: 15px;
+        }
+      }
+    }
+  }
+</style>

+ 155 - 0
src/views/inventoryManagement/intelligentReplenishment/list.vue

@@ -0,0 +1,155 @@
+<template>
+  <a-card size="small" :bordered="false" class="intelligentReplenishmentList-wrap">
+    <!-- 操作按钮 -->
+    <div class="table-operator">
+      <a-button id="intelligentReplenishmentList-add" type="primary" class="button-error" @click="handleEdit()">新增</a-button>
+      <a-button id="intelligentReplenishmentList-set" type="primary" class="button-warning" @click="handleSet">基础信息设置</a-button>
+    </div>
+    <a-alert type="info" showIcon style="margin-bottom:15px">
+      <div slot="message">为保证系统性能,仅保留最近10次的预测结果</div>
+    </a-alert>
+    <!-- 列表 -->
+    <s-table
+      class="sTable"
+      ref="table"
+      size="default"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      :showPagination="false"
+      bordered>
+      <!-- 操作 -->
+      <template slot="action" slot-scope="text, record">
+        <a-button
+          size="small"
+          type="link"
+          class="button-info"
+          @click="handleEdit(record)"
+          id="intelligentReplenishmentList-edit-btn">编辑</a-button>
+        <a-button
+          size="small"
+          type="link"
+          class="button-error"
+          @click="handleDel(record)"
+          id="intelligentReplenishmentList-del-btn">删除</a-button>
+        <a-button
+          size="small"
+          type="link"
+          class="button-success"
+          @click="handleDetail(record)"
+          id="customerManagementList-detail-btn">详情</a-button>
+        <a-button
+          size="small"
+          type="link"
+          class="button-warning"
+          :loading="downloadLoading"
+          @click="handleDownload(record)"
+          id="chainTransferInList-download-btn">结果下载</a-button>
+      </template>
+    </s-table>
+    <!-- 详情 -->
+    <intelligent-replenishment-detail-modal :openModal="openDetailModal" :itemId="itemId" @close="closeModal" />
+  </a-card>
+</template>
+
+<script>
+import moment from 'moment'
+import { STable, VSelect } from '@/components'
+import intelligentReplenishmentDetailModal from './detailModal.vue'
+import { predictList, predictSave } from '@/api/predict'
+export default {
+  components: { STable, VSelect, intelligentReplenishmentDetailModal },
+  data () {
+    return {
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 80, align: 'center' },
+        { title: '创建时间', dataIndex: 'createDate', width: 160, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '创建人', dataIndex: 'creatorName', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '状态', dataIndex: 'stateDictValue', width: 200, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: 200, align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return predictList({}).then(res => {
+          const data = res.data
+          for (var i = 0; i < data.length; i++) {
+            data[i].no = i + 1
+          }
+          return data
+        })
+      },
+      itemId: '', //  当前id
+      downloadLoading: false,
+      openDetailModal: false
+    }
+  },
+  methods: {
+    //  新增/编辑
+    handleEdit (row) {
+      if (row) { //  编辑
+        this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/edit/${row.stockPredictSn}` })
+      } else { //  新增
+        predictSave({}).then(res => {
+          if (res.status == 200) {
+            this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/add/${row.stockPredictSn}` })
+          }
+        })
+      }
+    },
+    //  详情
+    handleDetail (row) {
+      this.itemId = row ? row.id : null
+      this.openDetailModal = true
+    },
+    // 设置
+    handleSet (row) {
+      // this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/set/${row.sn}` })
+      this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/set/111` })
+    },
+    // 删除
+    handleDel (row) {
+      const _this = this
+      this.$confirm({
+        title: '提示',
+        content: '删除后不可恢复,确定要进行删除吗?',
+        centered: true,
+        onOk () {
+          // custTypeDel({ id: row.id }).then(res => {
+          //   if (res.status == 200) {
+          //     _this.$message.success(res.message)
+          //     _this.$refs.table.refresh()
+          //   }
+          // })
+        }
+      })
+    },
+    //  关闭弹框
+    closeModal () {
+      this.itemId = ''
+      this.openDetailModal = false
+      this.$refs.table.refresh(true)
+    },
+    //  结果下载
+    handleDownload () {
+      const params = this.queryParam
+      this.downloadLoading = true
+      // stockExport(params).then(res => {
+      //   this.downloadLoading = false
+      //   this.download(res)
+      // })
+    },
+    download (data) {
+      if (!data) { return }
+      const url = window.URL.createObjectURL(new Blob([data]))
+      const link = document.createElement('a')
+      link.style.display = 'none'
+      link.href = url
+      const a = moment().format('YYYYMMDDHHmmss')
+      const fname = '智能补货' + a
+      link.setAttribute('download', fname + '.xlsx')
+      document.body.appendChild(link)
+      link.click()
+    }
+  }
+}
+</script>

+ 133 - 0
src/views/inventoryManagement/intelligentReplenishment/productRange.vue

@@ -0,0 +1,133 @@
+<template>
+  <div class="productRange-wrap">
+    <!-- 操作按钮 -->
+    <div class="table-operator">
+      <a-button id="productRange-brand" type="primary" class="button-error" @click="choosePModal('BRAND')">选择产品品牌</a-button>
+      <a-button id="productRange-type" type="primary" class="button-info" @click="choosePModal('CATEGORY')">选择产品分类</a-button>
+      <a-button id="productRange-product" type="primary" class="button-success" @click="choosePModal('PRODUCT')">选择供应商</a-button>
+    </div>
+    <!-- 选择产品品牌 -->
+    <chooseBrandModal :openModal="openBrandModal" :chooseData="chooseBrand" @close="openBrandModal=false" @ok="handleBrandOk" />
+    <!-- 选择产品分类 -->
+    <chooseTypeModal :openModal="openTypeModal" :chooseData="chooseType" @close="openTypeModal=false" @ok="handleTypeOk" />
+    <!-- 列表 -->
+    <s-table
+      class="sTable"
+      ref="table"
+      size="small"
+      :rowKey="(record) => record.id"
+      :columns="columns"
+      :data="loadData"
+      :showPagination="false"
+      bordered>
+    </s-table>
+  </div>
+</template>
+
+<script>
+import { STable } from '@/components'
+import ChooseBrandModal from '@/views/common/chooseBrandModal.vue'
+import ChooseTypeModal from '@/views/common/chooseTypeModal.vue'
+import { predictRangeList } from '@/api/predict'
+export default {
+  components: { STable, ChooseBrandModal, ChooseTypeModal },
+  props: {
+    itemSn: {
+      type: [String, Number],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      openBrandModal: false, //  选择产品品牌
+      openTypeModal: false, //  选择产品分类
+      chooseBrand: [], //  所选品牌
+      chooseType: [], //  所选分类
+      columns: [
+        { title: '序号', dataIndex: 'no', width: 80, align: 'center' },
+        { title: '创建时间', dataIndex: 'createDate', width: 160, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '创建人', dataIndex: 'creatorName', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '状态', dataIndex: 'stateDictValue', width: 200, align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: 200, align: 'center' }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return predictRangeList({ 'sn': this.itemSn }).then(res => {
+          const data = res.data
+          for (var i = 0; i < data.length; i++) {
+            data[i].no = i + 1
+          }
+          return data
+        })
+      }
+    }
+  },
+  methods: {
+    // 选择
+    choosePModal (type) {
+      const brandList = []
+      const typeList = []
+      predictRangeList({ 'sn': this.itemSn }).then(res => {
+        if (res.status == 200) {
+          const data = res.data
+          data.map(item => {
+            if (item.goodsType == 'BRAND') {
+              brandList.push(item)
+            } else if (item.goodsType == 'CATEGORY') {
+              typeList.push(item)
+            }
+          })
+          if (type == 'BRAND') { //  选择品牌
+            this.chooseBrand = brandList
+            this.openBrandModal = true
+          } else if (type == 'CATEGORY') { //  选择分类
+            this.chooseType = typeList
+            this.openTypeModal = true
+          }
+        }
+      })
+      if (type == 'BRAND') { //  选择品牌
+        // this.chooseBrand = brandList
+        this.openBrandModal = true
+      } else if (type == 'CATEGORY') { //  选择分类
+        // this.chooseType = typeList
+        this.openTypeModal = true
+      }
+    },
+    // 品牌
+    handleBrandOk (obj) {
+      this.chooseBrand = obj
+      this.changeData('BRAND')
+    },
+    // 分类
+    handleTypeOk (obj) {
+      this.chooseType = obj
+      this.changeData('CATEGORY')
+    },
+    changeData (type) {
+      const _this = this
+      if (type == 'BRAND') { //  选择品牌
+        if (_this.chooseBrand.length > 0) {
+          const snList = []
+          _this.chooseBrand.map(item => {
+            snList.push(item.brandSn)
+          })
+          this.setData(snList, type)
+        }
+      } else if (type == 'CATEGORY') { //  选择分类
+        if (_this.chooseType.length > 0) {
+          const snList = []
+          _this.chooseType.map(item => {
+            snList.push(item.productTypeSn)
+          })
+          this.setData(snList, type)
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .productRange-wrap{}
+</style>

+ 128 - 0
src/views/inventoryManagement/intelligentReplenishment/serviceLevelModal.vue

@@ -0,0 +1,128 @@
+<template>
+  <a-modal
+    centered
+    class="intelligentReplenishmentLevel-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="选择服务水平"
+    v-model="isShow"
+    @cancle="isShow=false"
+    :width="800">
+    <div>
+      <s-table
+        class="sTable"
+        ref="table"
+        size="small"
+        :rowKey="(record) => record.trendSn"
+        :row-selection="{ type: 'radio', columnTitle: '选择', selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
+        :columns="columns"
+        :data="loadData"
+        :scroll="{ y: 400 }"
+        bordered>
+      </s-table>
+      <div class="btn-cont">
+        <a-button type="primary" id="intelligentReplenishmentLevel-save" @click="handleSave">保存</a-button>
+        <a-button id="intelligentReplenishmentLevel-back" @click="isShow = false" style="margin-left: 15px;">关闭</a-button>
+      </div>
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import { STable } from '@/components'
+import { predictTrendList } from '@/api/predict'
+export default {
+  name: 'IntelligentReplenishmentLevelModal',
+  components: { STable },
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    itemId: {
+      type: [Number, String],
+      default: ''
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      detailsData: null, //  详情数据
+      columns: [
+        { title: '服务水平(%)', dataIndex: 'purchaseNo', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '安全系数', dataIndex: 'creatDate', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        return predictTrendList({}).then(res => {
+          const data = res.data
+          return data
+        })
+      },
+      selectedRowKeys: []
+    }
+  },
+  methods: {
+    onSelectChange (selectedRowKeys, selectedRows) {
+      console.log('selectedRowKeys changed: ', selectedRowKeys, selectedRows)
+      this.selectedRowKeys = selectedRowKeys
+    },
+    //  保存
+    handleSave () {
+      if (this.selectedRowKeys.length > 0) {
+        this.$emit('ok', this.selectedRowKeys)
+      } else {
+        this.$message.warning('请选择服务水平后再进行保存!')
+      }
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      }
+    },
+    itemId (newValue, oldValue) {
+      if (this.isShow && newValue) {
+
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .intelligentReplenishmentLevel-modal{
+    .module-cont{
+      border: 1px dashed #e8e8e8;
+      border-radius: 12px;
+      position: relative;
+      margin: 30px 0;
+      padding: 20px 15px 15px;
+      .title{
+        position: absolute;
+        left: 50px;
+        top: -12px;
+        padding: 0 10px;
+        background-color: #fff;
+      }
+      .explain{
+        margin-bottom: 5px;
+        font-weight: bold;
+      }
+    }
+    .spin-cont{
+      text-align: center;
+    }
+    .btn-cont {
+      text-align: center;
+      font-weight: bold;
+      margin: 35px 0 10px;
+    }
+  }
+</style>

+ 152 - 0
src/views/inventoryManagement/intelligentReplenishment/set.vue

@@ -0,0 +1,152 @@
+<template>
+  <div class="intelligentReplenishmentSet-wrap">
+    <a-page-header :ghost="false" :backIcon="false" class="intelligentReplenishmentSet-back">
+      <!-- 自定义的二级文字标题 -->
+      <template slot="subTitle">
+        <a id="intelligentReplenishmentSet-back-btn" href="javascript:;" @click="handleBack"><a-icon type="left" /> 返回列表</a>
+      </template>
+    </a-page-header>
+    <a-card size="small" :bordered="false" class="intelligentReplenishmentSet-cont">
+      <div class="importGuide-con">
+        <div class="explain-con">
+          <div class="explain-item">
+            <div class="explain-tit">
+              <span>1</span>准备导入
+            </div>
+            <p>所有允许导入的数据字段请参考模板,数据字段不符合规则,整条不予以导入。</p>
+            <ul>
+              <li>1) 下载导入模板得到的excel中,是目前系统中全部的产品信息,请修改变化的字段(该行的其他字段保持不变),并删除没有变化的行</li>
+              <li>2) “产品编码”字段为必填项</li>
+              <li>3) “订货周期”字段只能输入正整数,如果没有订货周期,保持为空即可</li>
+              <li>4) “是否淘汰”字段,如果确定淘汰,则输入“是”,如果不淘汰,则不需要输入,保持为空即可</li>
+              <li>5) “淘汰描述”字段,只有当是否淘汰为“是”时,才能录入淘汰描述,否则,淘汰描述只能保持为空</li>
+            </ul>
+            <a :href="filePath" style="padding: 5px 0 0 23px;display: block;">
+              <a-icon type="download" style="padding-right: 5px;" />下载导入模板
+            </a>
+          </div>
+          <div class="explain-item">
+            <div class="explain-tit">
+              <span>2</span>上传数据文件
+            </div>
+            <p>目前支持的文件类型*.xls,*.xlsx.</p>
+            <p>
+              <Upload
+                id="importGuide-attachList"
+                ref="importUpload"
+                :maxNums="1"
+                fileType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"
+                uploadType="import"
+                :action="attachAction"
+                :uploadParams="uploadParams"
+                upText="添加文件"
+                @change="changeImport"></Upload>
+            </p>
+          </div>
+        </div>
+        <!-- 按钮 -->
+        <div class="btn-con">
+          <a-button
+            type="primary"
+            id="importGuide-nextStep"
+            size="large"
+            class="button-primary"
+            @click="handlerNextStep"
+            style="padding: 0 60px;">下一步</a-button>
+          <a-button
+            id="importGuide-cancel"
+            size="large"
+            class="button-cancel"
+            @click="handleBack"
+            style="padding: 0 60px;margin-left: 15px;">取消</a-button>
+        </div>
+      </div>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { Upload } from '@/components'
+export default {
+  components: { Upload },
+  data () {
+    return {
+      // filePath: 'http://jg-ocs.oss-cn-beijing.aliyuncs.com/templ/promo/normal_product_templ.xlsx',
+      filePath: 'javascript:;',
+      attachAction: process.env.VUE_APP_API_BASE_URL + '/upload',
+      paramsData: null,
+      uploadParams: {
+        savePathType: 'local'
+      }
+    }
+  },
+  methods: {
+    // 返回
+    handleBack () {
+      this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/list` })
+    },
+    // 下一步
+    handlerNextStep () {
+      // if (this.paramsData) {
+      this.$router.push({ path: `/inventoryManagement/intelligentReplenishment/import/${this.$route.params.sn}` })
+      // } else {
+      //   this.$message.warning('添加文件后再进行下一步操作!')
+      // }
+    },
+    // 上传文件  change
+    changeImport (file) {
+      console.log(file, '----上传')
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .intelligentReplenishmentSet-wrap{
+    .intelligentReplenishmentSet-back{
+      margin-bottom: 10px;
+    }
+    .importGuide-con{
+      width: 900px;
+      margin: 30px auto 50px;
+      line-height: 30px;
+      .explain-con{
+        .explain-item{
+          margin-bottom: 40px;
+          .explain-tit{
+            font-weight: bold;
+            span{
+              display: inline-block;
+              width: 18px;
+              height: 18px;
+              line-height: 16px;
+              text-align: center;
+              margin-right: 5px;
+              border-radius: 50%;
+              border: 1px solid rgba(0, 0, 0, 0.3);
+            }
+          }
+          p{
+            margin: 8px 0;
+            padding-left: 23px;
+          }
+          ul{
+            list-style: none;
+            padding: 0;
+            padding-left: 23px;
+            margin: 0;
+            li{
+              line-height: 26px;
+            }
+          }
+        }
+      }
+      .btn-con{
+        margin: 80px 0 20px;
+        .button-cancel{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>