瀏覽代碼

Merge branch 'develop_szhj05' of jianguan-web/jq-repairFusion-html into pre-release

李磊 2 年之前
父節點
當前提交
1cf17799ed

+ 139 - 0
src/api/report.js

@@ -0,0 +1,139 @@
+import { axios } from '@/utils/request'
+// 梯形图
+export const queryUserCount = params => {
+  return axios({
+    url: `/report/user/queryUserCount`,
+    data: params,
+    method: 'post'
+  })
+}
+// 注册用户
+export const queryStatistics = params => {
+  return axios({
+    url: `/report/user/queryStatistics`,
+    data: params,
+    method: 'post'
+  })
+}
+export const registerUserQueryPage = params => {
+  const url = `/report/user/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 使用用户
+export const useUserStatistics = params => {
+  return axios({
+    url: `/report/shelf/useUser/statistics`,
+    data: params,
+    method: 'post'
+  })
+}
+export const useUserQueryPage = params => {
+  const url = `/report/shelf/queryShelfUseUserPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 导出
+export const exportShelfUseUser = params => {
+  return axios({
+    url: `/report/shelf/exportShelfUseUser`,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+// 参数设置查询
+export const queryStoreLevelParamMap = params => {
+  return axios({
+    url: `/bizparam/queryStoreLevelParamMap`,
+    data: params,
+    method: 'post'
+  })
+}
+export const saveStoreLevelParam = params => {
+  return axios({
+    url: `/bizparam/saveStoreLevelParam`,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 获取货架等级数据
+export const queryShelfLevelReport = params => {
+  return axios({
+    url: `/report/shelf/queryShelfLevelReport`,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 获取活跃用户列表数据
+export const queryShelfActiveUserPage = params => {
+  const url = `/report/shelf/queryShelfActiveUserPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+
+// 活跃用户-导出
+export const exportShelfActiveUser = params => {
+  return axios({
+    url: `/report/shelf/exportShelfActiveUser`,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}
+
+// 活跃用户-统计
+export const statistics = params => {
+  return axios({
+    url: `/report/shelf/activeUser/statistics`,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 获取订单数据汇总列表
+export const queryShelfOrderReportPage = params => {
+  const url = `/report/shelf/queryShelfOrderReportPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios({
+    url: url,
+    data: params,
+    method: 'POST'
+  })
+}
+// 订单汇总-统计
+export const queryShelfOrderTotalReport = params => {
+  return axios({
+    url: `/report/shelf/queryShelfOrderTotalReport`,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 订单汇总-导出
+export const exportShelfOrderReport = params => {
+  return axios({
+    url: `/report/shelf/exportShelfOrderReport`,
+    data: params,
+    method: 'post',
+    responseType: 'blob'
+  })
+}

二進制
src/assets/s1.png


二進制
src/assets/s2.png


二進制
src/assets/s3.png


+ 74 - 1
src/config/router.config.js

@@ -189,8 +189,81 @@ export const asyncRouterMap = [
           },
         ]
       },
+      // 数据统计
+      {
+        path: '/dataStatistics',
+        redirect: '/dataStatistics/userAnalysis',
+        component: PageView,
+        meta: {
+          title: '数据统计',
+          icon: 'hdd',
+          permission: 'M_dataStatistics'
+        },
+        children: [
+          {
+            path: '/dataStatistics/userAnalysis',
+            redirect: '/dataStatistics/userAnalysis/list',
+            name: 'userAnalysis',
+            component: BlankLayout,
+            meta: {
+              title: '用户分析',
+              icon: 'monitor',
+              permission: 'M_userAnalysisList'
+            },
+            hideChildrenInMenu: true,
+            children: [
+              {
+                path: 'list',
+                name: 'userAnalysisList',
+                component: () => import('@/views/dataStatistics/userAnalysis/list.vue'),
+                meta: {
+                  title: '用户分析',
+                  icon: 'monitor',
+                  hidden: true
+                }
+              },
+              {
+                path: 'registeredUser',
+                name: 'registeredUser',
+                component: () => import('@/views/dataStatistics/userAnalysis/registeredUser.vue'),
+                meta: {
+                  title: '注册用户',
+                  hidden: true,
+                }
+              },
+              {
+                path: 'usedUser',
+                name: 'usedUser',
+                component: () => import('@/views/dataStatistics/userAnalysis/usedUser.vue'),
+                meta: {
+                  title: '使用用户',
+                  hidden: true,
+                }
+              },
+              {
+                path: 'activeUser',
+                name: 'activeUser',
+                component: () => import('@/views/dataStatistics/userAnalysis/activeUser.vue'),
+                meta: {
+                  title: '活跃用户',
+                  hidden: true,
+                }
+              }
+            ]
+          },
+          {
+            path: '/dataStatistics/orderDataSummary',
+            name: 'orderDataSummary',
+            component: () => import('@/views/dataStatistics/orderDataSummary/list.vue'),
+            meta: {
+              title: '订单数据汇总',
+              icon: 'user',
+              permission: 'M_orderDataSummary'
+            }
+          },
+        ]
+      },
       // 系统设置
-      // auth
       {
         path: '/auth',
         redirect: '/auth/userList',

+ 2 - 2
src/utils/util.js

@@ -3,7 +3,7 @@ export function timeFix () {
   const hour = time.getHours()
   return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
 }
- 
+
 export function welcome () {
   const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
   const index = Math.floor(Math.random() * arr.length)
@@ -70,4 +70,4 @@ export function oneOf (value, validList) {
     }
   }
   return false
-}
+}

+ 101 - 0
src/views/common/areaList.js

@@ -0,0 +1,101 @@
+import { getArea } from '@/api/data'
+const areaList = {
+  template: `
+      <a-cascader
+        :value="defaultVal"
+        allowClear
+        :change-on-select="changeOnSelect"
+        @change="handleChange"
+        :options="list"
+        expand-trigger="hover"
+        :show-search="{ filterOption }"
+        :placeholder="placeholder"
+        :id="id"
+        :fieldNames="{ label: 'name', value: 'areaSn', children:'children'}"/>
+    `,
+  props: {
+    value: {
+      type: Array,
+      defatut: function(){
+        return []
+      }
+    },
+    id: {
+      type: String,
+      default: ''
+    },
+    placeholder:{
+      type: String,
+      default: '请选择'
+    },
+    changeOnSelect:{
+      type: Boolean,
+      default: false
+    },
+    level:{
+      type: [String,Number],
+      default: ''
+    }
+  },
+  data() {
+    return {
+      defaultVal: this.value,
+      list: []
+    };
+  },
+  mounted() {
+    this.getArea()
+  },
+  watch: {
+    value(newValue, oldValue) {
+      this.defaultVal = newValue
+    }
+  },
+  methods: {
+    filterOption(inputValue, path) {
+      return path.some(option => option.name.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
+    },
+    handleChange(value,opts) {
+      this.defaultVal = value;
+      this.$emit('input', value);
+      this.$emit('change', value,opts);
+    },
+    getArea () {
+      getArea({}).then(res => {
+        if (res.status == 200) {
+          this.list = this.getBylevel(res.data)
+        } else {
+          this.list = []
+        }
+      })
+    },
+    getBylevel(data){
+      const a = data.filter(item => item.type == 2) // 省
+      const b = data.filter(item => item.type == 3) // 市
+      const c = data.filter(item => item.type == 4) // 县
+      
+      // 显示一级分类
+      if(this.level == 1){
+        return a
+      }
+      // 显示二级分类
+      if(this.level == 2){
+        a.map(item => {
+           item.children = b.filter(k => k.parentId == item.id)
+        })
+        console.log(a)
+        return a
+      }
+      // 全部显示
+      b.map(item => {
+        item.children = c.filter(k => k.parentId == item.id)
+      })
+      a.map(item => {
+         item.children = b.filter(k => k.parentId == item.id)
+      })
+      return a
+    }
+  },
+};
+
+export default areaList

+ 9 - 0
src/views/common/rangeDate.vue

@@ -22,6 +22,10 @@ export default {
     size: {
       type: String,
       default: 'default'
+    },
+    showTime: {
+      type: Boolean,
+      default: true
     }
   },
   data () {
@@ -55,6 +59,11 @@ export default {
       this.date = date
       if (dateStrings[0] == '' && dateStrings[1] == '') {
         dateStrings = []
+      } else {
+        if (this.showTime) {
+          dateStrings[0] = dateStrings[0] + ' 00:00:00'
+          dateStrings[1] = dateStrings[1] + ' 23:59:59'
+        }
       }
       this.$emit('change', dateStrings)
     },

+ 352 - 0
src/views/dataStatistics/orderDataSummary/list.vue

@@ -0,0 +1,352 @@
+<template>
+  <div class="userd-baseInfo">
+    <a-card size="small" :bordered="false">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <div ref="tableSearch" class="table-page-search-wrapper">
+          <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+            <a-row :gutter="15">
+              <a-col :md="5" :sm="24">
+                <a-form-item label="货架创建时间">
+                  <rangeDate ref="rangeDate" :value="time" @change="dateChange" />
+                </a-form-item>
+              </a-col>
+              <a-col :md="5" :sm="24">
+                <a-form-item label="汽车修理厂">
+                  <storeList ref="storeList" @change="storeChange" id="userd-storeChange"></storeList>
+                </a-form-item>
+              </a-col>
+              <a-col :md="5" :sm="24">
+                <a-form-item label="配件经销商">
+                  <dealerList ref="dealerList" @change="dealerChange" id="userd-dealerChange"></dealerList>
+                </a-form-item>
+              </a-col>
+              <a-col :md="4" :sm="24">
+                <a-form-item label="所在地" >
+                  <areaList level="2" placeholder="请选择所在地" v-model="areaArr" @change="areaChange"></areaList>
+                </a-form-item>
+              </a-col>
+              <template v-if="advanced">
+                <a-col :md="4" :sm="24">
+                  <a-form-item label="货架状态">
+                    <v-select id="userd-state" code="SHELF_STATE" v-model="queryParam.shelfState" allowClear placeholder="请选择状态"></v-select>
+                  </a-form-item>
+                </a-col>
+                <a-col :md="5" :sm="24">
+                  <a-form-item label="下单时间">
+                    <rangeDate ref="orderDate" :value="orderTime" @change="orderDateChange" />
+                  </a-form-item>
+                </a-col>
+                <!-- <a-col :md="5" :sm="24">
+                  <a-form-item label="货架取货数量">
+                    <a-input-group compact>
+                      <a-input-number
+                        :precision="0"
+                        style=" width: 42%; text-align: center"
+                        v-model.trim="queryParam.qhslMin"
+                        allowClear
+                        placeholder="请输入最小值"/>
+                      <a-input
+                        style=" width: 16%; pointer-events: none; backgroundColor: #fff"
+                        placeholder="~"
+                        disabled
+                      />
+                      <a-input-number
+                        :precision="0"
+                        :min="queryParam.qhslMin"
+                        style=" width: 42%; text-align: center"
+                        v-model.trim="queryParam.qhslMax"
+                        allowClear
+                        placeholder="请输入最大值"/>
+                    </a-input-group>
+                  </a-form-item>
+                </a-col>
+                <a-col :md="5" :sm="24">
+                  <a-form-item label="销售数量">
+                    <a-input-group compact>
+                      <a-input-number
+                        :precision="0"
+                        style=" width: 42%; text-align: center"
+                        v-model.trim="queryParam.xsslMin"
+                        allowClear
+                        placeholder="请输入最小值"/>
+                      <a-input
+                        style=" width: 16%; pointer-events: none; backgroundColor: #fff"
+                        placeholder="~"
+                        disabled
+                      />
+                      <a-input-number
+                        :precision="0"
+                        :min="queryParam.xsslMin"
+                        style=" width: 42%; text-align: center"
+                        v-model.trim="queryParam.xsslMax"
+                        allowClear
+                        placeholder="请输入最大值"/>
+                    </a-input-group>
+                  </a-form-item>
+                </a-col> -->
+              </template>
+              <a-col :md="4" :sm="24" style="margin-bottom: 10px;">
+                <a-button type="primary" @click="$refs.table.refresh(true)" id="userd-refresh">查询</a-button>
+                <a-button type="" @click="reset" style="margin-left: 10px;" id="userd-reset">重置</a-button>
+                <a-button type="primary" @click="exportFile" class="button-warning" style="margin-left: 10px;" id="userd-reset">导出</a-button>
+                <a @click="advanced=!advanced" style="margin-left: 8px">
+                  {{ advanced ? '收起' : '展开' }}
+                  <a-icon :type="advanced ? 'up' : 'down'"/>
+                </a>
+              </a-col>
+            </a-row>
+          </a-form>
+        </div>
+        <div class="table-operator" v-if="statisticsObj">
+          <a-alert type="info">
+            <div slot="message" class="total-bar">
+              <div>
+                货架数量:<strong>{{ statisticsObj.shelfCount }}</strong>;
+                铺货数量合计:<strong>{{ statisticsObj.totalShelfMaxQty }}</strong>;
+                铺货金额合计:<strong>{{ statisticsObj.totalShelfMaxCost }}</strong>;
+                货架取货数量合计:<strong>{{ statisticsObj.totalOrderQty }}</strong>;
+                货架取货金额合计:<strong>{{ statisticsObj.totalOrderAmount }}</strong>;
+              </div>
+              <div>
+                急送数量合计:<strong>{{ statisticsObj.tempOrderQty }}</strong>;
+                急送金额合计:<strong>{{ statisticsObj.tempOrderAmount }}</strong>;
+                销售数量合计:<strong>{{ statisticsObj.saleOrderQty }}</strong>;
+                销售金额合计:<strong>{{ statisticsObj.saleOrderAmount }}</strong>;
+              </div>
+            </div>
+          </a-alert>
+        </div>
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          :style="{ height: tableHeight+84.5+'px', wordBreak: 'break-all' }"
+          size="small"
+          :rowKey="(record,index)=>{return index}"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight }"
+          :defaultLoadData="false"
+          bordered>
+          <div slot="area" slot-scope="text, record">
+            {{ record.dealerProvinceName }} {{ record.dealerCityName }}
+          </div>
+          <span slot="customTitle">
+            <a-popover>
+              <template slot="content">
+                货架铺货情况为实时数据<br>与查询条件中的下单时间无关
+              </template>
+              <a-icon type="question-circle" theme="twoTone" />
+            </a-popover>
+            货架铺货情况
+          </span>
+        </s-table>
+      </a-spin>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import rangeDate from '@/views/common/rangeDate.vue'
+import { queryShelfOrderReportPage, queryShelfOrderTotalReport, exportShelfOrderReport } from '@/api/report.js'
+import areaList from '@/views/common/areaList.js'
+import dealerList from '@/views/common/dealerList.vue'
+import storeList from '@/views/common/storeList.vue'
+import { toThousands } from '@/libs/tools.js'
+import { hdExportExcel } from '@/libs/exportExcel'
+export default {
+  name: 'UserList',
+  components: { STable, VSelect, rangeDate, dealerList, storeList, areaList },
+  data () {
+    return {
+      spinning: false,
+      advanced: false,
+      tableHeight: 0,
+      time: [],
+      orderTime: [],
+      // 查询参数
+      queryParam: {
+        beginDate: '', // 下单时间
+        endDate: '',
+        shelfCreateBeginDate: '', // 货架创建时间
+        shelfCreateEndDate: '',
+        storeSn: undefined,
+        dealerSn: undefined,
+        shelfState: undefined,
+        dealerProvinceSn: undefined,
+        dealerCitySn: undefined
+      },
+      showModal: false,
+      itemData: null, // 编辑行数据
+      openStatusModal: false, // 货架状态弹窗初始状态
+      statisticsObj: null,
+      areaArr: [],
+
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '6%', align: 'center' },
+        { title: '货架创建时间', dataIndex: 'shelfCreateDate', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '汽车修理厂', dataIndex: 'storeName', width: '12%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '配件经销商', dataIndex: 'dealerName', width: '12%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '所在地', scopedSlots: { customRender: 'area' }, width: '11%', align: 'center' },
+        { title: '货架状态', dataIndex: 'shelfStateDictValue', width: '6%', align: 'center', customRender: function (text) { return text || '--' } },
+        {
+          slots: { title: 'customTitle' },
+          children: [
+            { title: '铺货数量', dataIndex: 'totalShelfMaxQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+            { title: '铺货金额', dataIndex: 'totalShelfMaxCost', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+          ]
+        },
+        {
+          title: '货架订单',
+          children: [
+            { title: '取货数量', dataIndex: 'totalOrderQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+            { title: '取货金额', dataIndex: 'totalOrderAmount', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+          ]
+        },
+        {
+          title: '急送订单',
+          children: [
+            { title: '急送数量', dataIndex: 'tempOrderQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+            { title: '急送金额', dataIndex: 'tempOrderAmount', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+          ]
+        },
+        {
+          title: '销售单',
+          children: [
+            { title: '销售数量', dataIndex: 'saleOrderQty', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } },
+            { title: '销售金额', dataIndex: 'saleOrderAmount', width: '6%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') } }
+          ]
+        }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.spinning = true
+        return queryShelfOrderReportPage(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (let i = 0; i < data.list.length; i++) {
+              const _item = data.list[i]
+              _item.no = no + i + 1
+            }
+          }
+          this.getStatistics(this.queryParam)
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  methods: {
+    handleBack () {
+      this.$router.go(-1)
+    },
+    //  时间  change
+    dateChange (date) {
+      this.queryParam.shelfCreateBeginDate = date[0]
+      this.queryParam.shelfCreateEndDate = date[1]
+    },
+    //  时间  change
+    orderDateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    // 经销商 change
+    dealerChange (obj) {
+      this.queryParam.dealerSn = obj.key || undefined
+    },
+    // 汽车修理厂 change
+    storeChange (obj) {
+      this.queryParam.storeSn = obj.key || undefined
+    },
+    // 地区
+    areaChange (val, opts) {
+      this.queryParam.dealerProvinceSn = val && val[0] ? val[0] : ''
+      this.queryParam.dealerCitySn = val && val[1] ? val[1] : ''
+    },
+    // 重置
+    reset () {
+      this.queryParam = {
+        beginDate: '', // 下单时间
+        endDate: '',
+        shelfCreateBeginDate: '', // 货架创建时间
+        shelfCreateEndDate: '',
+        storeSn: undefined,
+        dealerSn: undefined,
+        shelfState: undefined,
+        dealerProvinceSn: undefined,
+        dealerCitySn: undefined
+      }
+      this.areaArr = []
+      this.$refs.rangeDate.resetDate()
+      if (this.advanced) {
+        this.$refs.orderDate.resetDate()
+      }
+      this.$refs.dealerList.resetForm()
+      this.$refs.storeList.resetForm()
+      this.$refs.table.refresh(true)
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    // 导出
+    exportFile () {
+      const _this = this
+      this.spinning = true
+      hdExportExcel(exportShelfOrderReport, this.queryParam, '订单数据汇总', function () {
+        _this.spinning = false
+      })
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 225
+    },
+    // 获取订单汇总统计数据
+    getStatistics (ajaxData) {
+      queryShelfOrderTotalReport(ajaxData).then(res => {
+        if (res.status == 200) {// eslint-disable-line
+          this.statisticsObj = res.data
+        } else {
+          this.$message.error(res.message)
+        }
+      })
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.reset()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.reset()
+    }
+  }
+}
+</script>
+<style lang="less">
+  .userd-baseInfo{
+    .userd-back{
+      margin-bottom: 6px;
+    }
+  }
+</style>

+ 358 - 0
src/views/dataStatistics/userAnalysis/activeUser.vue

@@ -0,0 +1,358 @@
+<template>
+  <div class="activeuser-baseInfo">
+    <a-page-header :ghost="false" title="活跃用户" :backIcon="false" class="activeuser-back">
+      <template slot="subTitle">
+        <a href="javascript:;" @click="handleBack" id="activeuser-handleBack">
+          <a-icon type="left"></a-icon> 返回上页
+        </a>
+      </template>
+    </a-page-header>
+    <a-card size="small" :bordered="false" style="margin-bottom: 6px;">
+      <div style="padding:0 10px;color: #00aaff;cursor: pointer;" slot="extra" @click="showSetModal=true"><a-icon type="setting" /> 参数设置</div>
+      <div class="gard-box">
+        <div v-for="(card,i) in getShelfLeveData" :key="i" @click="chooseCard(i)" :class="cardIndex == i? 'chooseCard':''">
+          <a-card size="small">
+            <h4>{{ card.levelName }}</h4>
+            <p v-if="card.levelName == 'LV1'">近{{ card.dayLimit }}天销售金额 ≤ {{ card.amountMax }}元</p>
+            <p v-if="card.levelName == 'LV2'">{{ card.amountMin }}元 < 近{{ card.dayLimit }}天销售金额 ≤ {{ card.amountMax }}元</p>
+            <p v-if="card.levelName == 'LV3'">{{ card.amountMin }}元 < 近{{ card.dayLimit }}天销售金额 ≤ {{ card.amountMax }}元</p>
+            <p v-if="card.levelName == 'LV4'">{{ card.amountMin }}元 < 近{{ card.dayLimit }}天销售金额 ≤ {{ card.amountMax }}元</p>
+            <p v-if="card.levelName == 'LV5'">{{ card.amountMin }}元 < 近{{ card.dayLimit }}天销售金额</p>
+            <div>
+              <div>
+                <span>门店数量</span>
+                <span>{{ card.shelfCount }}个</span>
+              </div>
+              <div>
+                <span>累计销售金额</span>
+                <span>{{ card.amountSum }}元</span>
+              </div>
+              <div>
+                <span>门店数量占比</span>
+                <span>{{ card.shelfRate? card.shelfRate : 0 }}</span>
+              </div>
+              <div>
+                <span>累计销售金额占比</span>
+                <span>{{ card.amountRate? card.amountRate : 0 }}</span>
+              </div>
+            </div>
+          </a-card>
+        </div>
+      </div>
+    </a-card>
+    <a-card size="small" :bordered="false">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <div ref="tableSearch" class="table-page-search-wrapper">
+          <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+            <a-row :gutter="15">
+              <a-col :md="5" :sm="24">
+                <a-form-item label="货架创建时间">
+                  <rangeDate ref="rangeDate" :value="time" @change="dateChange" />
+                </a-form-item>
+              </a-col>
+              <a-col :md="5" :sm="24">
+                <a-form-item label="汽车修理厂">
+                  <storeList ref="storeList" @change="storeChange" id="activeuser-storeChange"></storeList>
+                </a-form-item>
+              </a-col>
+              <a-col :md="5" :sm="24">
+                <a-form-item label="配件经销商">
+                  <dealerList ref="dealerList" @change="dealerChange" id="activeuser-dealerChange"></dealerList>
+                </a-form-item>
+              </a-col>
+              <a-col :md="4" :sm="24">
+                <a-form-item label="所在地">
+                  <areaList level="2" placeholder="请选择所在地" v-model="areaArr" @change="areaChange"></areaList>
+                </a-form-item>
+              </a-col>
+              <template v-if="advanced">
+                <a-col :md="4" :sm="24">
+                  <a-form-item label="货架状态">
+                    <v-select id="activeuser-state" code="SHELF_STATE" v-model="queryParam.shelfState" allowClear placeholder="请选择状态"></v-select>
+                  </a-form-item>
+                </a-col>
+              </template>
+              <a-col :md="4" :sm="24" style="margin-bottom: 10px;">
+                <a-button type="primary" @click="$refs.table.refresh(true)" id="activeuser-refresh">查询</a-button>
+                <a-button type="" @click="reset" style="margin-left: 10px;" id="activeuser-reset">重置</a-button>
+                <a-button type="primary" @click="exportFile" class="button-warning" style="margin-left: 10px;" id="activeuser-reset">导出</a-button>
+                <a @click="advanced=!advanced" style="margin-left: 8px">
+                  {{ advanced ? '收起' : '展开' }}
+                  <a-icon :type="advanced ? 'up' : 'down'"/>
+                </a>
+              </a-col>
+            </a-row>
+          </a-form>
+        </div>
+        <div class="table-operator" v-if="statisticsObj">
+          <a-alert type="info">
+            <div slot="message" class="total-bar">
+              <div>
+                门店数量:<strong>{{ statisticsObj.shelfCount || 0 }}</strong>;
+                近30天货架取货数量合计:<strong>{{ statisticsObj.totalOrderQty || 0 }}</strong>;
+                近30天货架取货金额合计:<strong>{{ statisticsObj.totalOrderAmount || 0 }}</strong>;
+                近30天销售数量合计:<strong>{{ statisticsObj.saleOrderQty || 0 }}</strong>;
+                近30天销售金额合计:<strong>{{ statisticsObj.saleOrderAmount || 0 }}</strong>;
+              </div>
+            </div>
+          </a-alert>
+        </div>
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          :style="{ height: tableHeight+84.5+'px', wordBreak: 'break-all' }"
+          size="small"
+          :rowKey="(record,index)=>{return index}"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight }"
+          :defaultLoadData="false"
+          bordered>
+          <div slot="area" slot-scope="text, record">
+            {{ record.dealerProvinceName }} {{ record.dealerCityName }}
+          </div>
+        </s-table>
+      </a-spin>
+    </a-card>
+    <!-- 参数设置 -->
+    <setModal :openModal="showSetModal" :nowData="itemData" @ok="getShelfLeve" @close="showSetModal=false"></setModal>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import rangeDate from '@/views/common/rangeDate.vue'
+import { queryShelfActiveUserPage, queryShelfLevelReport, exportShelfActiveUser, statistics } from '@/api/report.js'
+import areaList from '@/views/common/areaList.js'
+import dealerList from '@/views/common/dealerList.vue'
+import storeList from '@/views/common/storeList.vue'
+import { toThousands } from '@/libs/tools.js'
+import { hdExportExcel } from '@/libs/exportExcel'
+import setModal from './setModal.vue'
+export default {
+  name: 'UserList',
+  components: { STable, VSelect, rangeDate, dealerList, storeList, areaList, setModal },
+  data () {
+    return {
+      spinning: false,
+      advanced: false,
+      showSetModal: false,
+      tableHeight: 0,
+      activeKey: ['1'],
+      time: [],
+      orderTime: [],
+      // 查询参数
+      queryParam: {
+        endDate: '',
+        beginDate: '',
+        storeSn: undefined,
+        dealerSn: undefined,
+        shelfState: undefined,
+        dealerProvinceSn: undefined,
+        dealerCitySn: undefined
+      },
+      showModal: false,
+      itemData: null, // 编辑行数据
+      openStatusModal: false, // 货架状态弹窗初始状态
+      getShelfLeveData: [], // 货架等级数据
+      statisticsObj: null,
+      cardIndex: null,
+      areaArr: [],
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '5%', align: 'center' },
+        { title: '货架创建时间', dataIndex: 'shelfCreateDate', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '汽车修理厂', dataIndex: 'storeName', width: '15%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '配件经销商', dataIndex: 'dealerName', width: '15%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '所在地', scopedSlots: { customRender: 'area' }, width: '11%', align: 'center' },
+        { title: '货架状态', dataIndex: 'shelfStateDictValue', width: '11%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '近30天货架取货数量', dataIndex: 'totalOrderQty', width: '11%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') }, sorter: true },
+        { title: '近30天货架取货金额', dataIndex: 'totalOrderAmount', width: '11%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') }, sorter: true },
+        { title: '近30天销售数量', dataIndex: 'saleOrderQty', width: '11%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') }, sorter: true },
+        { title: '近30天销售金额', dataIndex: 'saleOrderAmount', width: '11%', align: 'center', customRender: function (text) { return ((text || text == 0) ? text : '--') }, sorter: true }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.spinning = true
+        return queryShelfActiveUserPage(Object.assign(parameter, this.queryParam)).then(res => {
+          let data
+          if (res.status == 200) {// eslint-disable-line
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (let i = 0; i < data.list.length; i++) {
+              const _item = data.list[i]
+              _item.no = no + i + 1
+            }
+          }
+          this.spinning = false
+          this.getShelfLeve()
+          this.getStatistics(this.queryParam)
+          return data
+        })
+      }
+    }
+  },
+  methods: {
+    handleBack () {
+      this.$router.go(-1)
+    },
+    //  时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+
+    // 经销商 change
+    dealerChange (obj) {
+      this.queryParam.dealerSn = obj.key || undefined
+    },
+    // 汽车修理厂 change
+    storeChange (obj) {
+      this.queryParam.storeSn = obj.key || undefined
+    },
+    // 地区
+    areaChange (val, opts) {
+      this.queryParam.dealerProvinceSn = val && val[0] ? val[0] : ''
+      this.queryParam.dealerCitySn = val && val[1] ? val[1] : ''
+    },
+    // 导出
+    exportFile () {
+      const _this = this
+      this.spinning = true
+      hdExportExcel(exportShelfActiveUser, this.queryParam, '用户分析(活跃用户)详情', function () {
+        _this.spinning = false
+      })
+    },
+    // 重置
+    reset () {
+      this.cardIndex = null
+      this.queryParam = {
+        endDate: '',
+        beginDate: '',
+        storeSn: undefined,
+        dealerSn: undefined,
+        shelfState: undefined,
+        dealerProvinceSn: undefined,
+        dealerCitySn: undefined
+      }
+      this.areaArr = []
+      this.$refs.rangeDate.resetDate()
+      this.$refs.dealerList.resetForm()
+      this.$refs.storeList.resetForm()
+      this.$refs.table.refresh(true)
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 255
+    },
+    // 获取货架等级
+    getShelfLeve () {
+      const _this = this
+      queryShelfLevelReport().then(res => {
+        if (res.status == 200) { // eslint-disable-line
+          _this.getShelfLeveData = res.data
+        } else {
+          _this.$message.error(res.message)
+        }
+      })
+    },
+    // 获取活跃用户统计数据
+    getStatistics (ajaxData) {
+      statistics(ajaxData).then(res => {
+        if (res.status == 200) { // eslint-disable-line
+          this.statisticsObj = res.data
+        } else {
+          this.$message.error(res.message)
+        }
+      })
+    },
+    // 选中盒子
+    chooseCard (num) {
+      if (this.cardIndex == num) { // eslint-disable-line
+        this.cardIndex = null
+        var { lvCode, dealerSnList, customerSnList, ...newObj } = this.queryParam
+        this.queryParam = newObj
+      } else {
+        this.cardIndex = num
+        const obj = {
+          lvCode: this.getShelfLeveData[num].levelName,
+          dealerSnList: this.getShelfLeveData[num].dealerSnList || [],
+          customerSnList: this.getShelfLeveData[num].customerSnList || []
+        }
+        Object.assign(this.queryParam, obj)
+      }
+      this.$refs.table.refresh(true)
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.reset()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.reset()
+    }
+  }
+}
+</script>
+<style lang="less">
+  .activeuser-baseInfo{
+    .activeuser-back{
+      margin-bottom: 6px;
+    }
+    .gard-box{
+      display: flex;
+      > div{
+        width: 20%;
+        padding:0 10px;
+        .ant-card-body{
+          > h4,p{
+            text-align: center;
+          }
+          > h4{
+            font-size: 18px;
+            margin: 0 0 5px;
+          }
+          > div{
+            > div{
+              display: flex;
+              align-items: center;
+              justify-content: space-between;
+              padding: 2px 0;
+              > span{
+                &:first-child{
+                  color:#999;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  .chooseCard .ant-card-bordered{
+    border:1px solid #91d5ff !important;
+    background:#e6f7ff !important;
+  }
+</style>

+ 178 - 0
src/views/dataStatistics/userAnalysis/list.vue

@@ -0,0 +1,178 @@
+<template>
+  <a-card size="small" :bordered="false">
+    <div class="s-list">
+      <div class="s-row">
+        <div class="c-1">
+          <div>
+            <span>{{ countData?countData.useRate:0 }}%</span>
+            <span>转化率 ◕</span>
+          </div>
+        </div>
+        <div class="c-2">
+          <img src="@/assets/s1.png"></img>
+          <div class="text">
+            <div>注册用户</div>
+            <div>{{ countData?countData.registerUserCount:0 }}个</div>
+          </div>
+        </div>
+        <div class="c-3">
+          ● 只要登录过修配易码通就算注册用户。
+        </div>
+        <div class="c-4">
+          <a-button type="link" class="button-info" @click="toPage('registeredUser')">查看详情></a-button>
+        </div>
+      </div>
+      <div class="s-row">
+        <div class="c-1">
+          <div>
+            <span>{{ countData?countData.activeRate:0 }}%</span>
+            <span>转化率 ◕</span>
+          </div>
+        </div>
+        <div class="c-2">
+          <img src="@/assets/s2.png"></img>
+          <div class="text">
+            <div>使用用户</div>
+            <div>{{ countData?countData.useUserCount:0 }}个/{{ countData?countData.useStoreCount:0 }}家门店</div>
+          </div>
+        </div>
+        <div class="c-3">
+          <p>● 注册用户中,数字货架汽修店的员工定义为使用用户</p>
+          <p>● 如果一个汽修店-共有5位员工,会算做5个使用用户,1家门店</p>
+        </div>
+        <div class="c-4">
+          <a-button type="link" class="button-info" @click="toPage('usedUser')">查看详情></a-button>
+        </div>
+      </div>
+      <div class="s-row">
+        <div class="c-1"></div>
+        <div class="c-2">
+          <img src="@/assets/s3.png"></img>
+          <div class="text">
+            <div>活跃用户</div>
+            <div>{{ countData?countData.activeUserCount:0 }}个/{{ countData?countData.activeStoreCount:0 }}家门店</div>
+          </div>
+        </div>
+        <div class="c-3">
+          <p>● 使用用户中,最近30天内,有产生销售单的汽修店定义为活跃门店</p>
+          <p>● 这些活跃门店的员工为活跃用户</p>
+        </div>
+        <div class="c-4">
+          <a-button type="link" class="button-info" @click="toPage('activeUser')">查看详情></a-button>
+        </div>
+      </div>
+    </div>
+  </a-card>
+</template>
+
+<script>
+import { queryUserCount } from '@/api/report.js'
+export default {
+  data () {
+    return {
+      countData: null
+    }
+  },
+  methods: {
+    toPage (name) {
+      this.$router.push({ name })
+    },
+    getData () {
+      queryUserCount().then(res => {
+        this.countData = res.data || null
+      })
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.getData()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.getData()
+    }
+  }
+}
+</script>
+
+<style lang="less">
+  .s-list{
+    height: calc(100vh - 135px);
+    .s-row{
+      display: flex;
+      align-items:center;
+      &:first-child{
+        margin-top: 50px;
+      }
+      &:last-child{
+        > div{
+          border: 0;
+        }
+      }
+      > div{
+        height: 96px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+      }
+      .c-1{
+        width: 20%;
+        position: relative;
+        > div{
+          position: absolute;
+          bottom: -18px;
+          right: 20px;
+          display: flex;
+          align-items:center;
+          > span{
+            &:first-child{
+              font-size: 24px;
+              margin-right: 20px;
+            }
+            &:last-child{
+              font-size: 16px;
+              color: #999;
+            }
+          }
+        }
+      }
+      .c-2{
+        width: 374px;
+        position: relative;
+        img{
+          width:100%;
+          height: 96px;
+        }
+        .text{
+          position: absolute;
+          left:0;
+          top:0;
+          width:100%;
+          display: flex;
+          align-items:center;
+          flex-direction: column;
+          height: 100%;
+          justify-content: center;
+          color: #fff;
+          font-size: 18px;
+        }
+      }
+      .c-3{
+        width: 40%;
+        color: #666;
+        border-bottom:1px dashed #d3cfcf;
+        padding: 0 30px;
+        font-size: 14px;
+        > p{
+          margin: 3px 0;
+        }
+      }
+      .c-4{
+        width: 10%;
+        border-bottom:1px dashed #d3cfcf;
+      }
+    }
+  }
+</style>

+ 238 - 0
src/views/dataStatistics/userAnalysis/registeredUser.vue

@@ -0,0 +1,238 @@
+<template>
+  <div class="registeredUser-baseInfo">
+    <a-page-header :ghost="false" title="注册用户" :backIcon="false" class="registeredUser-back">
+      <template slot="subTitle">
+        <a href="javascript:;" @click="handleBack" id="registeredUser-handleBack">
+          <a-icon type="left"></a-icon> 返回上页
+        </a>
+      </template>
+    </a-page-header>
+    <a-card size="small" :bordered="false">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <div ref="tableSearch" class="table-page-search-wrapper">
+          <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+            <a-row :gutter="15">
+              <a-col :md="5" :sm="24">
+                <a-form-item label="注册时间">
+                  <rangeDate ref="rangeDate" v-model="time" @change="dateChange" />
+                </a-form-item>
+              </a-col>
+              <a-col :md="5" :sm="24">
+                <a-form-item label="手机号码">
+                  <a-input id="registeredUser-mobile" v-model.trim="queryParam.mobile" allowClear placeholder="请输入手机号码"/>
+                </a-form-item>
+              </a-col>
+              <a-col :md="4" :sm="24">
+                <a-form-item label="用户类型">
+                  <v-select id="registeredUser-sysUserFlag" code="USER_TYPE" v-model="queryParam.sysUserFlag" allowClear placeholder="请选择用户类型"></v-select>
+                </a-form-item>
+              </a-col>
+              <a-col :md="5" :sm="24">
+                <a-form-item label="汽车修理厂">
+                  <storeList ref="storeList" @change="storeChange" id="registeredUser-storeChange"></storeList>
+                </a-form-item>
+              </a-col>
+              <template v-if="advanced">
+                <a-col :md="4" :sm="24">
+                  <a-form-item label="职位">
+                    <v-select id="registeredUser-storeManagerFlag" code="USER_JOB" v-model="queryParam.storeManagerFlag" allowClear placeholder="请选择职位"></v-select>
+                  </a-form-item>
+                </a-col>
+                <a-col :md="5" :sm="24">
+                  <a-form-item label="配件经销商">
+                    <dealerList ref="dealerList" @change="dealerChange" id="registeredUser-dealerChange"></dealerList>
+                  </a-form-item>
+                </a-col>
+              </template>
+              <a-col :md="4" :sm="24" style="margin-bottom: 10px;">
+                <a-button type="primary" @click="$refs.table.refresh(true)" id="registeredUser-refresh">查询</a-button>
+                <a-button type="" @click="reset" style="margin-left: 10px;" id="registeredUser-reset">重置</a-button>
+                <a @click="advanced=!advanced" style="margin-left: 8px">
+                  {{ advanced ? '收起' : '展开' }}
+                  <a-icon :type="advanced ? 'up' : 'down'"/>
+                </a>
+              </a-col>
+            </a-row>
+          </a-form>
+        </div>
+        <div class="table-operator" v-if="countData">
+          <a-alert type="info">
+            <div slot="message" class="total-bar">
+              <div>
+                用户数量:<strong>{{ countData.userTotal||0 }}</strong>;
+                累计vin扫描次数合计:<strong>{{ countData.vinCount||0 }}</strong>;
+              </div>
+            </div>
+          </a-alert>
+        </div>
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          :style="{ height: tableHeight+84.5+'px', wordBreak: 'break-all' }"
+          size="small"
+          rowKey="id"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight }"
+          :defaultLoadData="false"
+          bordered>
+          <span slot="customTitle">
+            <a-popover>
+              <template slot="content">
+                表示以用户身份的vin扫描次数,<br>而不是用户所在门店的vin扫描次数
+              </template>
+              <a-icon type="question-circle" theme="twoTone" />
+            </a-popover>
+            累计vin扫描次数
+          </span>
+        </s-table>
+      </a-spin>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import rangeDate from '@/views/common/rangeDate.vue'
+import { registerUserQueryPage, queryStatistics } from '@/api/report.js'
+import dealerList from '@/views/common/dealerList.vue'
+import storeList from '@/views/common/storeList.vue'
+export default {
+  name: 'UserList',
+  components: { STable, VSelect, rangeDate, dealerList, storeList },
+  data () {
+    return {
+      spinning: false,
+      advanced: false,
+      tableHeight: 0,
+      time: [],
+      // 查询参数
+      queryParam: {
+        beginDate: '',
+        endDate: '',
+        mobile: '',
+        storeManagerFlag: undefined,
+        sysUserFlag: undefined,
+        dealerSn: undefined,
+        storeSn: undefined
+      },
+      showModal: false,
+      itemData: null, // 编辑行数据
+      openStatusModal: false, // 货架状态弹窗初始状态
+      countData: null,
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '5%', align: 'center' },
+        { title: '注册时间', dataIndex: 'registerDate', width: '15%', align: 'left', customRender: function (text) { return text || '--' } },
+        { title: '手机号码', dataIndex: 'mobile', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '用户类型', dataIndex: 'sysUserFlagDictValue', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '汽车修理厂', dataIndex: 'storeName', width: '20%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '职位', dataIndex: 'storeManagerFlagDictValue', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '配件经销商', dataIndex: 'dealerName', width: '20%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { slots: { title: 'customTitle' }, dataIndex: 'vinCount', width: '10%', align: 'center', customRender: function (text) { return (text || text == 0) ? text : '--' } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.spinning = true
+        const params = Object.assign(parameter, this.queryParam)
+        return registerUserQueryPage(params).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (let i = 0; i < data.list.length; i++) {
+              const _item = data.list[i]
+              _item.no = no + i + 1
+            }
+          }
+          this.getCount(params)
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  methods: {
+    handleBack () {
+      this.$router.go(-1)
+    },
+    getCount (params) {
+      queryStatistics(params).then(res => {
+        this.countData = res.data || null
+      })
+    },
+    //  时间  change
+    dateChange (date) {
+      this.queryParam.beginDate = date[0]
+      this.queryParam.endDate = date[1]
+    },
+    // 经销商 change
+    dealerChange (obj) {
+      this.queryParam.dealerSn = obj.key || undefined
+    },
+    // 汽车修理厂 change
+    storeChange (obj) {
+      this.queryParam.storeSn = obj.key || undefined
+    },
+    // 重置
+    reset () {
+      this.queryParam = {
+        beginDate: '',
+        endDate: '',
+        mobile: '',
+        storeManagerFlag: undefined,
+        sysUserFlag: undefined,
+        dealerSn: undefined,
+        storeSn: undefined
+      }
+      this.time = []
+      this.$refs.rangeDate.resetDate('')
+      this.$refs.table.refresh(true)
+      if (this.advanced) {
+        this.$refs.dealerList.resetForm()
+      }
+      this.$refs.storeList.resetForm()
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+        _this.reset()
+      })
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 255
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+    }
+  }
+}
+</script>
+<style lang="less">
+  .registeredUser-baseInfo{
+    .registeredUser-back{
+      margin-bottom: 6px;
+    }
+  }
+</style>

+ 195 - 0
src/views/dataStatistics/userAnalysis/setModal.vue

@@ -0,0 +1,195 @@
+<template>
+  <div>
+    <a-modal
+      centered
+      wrapClassName="setModal-modal"
+      :footer="null"
+      :maskClosable="false"
+      :title="textTitle"
+      v-model="isshow"
+      @cancle="isshow=false"
+      :width="500">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <a-form-model
+          id="setModal-form"
+          ref="ruleForm"
+          :model="form"
+          :rules="rules"
+        >
+          <div style="margin-bottom: 10px;text-align: center;">
+            <strong>近{{ form&&form.day_limit||'' }}天下单额</strong>
+          </div>
+          <a-form-model-item label="LV1" prop="LV1" :label-col="{span: 4}" :wrapper-col="{span: 18}">
+            <a-input-number style="width:80%;" v-model.trim="form.LV1" :precision="2" allowClear placeholder="请输入LV1下单额"/>
+            元以下
+          </a-form-model-item>
+          <a-form-model-item label="LV2" prop="LV2" :label-col="{span: 4}" :wrapper-col="{span: 18}">
+            <a-input-group style="width: 90%;" compact>
+              <a-input style="width: 43%; text-align: center;pointer-events: none; backgroundColor: #f8f8f8;color:#666;" disabled v-model.trim="form.LV1"/>
+              <a-input
+                style=" width: 12%; pointer-events: none; backgroundColor: #fff"
+                placeholder="至"
+                disabled
+              />
+              <a-input-number
+                :precision="2"
+                :min="form.LV1"
+                style="width: 43%; text-align: center"
+                v-model.trim="form.LV2"
+                allowClear
+                placeholder="请输入LV2下单额"/>
+            </a-input-group>
+            元
+          </a-form-model-item>
+          <a-form-model-item label="LV3" prop="LV3" :label-col="{span: 4}" :wrapper-col="{span: 18}">
+            <a-input-group style="width: 90%;" compact>
+              <a-input style=" width: 43%; text-align: center;pointer-events: none; backgroundColor: #f8f8f8;color:#666;" disabled v-model.trim="form.LV2"/>
+              <a-input
+                style=" width: 12%; pointer-events: none; backgroundColor: #fff"
+                placeholder="至"
+                disabled
+              />
+              <a-input-number
+                :precision="2"
+                :min="form.LV2"
+                style=" width: 43%; text-align: center"
+                v-model.trim="form.LV3"
+                allowClear
+                placeholder="请输入LV3下单额"/>
+            </a-input-group>
+            元
+          </a-form-model-item>
+          <a-form-model-item label="LV4" prop="LV4" :label-col="{span: 4}" :wrapper-col="{span: 18}">
+            <a-input-group style="width: 90%;" compact>
+              <a-input style=" width: 43%; text-align: center;pointer-events: none; backgroundColor: #f8f8f8;color:#666;" disabled v-model.trim="form.LV3"/>
+              <a-input
+                style=" width: 12%; pointer-events: none; backgroundColor: #fff"
+                placeholder="至"
+                disabled
+              />
+              <a-input-number
+                :precision="2"
+                :min="form.LV3"
+                style=" width: 43%; text-align: center"
+                v-model.trim="form.LV4"
+                allowClear
+                placeholder="请输入LV4下单额"/>
+            </a-input-group>
+            元
+          </a-form-model-item>
+          <a-form-model-item label="LV5" :label-col="{span: 4}" :wrapper-col="{span: 18}">
+            <a-input style="width: 80%; text-align: center;pointer-events: none; backgroundColor: #f8f8f8;color:#666;" disabled v-model.trim="form.LV4"/>
+            元以上
+          </a-form-model-item>
+
+          <a-form-model-item :label-col="{span: 0}" :wrapper-col="{span: 24}" style="text-align: center;">
+            <a-button type="primary" @click="handleSubmit()" :style="{ marginRight: '8px' }" id="setModal-handleSubmit">保存</a-button>
+            <a-button :style="{ marginLeft: '8px' }" @click="isshow=false" id="setModal-close">取消</a-button>
+          </a-form-model-item>
+        </a-form-model>
+      </a-spin>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { queryStoreLevelParamMap, saveStoreLevelParam } from '@/api/report.js'
+export default {
+  name: 'AddHWModal',
+  props: {
+    openModal: {
+      type: Boolean,
+      default: false
+    },
+    shelfSn: {
+      type: [String, Number],
+      default: ''
+    },
+    nowData: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    }
+  },
+
+  data () {
+    return {
+      spinning: false,
+      isshow: this.openModal,
+      textTitle: '参数设置',
+      roleList: [],
+      pageInfo: null,
+      form: {
+        LV1: '',
+        LV2: '',
+        LV3: '',
+        lv4: '',
+        LV5: '',
+        day_limit: '30'
+      },
+      rules: {
+        LV1: [{ required: true, message: '请输入LV1下单金额', trigger: 'blur' }],
+        LV2: [{ required: true, message: '请输入LV2下单金额', trigger: 'blur' }],
+        LV3: [{ required: true, message: '请输入LV3下单金额', trigger: 'blur' }],
+        LV4: [{ required: true, message: '请输入LV4下单金额', trigger: 'blur' }]
+      }
+    }
+  },
+  methods: {
+    // 查询货位详情
+    getDetail () {
+      this.spinning = true
+      queryStoreLevelParamMap().then(res => {
+        if (res.status == 200) {
+          this.form = Object.assign({}, res.data)
+          for (const key in this.form) {
+            this.form[key] = Number(this.form[key])
+          }
+        }
+        this.spinning = false
+      })
+    },
+    // 保存提交
+    handleSubmit () {
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          _this.spinning = true
+          saveStoreLevelParam(_this.form).then(res => {
+            if (res.status == 200) {
+              _this.$message.success(res.message)
+              _this.$emit('ok')
+              setTimeout(function () {
+                _this.isshow = false
+                _this.spinning = false
+              }, 300)
+            } else {
+              _this.spinning = false
+            }
+          })
+        } else {
+          console.log('error submit!!')
+          return false
+        }
+      })
+    }
+  },
+  watch: {
+    openModal (newValue, oldValue) {
+      this.isshow = newValue
+    },
+    isshow (newValue, oldValue) {
+      if (!newValue) {
+        this.$refs.ruleForm.resetFields()
+        this.form = {}
+        this.$emit('close')
+      } else {
+        this.getDetail()
+      }
+    }
+  }
+}
+</script>
+<style lang="less">
+</style>

+ 278 - 0
src/views/dataStatistics/userAnalysis/usedUser.vue

@@ -0,0 +1,278 @@
+<template>
+  <div class="userd-baseInfo">
+    <a-page-header :ghost="false" title="使用用户" :backIcon="false" class="userd-back">
+      <template slot="subTitle">
+        <a href="javascript:;" @click="handleBack" id="userd-handleBack">
+          <a-icon type="left"></a-icon> 返回上页
+        </a>
+      </template>
+    </a-page-header>
+    <a-card size="small" :bordered="false">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <div ref="tableSearch" class="table-page-search-wrapper">
+          <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
+            <a-row :gutter="15">
+              <a-col :md="5" :sm="24">
+                <a-form-item label="货架创建时间">
+                  <rangeDate ref="rangeDate" v-model="time" @change="dateChange" />
+                </a-form-item>
+              </a-col>
+              <a-col :md="5" :sm="24">
+                <a-form-item label="汽车修理厂">
+                  <storeList ref="storeList" @change="storeChange" id="userd-storeChange"></storeList>
+                </a-form-item>
+              </a-col>
+              <a-col :md="5" :sm="24">
+                <a-form-item label="配件经销商">
+                  <dealerList ref="dealerList" @change="dealerChange" id="userd-dealerChange"></dealerList>
+                </a-form-item>
+              </a-col>
+              <a-col :md="4" :sm="24">
+                <a-form-item label="所在地">
+                  <areaList level="2" placeholder="请选择所在地" v-model="areaArr" @change="areaChange"></areaList>
+                </a-form-item>
+              </a-col>
+              <template v-if="advanced">
+                <a-col :md="4" :sm="24">
+                  <a-form-item label="货架状态">
+                    <v-select
+                      id="userd-state"
+                      code="SHELF_STATE"
+                      v-model="queryParam.shelfState"
+                      allowClear
+                      placeholder="请选择状态"
+                      :notIn="['NOT_ENABLE']"></v-select>
+                  </a-form-item>
+                </a-col>
+                <a-col :md="5" :sm="24">
+                  <a-form-item label="最近下单时间">
+                    <rangeDate ref="orderDate" :value="orderTime" @change="orderDateChange" />
+                  </a-form-item>
+                </a-col>
+              </template>
+              <a-col :md="4" :sm="24" style="margin-bottom: 10px;">
+                <a-button type="primary" @click="$refs.table.refresh(true)" id="userd-refresh">查询</a-button>
+                <a-button type="" @click="reset" style="margin-left: 10px;" id="userd-reset">重置</a-button>
+                <a-button type="primary" @click="exportFile" class="button-warning" style="margin-left: 10px;" id="userd-reset">导出</a-button>
+                <a @click="advanced=!advanced" style="margin-left: 8px">
+                  {{ advanced ? '收起' : '展开' }}
+                  <a-icon :type="advanced ? 'up' : 'down'"/>
+                </a>
+              </a-col>
+            </a-row>
+          </a-form>
+        </div>
+        <div class="table-operator" v-if="countData">
+          <a-alert type="info">
+            <div slot="message" class="total-bar">
+              <div>
+                门店数量:<strong>{{ countData.shelfCount||0 }}</strong>;
+                铺货数量合计:<strong>{{ countData.totalShelfMaxQty||0 }}</strong>;
+                铺货金额合计:<strong>{{ countData.totalShelfMaxCost||0 }}</strong>;
+              </div>
+            </div>
+          </a-alert>
+        </div>
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          :style="{ height: tableHeight+84.5+'px', wordBreak: 'break-all' }"
+          size="small"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight }"
+          :defaultLoadData="false"
+          bordered>
+          <div slot="area" slot-scope="text, record">
+            {{ record.dealerProvinceName }} {{ record.dealerCityName }}
+          </div>
+          <span slot="customTitle">
+            <a-popover>
+              <template slot="content">
+                表示此修理厂最近一次从货架上取货的时间
+              </template>
+              <a-icon type="question-circle" theme="twoTone" />
+            </a-popover>
+            最近下单时间
+          </span>
+        </s-table>
+      </a-spin>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { STable, VSelect } from '@/components'
+import rangeDate from '@/views/common/rangeDate.vue'
+import { useUserQueryPage, useUserStatistics, exportShelfUseUser } from '@/api/report.js'
+import areaList from '@/views/common/areaList.js'
+import dealerList from '@/views/common/dealerList.vue'
+import storeList from '@/views/common/storeList.vue'
+import { hdExportExcel } from '@/libs/exportExcel'
+import { toThousands } from '@/libs/tools.js'
+export default {
+  name: 'UserList',
+  components: { STable, VSelect, rangeDate, dealerList, storeList, areaList },
+  data () {
+    return {
+      spinning: false,
+      advanced: false,
+      tableHeight: 0,
+      areaArr: [],
+      time: [],
+      orderTime: [],
+      // 查询参数
+      queryParam: {
+        shelfCreateBeginDate: '',
+        shelfCreateEndDate: '',
+        lastOrderBeginDate: '',
+        lastOrderEndDate: '',
+        storeSn: undefined,
+        dealerSn: undefined,
+        shelfState: undefined,
+        dealerProvinceSn: undefined,
+        dealerCitySn: undefined
+      },
+      showModal: false,
+      itemData: null, // 编辑行数据
+      countData: null,
+      openStatusModal: false, // 货架状态弹窗初始状态
+      // 表头
+      columns: [
+        { title: '序号', dataIndex: 'no', width: '5%', align: 'center' },
+        { title: '货架创建时间', dataIndex: 'shelfCreateDate', width: '10%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '汽车修理厂', dataIndex: 'storeName', width: '15%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '配件经销商', dataIndex: 'dealerName', width: '15%', align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '所在地', scopedSlots: { customRender: 'area' }, width: '11%', align: 'center' },
+        { title: '货架状态', dataIndex: 'shelfStateDictValue', width: '11%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '铺货数量', dataIndex: 'totalShelfMaxQty', width: '11%', align: 'center', customRender: function (text) { return (text || text == 0) ? text : '--' } },
+        { title: '铺货金额', dataIndex: 'totalShelfMaxCost', width: '11%', align: 'center', customRender: function (text) { return (text || text == 0) ? text : '--' } },
+        { slots: { title: 'customTitle' }, dataIndex: 'lastOrderDate', width: '11%', align: 'center', customRender: function (text) { return text || '--' } }
+      ],
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.spinning = true
+        const params = Object.assign(parameter, this.queryParam)
+        return useUserQueryPage(params).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            const no = (data.pageNo - 1) * data.pageSize
+            for (let i = 0; i < data.list.length; i++) {
+              const _item = data.list[i]
+              _item.no = no + i + 1
+            }
+          }
+          this.getCount(params)
+          this.spinning = false
+          return data
+        })
+      }
+    }
+  },
+  methods: {
+    handleBack () {
+      this.$router.go(-1)
+    },
+    getCount (params) {
+      useUserStatistics(params).then(res => {
+        this.countData = res.data || null
+      })
+    },
+    // 地区
+    areaChange (val, opts) {
+      this.queryParam.dealerProvinceSn = val && val[0] ? val[0] : ''
+      this.queryParam.dealerCitySn = val && val[1] ? val[1] : ''
+    },
+    //  时间  change
+    dateChange (date) {
+      this.queryParam.shelfCreateBeginDate = date[0]
+      this.queryParam.shelfCreateEndDate = date[1]
+    },
+    //  时间  change
+    orderDateChange (date) {
+      this.queryParam.lastOrderBeginDate = date[0]
+      this.queryParam.lastOrderEndDate = date[1]
+    },
+    // 经销商 change
+    dealerChange (obj) {
+      this.queryParam.dealerSn = obj.key || undefined
+    },
+    // 汽车修理厂 change
+    storeChange (obj) {
+      this.queryParam.storeSn = obj.key || undefined
+    },
+    // 导出
+    exportFile () {
+      const _this = this
+      this.spinning = true
+      hdExportExcel(exportShelfUseUser, this.queryParam, '用户分析(使用用户)详情', function () {
+        _this.spinning = false
+      })
+    },
+    // 重置
+    reset () {
+      this.queryParam = {
+        shelfCreateBeginDate: '',
+        shelfCreateEndDate: '',
+        lastOrderBeginDate: '',
+        lastOrderEndDate: '',
+        storeSn: undefined,
+        dealerSn: undefined,
+        shelfState: undefined,
+        dealerProvinceSn: undefined,
+        dealerCitySn: undefined
+      }
+      this.areaArr = []
+      this.$refs.rangeDate.resetDate()
+      if (this.advanced) {
+        this.$refs.orderDate.resetDate()
+      }
+      this.$refs.dealerList.resetForm()
+      this.$refs.storeList.resetForm()
+      this.$refs.table.refresh(true)
+    },
+    pageInit () {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 255
+    }
+  },
+  watch: {
+    advanced (newValue, oldValue) {
+      const _this = this
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        _this.setTableH()
+      })
+    },
+    '$store.state.app.winHeight' (newValue, oldValue) { //  窗口变更时,需同时更改表格高度
+      this.setTableH()
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+      this.reset()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+      this.reset()
+    }
+  }
+}
+</script>
+<style lang="less">
+  .userd-baseInfo{
+    .userd-back{
+      margin-bottom: 6px;
+    }
+  }
+</style>

+ 5 - 5
src/views/numsGoodsShelves/bondManagement/list.vue

@@ -4,23 +4,23 @@
       <div ref="tableSearch" class="table-page-search-wrapper">
         <a-form layout="inline" @keyup.enter.native="$refs.table.refresh(true)">
           <a-row :gutter="15">
-            <a-col :md="6" :sm="24">
+            <a-col :md="5" :sm="24">
               <a-form-item label="货架名称">
                 <a-input id="bondManagementList-shelfName" allowClear v-model.trim="queryParam.shelfName" placeholder="请输入货架名称"/>
               </a-form-item>
             </a-col>
-            <a-col :md="6" :sm="24">
+            <a-col :md="5" :sm="24">
               <a-form-item label="配件经销商">
                 <dealerList ref="dealerList" @change="dealerChange" id="bondManagementList-dealerChange"></dealerList>
               </a-form-item>
             </a-col>
-            <a-col :md="6" :sm="24">
+            <a-col :md="5" :sm="24">
               <a-form-item label="汽车修理厂">
                 <storeList ref="storeList" @change="storeChange" id="bondManagementList-storeChange"></storeList>
               </a-form-item>
             </a-col>
             <template v-if="advanced">
-              <a-col :md="6" :sm="24">
+              <a-col :md="5" :sm="24">
                 <a-form-item label="状态">
                   <v-select id="bondManagementList-state" code="BOND_RECORD_STATE" v-model="queryParam.state" allowClear placeholder="请选择状态"></v-select>
                 </a-form-item>
@@ -38,7 +38,7 @@
         </a-form>
       </div>
       <div class="table-operator">
-        <a-button size="small" type="primary" class="button-error" @click="handleEdit()" id="bondManagementList-handleEdit">新增保证金</a-button>
+        <a-button type="primary" class="button-error" @click="handleEdit()" id="bondManagementList-handleEdit">新增保证金</a-button>
       </div>
       <s-table
         class="sTable fixPagination"

+ 7 - 0
src/views/numsGoodsShelves/redPacket/shelfModal.vue

@@ -131,6 +131,13 @@ export default {
     // 表格选中项
     rowSelectionFun (obj) {
       this.rowSelectionInfo = obj || null
+      const ret = []
+      this.rowSelectionInfo.selectedRowKeys.map(item => {
+        ret.push({
+          'shelfSn': item
+        })
+      })
+      this.checkedList = ret
     },
     // 经销商 change
     dealerChange (obj) {

+ 2 - 2
vue.config.js

@@ -108,8 +108,8 @@ const vueConfig = {
     // If you want to turn on the proxy, please remove the mockjs /src/main.jsL11
     proxy: {
       '/api': {
-        // target: 'http://p.xprh.360arrow.com/xprh-admin',
-        target: 'http://192.168.0.103:8701/xprh-admin',
+        target: 'http://p.xprh.360arrow.com/xprh-admin',
+        // target: 'http://192.168.0.115:8701/xprh-admin',
         // ws: false,
         ws: true,
         changeOrigin: true,