Crunchy
2025-06-14 7e460156de73171f9660ce48f80703e79f8b478d
初始化提交
已删除1个文件
已修改39个文件
4523 ■■■■ 文件已修改
.env.development 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.production 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/index.html 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/table.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/user.js 93 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/loginbg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Hamburger/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SettingTitle/index.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SvgIcon/index.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/TableSearch/index.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/AppMain.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Navbar.vue 198 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Sidebar/Logo.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/index.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/permission.js 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 82 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/settings.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/getters.js 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/index.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.js 82 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/element-ui.scss 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/sidebar.scss 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/variables.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/auth.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request.js 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/validate.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/add_operation/barcode/index.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/add_operation/index.vue 639 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/index.vue 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.vue 264 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/out_operation/index.vue 816 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/out_operation/manual/index.vue 327 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/out_operation/outboundLedger/index.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/outbound/index.vue 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/dict/index.vue 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/user/index.vue 854 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.development
@@ -2,4 +2,5 @@
ENV = 'development'
# base api
VUE_APP_BASE_API = '/dev-api'
VUE_APP_BASE_API = 'http://localhost:8011'
# VUE_APP_BASE_API = '/dev-api'
.env.production
@@ -2,5 +2,6 @@
ENV = 'production'
# base api
VUE_APP_BASE_API = 'http://localhost:8080'
VUE_APP_BASE_API = 'http://58.56.84.138:9155'
# VUE_APP_BASE_API = 'http://localhost:8080'
package.json
@@ -17,12 +17,15 @@
    "axios": "0.18.1",
    "core-js": "3.6.5",
    "echarts": "^5.4.2",
    "element-ui": "2.13.2",
    "element-ui": "^2.15.3",
    "js-cookie": "2.2.0",
    "jsbarcode": "^3.11.5",
    "normalize.css": "7.0.0",
    "nprogress": "0.2.0",
    "path-to-regexp": "2.4.0",
    "vue": "2.6.10",
    "vue-barcode": "^1.3.0",
    "vue-print-nb": "^1.7.5",
    "vue-router": "3.0.6",
    "vuex": "3.1.0"
  },
public/index.html
@@ -6,6 +6,20 @@
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= webpackConfig.name %></title>
    <style media="print">
      @page{
        size: auto;
        margin: 3mm;
      }
      html{
        background-color: #fff;
        margin: 0px;
      }
      body{
        border: 1px solid #fff;
        margin: 10mm 15mm 10mm 15mm;
      }
    </style>
  </head>
  <body>
    <noscript>
src/api/table.js
@@ -2,7 +2,7 @@
export function getList(params) {
  return request({
    url: '/vue-admin-template/table/list',
    url: '/table/list',
    method: 'get',
    params
  })
src/api/user.js
@@ -1,24 +1,45 @@
import request from '@/utils/request'
export function login(data) {
/* export function login(data) {
  return request({
    url: '/vue-admin-template/user/login',
    method: 'post',
    data
  })
} */
// refresh
export function refresh(data) {
  return request({
    url: '/user/login/refresh',
    method: 'post',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    data
  })
}
export function login(data) {
  return request({
    url: '/user/login/account',
    method: 'post',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    data
  })
}
export function getInfo(token) {
  return request({
    url: '/vue-admin-template/user/info',
    method: 'get',
    params: { token }
    url: '/user/info',
    method: 'get'
    // params: { token }
  })
}
export function logout() {
  return request({
    url: '/vue-admin-template/user/logout',
    url: '/user/logout',
    method: 'post'
  })
}
@@ -40,12 +61,30 @@
  })
}
// æ–°å¢žç”¨æˆ·
export function addUser(data) {
// æ·»åŠ åº“å­˜åç§°
export function addProductName(params) {
  return request({
    url: '/system/user',
    url: '/product_name/add',
    method: 'post',
    data: data
    params
  })
}
// æ·»åŠ åº“å­˜åç§°
export function addProductModel(params) {
  return request({
    url: '/product_name/add',
    method: 'post',
    params
  })
}
// æ–°å¢žç”¨æˆ·
export function addUser(params) {
  return request({
    url: '/user/add',
    method: 'post',
    params
  })
}
@@ -59,10 +98,11 @@
}
// åˆ é™¤ç”¨æˆ·
export function delUser(userId) {
export function delUser(params) {
  return request({
    url: '/system/user/' + userId,
    method: 'delete'
    url: '/user/delete',
    method: 'delete',
    params
  })
}
@@ -101,24 +141,20 @@
}
// ä¿®æ”¹ç”¨æˆ·ä¸ªäººä¿¡æ¯
export function updateUserProfile(data) {
export function updateUserProfile(params) {
  return request({
    url: '/system/user/profile',
    url: '/user/update/user',
    method: 'put',
    data: data
    params
  })
}
// ç”¨æˆ·å¯†ç é‡ç½®
export function updateUserPwd(oldPassword, newPassword) {
  const data = {
    oldPassword,
    newPassword
  }
export function updateUserPwd(params) {
  return request({
    url: '/system/user/profile/updatePwd',
    url: '/user/update/password',
    method: 'put',
    params: data
    params
  })
}
@@ -149,10 +185,19 @@
}
// æŸ¥è¯¢éƒ¨é—¨ä¸‹æ‹‰æ ‘结构
export function deptTreeSelect() {
export function getUserList() {
  return request({
    url: '/system/user/deptTree',
    url: '/user/list',
    method: 'get'
  })
}
export function tideLogin(data) {
  return request({
    url: '/tide/tideLogin',
    method: 'post',
    data: {
      code: data
    }
  })
}
src/assets/images/loginbg.png

src/assets/images/logo.png

src/components/Hamburger/index.vue
@@ -36,6 +36,7 @@
  vertical-align: middle;
  width: 20px;
  height: 20px;
  fill: #fff;
}
.hamburger.is-active {
src/components/SettingTitle/index.vue
@@ -1,14 +1,19 @@
<template>
  <div class="setting-title">
    <div class="title-left">{{left}}</div>
    <div class="title-right">{{right}}</div>
    <div class="title-right" @click="clickEvent"><span :class="icon"></span> {{right}}</div>
  </div>
</template>
<script>
export default {
  name: 'SettingTitle',
  props: ['left', 'right']
  props: ['left', 'right', 'icon', 'clickFun'],
  methods: {
    clickEvent() {
      this.clickFun()
    }
  }
}
</script>
src/components/SvgIcon/index.vue
@@ -1,8 +1,11 @@
<template>
  <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
  <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
  <!-- <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
    <use :xlink:href="iconName" />
  </svg>
  </svg> -->
  <span v-else class="iconfont" :class="svgClass" aria-hidden="true" v-on="$listeners">
    <!-- <i class="iconfont" :class="iconName"></i> -->
  </span>
</template>
<script>
@@ -26,13 +29,14 @@
      return isExternal(this.iconClass)
    },
    iconName() {
      return `#icon-${this.iconClass}`
      // return `#icon-${this.iconClass}`
      return `iconfont ${this.iconClass}`
    },
    svgClass() {
      if (this.className) {
        return 'svg-icon ' + this.className
        return 'svg-icon ' + this.iconClass + this.className
      } else {
        return 'svg-icon'
        return 'svg-icon ' + this.iconClass
      }
    },
    styleExternalIcon() {
src/components/TableSearch/index.vue
@@ -1,40 +1,139 @@
<template>
  <div class="table-search">
    <el-form
      v-model="queryParams"
      ref="queryForm"
      v-model="queryParams"
      size="small"
      :inline="true"
      label-width="68px"
    >
      <el-form-item label="日期:">
        <el-date-picker
          v-model="queryParams.date"
          value-format="yyyy-MM-dd HH:mm"
          format="yyyy-MM-dd HH:mm"
          type="datetimerange"
          :picker-options="pickerOptions"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          align="right"
        >
        </el-date-picker>
        />
      </el-form-item>
      <el-form-item label="规格:">
        <el-select placeholder="规格型号" clearable style="width: 240px">
      <el-form-item v-show="show" :label="searchParams.hasOwnProperty('productModel')? '规格型号':'客户名称'">
        <el-select v-model="queryParams.type" :placeholder="searchParams.hasOwnProperty('productModel')? '请选择规格型号':'请选择客户名称'" clearable style="width: 240px">
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini"
          >搜索</el-button
        >
        <el-button icon="el-icon-refresh" size="mini">导出</el-button>
        <el-button
          type="primary"
          icon="el-icon-search"
          size="mini"
          @click="search"
        >搜索</el-button>
        <el-button :style="{color:'#409EFF',border:' 1px solid #409EFF'}" icon="iconfont icon-wenjiandaochu" size="mini" @click="exportExcel">导出</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
export default {
  props: [
    'searchData',
    'searchParams',
    'options',
    'getList',
    'file',
    'show',
    'excelName'
  ],
  data() {
    return {
      queryParams: {
        date: [],
        type: ''
      },
      pickerOptions: {
        shortcuts: [{
          text: '最近一周',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近一个月',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近三个月',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
            picker.$emit('pick', [start, end])
          }
        }]
      }
    }
  },
  methods: {
    search() {
      // "查询条件:"时间需要格式化成yyyy-mm-dd hh-mm-ss
      // console.log(this.queryParams)
      let { date, type } = this.queryParams
      date = date == null ? [] : date
      let params = { ...this.searchParams, startTime: date[0], endTime: date[1] }
      params = this.searchParams.hasOwnProperty('productModel') ? { ...params, productModel: type } : { ...params, customerName: type }
      const obj = {}
      const arr = Object.keys(params).filter(key => params[key])
      arr.forEach(item => obj[item] = params[item])
      console.log(obj)// æŸ¥çœ‹æ‰€æœ‰è¯·æ±‚参数
      this.getList(obj).then(res => {
        this.searchData({ ...res.data, startTime: date[0], endTime: date[1] })
      })
    },
    exportExcel() {
      let { date, type } = this.queryParams
      date = date == null ? [] : date
      let params = { startTime: date[0], endTime: date[1] }
      params = this.searchParams.hasOwnProperty('productModel') ? { ...params, productModel: type } : { ...params, customerName: type }
      const obj = {}
      const arr = Object.keys(params).filter(key => params[key])
      arr.forEach(item => obj[item] = params[item])
      console.log(obj)// æŸ¥çœ‹æ‰€æœ‰è¯·æ±‚参数
      this.file(obj).then(response => {
        const blob = new Blob([response.data], { type: 'application/vnd.ms-excel;charset=utf-8' })
        const downloadElement = document.createElement('a')
        const href = window.URL.createObjectURL(blob) // åˆ›å»ºä¸‹è½½çš„链接
        downloadElement.href = href
        downloadElement.download = `${this.excelName}.xlsx` // ä¸‹è½½åŽæ–‡ä»¶å
        document.body.appendChild(downloadElement)
        downloadElement.click() // ç‚¹å‡»ä¸‹è½½
        this.loadingBtn = false
        document.body.removeChild(downloadElement) // ä¸‹è½½å®Œæˆç§»é™¤å…ƒç´ 
        window.URL.revokeObjectURL(href) // é‡Šæ”¾æŽ‰blob对象
      }).catch(message => {
        this.$message.error({
          message: '抱歉下载错误!错误原因:' + message,
          type: 'error'
        })
      })
    }
  }
}
</script>
@@ -43,6 +142,6 @@
   .el-form-item{
      margin-bottom: 0;
      margin: 12px;
    }
    }
}
</style>
</style>
src/layout/components/AppMain.vue
@@ -24,9 +24,10 @@
  width: 100%;
  position: relative;
  overflow: hidden;
}
.fixed-header+.app-main {
  padding-top: 50px;
  padding-top: 97px;
}
</style>
src/layout/components/Navbar.vue
@@ -1,74 +1,211 @@
<template>
  <div class="navbar">
    <hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
  <div class="header">
    <div class="navbar">
      <hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
      <el-input v-model="keyword" size="small" placeholder="请输入客户名称查询台账" class="input-with-select">
        <el-button slot="append" type="primary" icon="el-icon-search" @click="goTo" />
      </el-input>
      <!-- <breadcrumb class="breadcrumb-container" /> -->
      <div class="center-title">
        WMS系统
      </div>
    <breadcrumb class="breadcrumb-container" />
    <div class="center-title">
      ä¸­å¤©ç§‘技WMS系统
    </div>
    <div class="right-menu">
      <el-dropdown class="avatar-container" trigger="click">
        <div class="avatar-wrapper">
          <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
          <i class="el-icon-caret-bottom" />
        </div>
        <el-dropdown-menu slot="dropdown" class="user-dropdown">
          <router-link to="/">
      <div class="right-menu">
        <el-dropdown class="avatar-container" trigger="click">
          <div class="avatar-wrapper">
            <!-- <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar"> -->
            <img :src="baseUrl+'/img'+avatar" class="user-avatar">
            <span class="avater-name">{{ name }}</span>
          <!-- <i class="el-icon-caret-bottom" /> -->
          </div>
          <el-dropdown-menu slot="dropdown" class="user-dropdown">
            <!-- <router-link to="/">
            <el-dropdown-item>
              Home
            </el-dropdown-item>
          </router-link>
          <a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/">
          </router-link> -->
            <!-- <a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/">
            <el-dropdown-item>Github</el-dropdown-item>
          </a>
          <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
            <el-dropdown-item>Docs</el-dropdown-item>
          </a>
          <el-dropdown-item divided @click.native="logout">
            <span style="display:block;">Log Out</span>
          </el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
          </a> -->
            <!-- <el-button>退出</el-button> -->
            <el-dropdown-item divided @click.native="logout">
              <span style="display:block;">退 å‡º</span>
            </el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </div>
    </div>
    <div class="header-tabs">
      <div class="el-icon-arrow-left" @click="prev" />
      <div class="routers">
        <a v-for="tag in openTab.openTab">
          <el-tag
            :key="tag.name"
            closable
            :class="tag.name==openTab.activeIndex?'active':''"
            @close="handleClose(tag)"
            @click="changeRouter(tag)"
          >
            {{ tag.name }}
          </el-tag>
        </a>
      </div>
    </div>
  </div>
</template>
<script>
import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger'
import openTab from '@/store/modules/openTab'
// import openTab from '@/store/modules/openTab'
export default {
  components: {
    Breadcrumb,
    Hamburger
  },
  data() {
    return {
      keyword: '',
      routers: [
      ],
      baseUrl: process.env.VUE_APP_BASE_API
    }
  },
  computed: {
    ...mapGetters([
      'sidebar',
      'avatar'
      'avatar',
      'name',
      'openTab'
    ])
  },
  mounted() {
    // console.log(this.openTab)
  },
  methods: {
    goTo() {
      // console.log('点击查询', this.$route)
      this.$router.push({ path: '/outbound/outboundLedger', query: { keyword: this.keyword }})
      this.keyword = ''
      // if (this.$route.name === '出库台账') {
      //   console.log('输出当前')
      //   // this.$router.go(0)
      //   return
      // }
    },
    prev() {
      this.$router.go(-1)
    },
    handleClose(tag) {
      console.log(this.openTab.activeIndex)
      if (this.openTab.openTab.length == 1) {
        if (tag.name == '主页') {
          return
        }
        this.$store.commit('DEL_TAB', tag.route)
        this.$router.push('/home')
        this.$store.commit('SET_ACTIVE_INDEX', '/home')
      }
      if (this.openTab.activeIndex == tag.route) {
        this.$store.commit('DEL_TAB', tag.route)
        this.$router.push(this.openTab.openTab[0].route)
        this.$store.commit('SET_ACTIVE_INDEX', this.openTab.openTab[0].route)
      }
      this.$store.commit('DEL_TAB', tag.route)
    },
    toggleSideBar() {
      this.$store.dispatch('app/toggleSideBar')
    },
    async logout() {
      await this.$store.dispatch('user/logout')
      this.$router.push(`/login?redirect=${this.$route.fullPath}`)
    },
    goBack() {
    },
    changeRouter(tag) {
      this.$router.push(tag.route)
    }
  }
}
</script>
<style lang="scss" scoped>
.header{
  background: #efefef;
  .header-tabs{
    margin-top: 10px;
    background: #304156;
    color: #fff;
    height: 35px;
    display: flex;
    align-items: center;
    >div:nth-child(1){
      width: 40px;
      text-align: center;
    }
    .el-tabs{
      flex: 1;
    }
    ::v-deep .el-breadcrumb .el-breadcrumb__inner a{
      color: #fff !important;
    }
    .el-tag{
      height: 100%;
      background: #304156;
      color: #fff;
      border-radius: 0;
      margin: 0;
      border-right: 0px;
      border-top: 0px;
      border-bottom: 0px;
      line-height: 35px;
      .el-tag__close{
        color: #fff;
      }
    }
    .routers{
      height: 100%;
       a:last-of-type{
      .el-tag{
      border-right: 1px solid #fff;
     }
    }
    }
    // .el-tag,.active{
    //   color: #409EFF !important;
    // }
  }
}
.navbar {
  height: 50px;
  overflow: hidden;
  position: relative;
  background: #fff;
  background: #304156;
  color: #fff;
  line-height: 50px;
  box-shadow: 0 1px 4px rgba(0,21,41,.08);
  ::v-deep .el-input-group__append{
    background: #448ACA;
    border: 0px;
    color: #fff;
  }
  .input-with-select{
  width: 300px;
  // height: 30px;
}
  .center-title{
    position: absolute;
    left: 50%;
@@ -125,12 +262,19 @@
      .avatar-wrapper {
        margin-top: 5px;
        position: relative;
        color: #fff;
        display: flex;
        .avater-name{
          // position: absolute;
          // top: 50%;
          margin-left: 10px;
        }
        .user-avatar {
          cursor: pointer;
          border-radius: 50%;
          width: 40px;
          height: 40px;
          border-radius: 10px;
          // border-radius: 10px;
        }
        .el-icon-caret-bottom {
src/layout/components/Sidebar/Logo.vue
@@ -28,6 +28,9 @@
      title: 'Vue Admin Template',
      logo
    }
  },
  mounted() {
    console.log(this.collapse)
  }
}
</script>
@@ -47,19 +50,21 @@
  width: 100%;
  height: 50px;
  line-height: 50px;
  background: #6095FB;
  background: #304156;
  text-align: center;
  overflow: hidden;
  & .sidebar-logo-link {
    height: 100%;
    width: 100%;
    text-align:left;
    & .sidebar-logo {
      padding: 7.5px 20px;
      // padding: 7.5px 20px;
      width: 135px;
      height: 45px;
      vertical-align: middle;
      // position: absolute;
      // left: 20px;
    }
    & .sidebar-title {
src/layout/index.vue
@@ -63,6 +63,12 @@
      position: fixed;
      top: 0;
    }
  }
  .hideSidebar .sidebar-container{
     ::v-deep img{
        //  content: url("@/a");
      }
  }
  .drawer-bg {
    background: #000;
src/main.js
@@ -7,10 +7,11 @@
import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n
import '@/styles/index.scss' // global css
import '@/assets/iconfont/iconfont.css'
import App from './App'
import store from './store'
import router from './router'
import Print from 'vue-print-nb'
import '@/icons' // icon
import '@/permission' // permission control
@@ -32,9 +33,16 @@
Vue.use(ElementUI, { locale })
// å¦‚果想要中文版 element-ui,按如下方式声明
// Vue.use(ElementUI)
Vue.use(Print)
Vue.config.productionTip = false
Vue.prototype.$flush = () => {
  if (this.$route.path !== '/' && this.$route.path !== '/home') {
    console.log('1');
    this.$store.commit('ADD_TAB', {route: '/home' , name: 'home'});
    this.$store.commit('ADD_TAB', {route: this.$route.path , name: this.$route.name });
    this.$store.commit('SET_ACTIVE_INDEX', this.$route.path);
  }
}
new Vue({
  el: '#app',
  router,
src/permission.js
@@ -13,27 +13,36 @@
router.beforeEach(async(to, from, next) => {
  // start progress bar
  NProgress.start()
  console.log(to)
  if (to.query.code) {
    console.log(to.query.code)
    store.dispatch('user/tideLogin', to.query.code).then(res => {
      next({ path: '/' })
    })
  }
  // set page title
  document.title = getPageTitle(to.meta.title)
  // determine whether the user has logged in
  const hasToken = getToken()
  // console.log('路由守卫', hasToken)
  if (hasToken) {
    // console.log('服务器有token')
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({ path: '/' })
      NProgress.done()
    } else {
      // console.log('服务器有token,访问不是login页面')
      const hasGetUserInfo = store.getters.name
      if (hasGetUserInfo) {
        next()
      } else {
        // console.log('没有用户信息')
        try {
          // get user info
          await store.dispatch('user/getInfo')
          // console.log('获取用户信息')
          const userInfo = await store.dispatch('user/getInfo')
          // console.log('获取用户数据成功', userInfo)
          next()
        } catch (error) {
          // remove token and go to login page to re-login
@@ -52,6 +61,7 @@
      next()
    } else {
      // other pages that do not have permission to access are redirected to the login page.
      // next()
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
src/router/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue'
import Router from 'vue-router'
import store from '@/store/index'
Vue.use(Router)
/* Layout */
@@ -33,6 +33,7 @@
export const constantRoutes = [
  {
    path: '/login',
    name: 'login',
    component: () => import('@/views/login/index'),
    hidden: true
  },
@@ -49,27 +50,27 @@
    redirect: '/home',
    children: [{
      path: 'home',
      name: 'Home',
      name: '主页',
      component: () => import('@/views/home/index'),
      meta: { title: '首页', icon: 'el-icon-house' }
      meta: { title: '首页', icon: 'icon-shouye' }
    }]
  },
  {
    path: '/add_operation',
    component: Layout,
    redirect: '/add_operation/table',
    meta: { title: '入库操作', icon: 'el-icon-edit-outline' },
    meta: { title: '入库操作', icon: 'icon-warehouse' },
    children: [
      {
        path: 'table',
        name: '入库操作',
        component: () => import('@/views/add_operation/index'),
        meta: { title: '入库操作', icon: 'el-icon-edit-outline' }
        meta: { title: '入库操作', icon: 'icon-warehouse' }
      }
    // ,{
    //   path: 'barcode',
    //   component: () => import('@/views/add_operation/barcode'),
    //   meta: { title: '条码打印', icon: 'el-icon-edit-outline' }
    //   meta: { title: '条码打印', icon: 'icon-warehouse' }
    // }
    ]
  },
@@ -77,39 +78,39 @@
    path: '/out_operation',
    component: Layout,
    redirect: '/out_operation/table',
    meta: { title: '出库操作', icon: 'el-icon-box' },
    meta: { title: '出库操作', icon: 'icon-warehouseOut' },
    children: [
      {
        path: 'table',
        name: 'OutOperation',
        name: '出库操作',
        component: () => import('@/views/out_operation/index'),
        meta: { title: '出库操作', icon: 'el-icon-box' }
        meta: { title: '出库操作', icon: 'icon-warehouseOut' }
      }
      // ,{
      //   path: 'manual',
      //   name: 'manual',
      //   component: () => import('@/views/out_operation/manual'),
      //   meta: { title: '手动出库', icon: 'el-icon-box' }
      // },
      // {
      //   path: 'outboundLedger',
      //   name: 'outboundLedger',
      //   component: () => import('@/views/out_operation/outboundLedger'),
      //   meta: { title: '出库台账', icon: 'el-icon-box' }
      // }
    ]
  },
  {
    path: '/outbound',
    component: Layout,
    redirect: '/outbound/book',
    meta: { title: '库存管理', icon: 'el-icon-box' },
    meta: { title: '库存管理', icon: 'icon-biaogeziduan' },
    children: [
      {
        path: 'book',
        name: '收发存管理',
        component: () => import('@/views/outbound/index.vue'),
        meta: { title: '库存管理', icon: 'el-icon-box' }
        meta: { title: '收发存管理', icon: 'icon-kucunguanli' }
      },
      {
        path: 'outboundLedger',
        name: '出库台账',
        component: () => import('@/views/outbound/outboundLedger'),
        meta: { title: '出库台账', icon: 'icon-taizhangzhangbuxinxichaxun' }
      }
      // ,{
      //   path: 'depositoryManagement',
@@ -122,7 +123,7 @@
    path: '/system',
    component: Layout,
    redirect: '/system/user',
    meta: { title: '系统设置', icon: 'el-icon-box' },
    meta: { title: '系统设置', icon: 'icon-yonghuguanli' },
    children: [
      // {
      //   path: 'index',
@@ -131,8 +132,9 @@
      // },
      {
        path: 'user',
        name: '系统设置',
        component: () => import('@/views/system/user'),
        meta: { title: '用户管理', icon: 'el-icon-box' }
        meta: { title: '用户管理', icon: 'icon-yonghuguanli' }
      }
      // ,{
      //   path: 'dict',
@@ -146,7 +148,7 @@
]
const createRouter = () => new Router({
  // mode: 'history', // require service support
  mode: 'history', // require service support
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRoutes
})
@@ -159,4 +161,40 @@
  router.matcher = newRouter.matcher // reset router
}
const getState = ()=> import("@/store/index")
router.beforeEach(async (to, from, next) => {
  // console.log(to,from)
 let state = (await getState()).default.state
  // console.log(state)
  // console.log(to)
  if (to.name === 'login') {
    next()
    return
  }
  // console.log("跳转路由前的判断")
  let flag = false;
  let {openTab} = state.openTab
  // console.log(openTab)
  for (let item of openTab) {
    // console.log(item)
    // console.log("item.name" , item.name)
    // console.log("t0.name",to.name)
    if(item.name === to.name) {
      // console.log('to.path',to.path);
      store.commit('SET_ACTIVE_INDEX',to.path)
      flag = true;
      break;
    }
  }
  if(!flag) {
    // console.log("执行一遍")
    // console.log('to.path',to.path);
    store.commit('ADD_TAB', {route: to.path, name: to.name});
    store.commit('SET_ACTIVE_INDEX', to.path);
  }
  next()
})
export default router
src/settings.js
@@ -6,7 +6,7 @@
   * @type {boolean} true | false
   * @description Whether fix the header
   */
  fixedHeader: false,
  fixedHeader: true,
  /**
   * @type {boolean} true | false
src/store/getters.js
@@ -2,7 +2,13 @@
  sidebar: state => state.app.sidebar,
  device: state => state.app.device,
  token: state => state.user.token,
  refresh: state => state.user.refresh,
  avatar: state => state.user.avatar,
  name: state => state.user.name
  name: state => state.user.name,
  authority: state => state.user.authority,
  user: state => state.user,
  openTab: state => state.openTab,
  allTab: state => state.tableKey.allTab,
  addTab: state => state.tableKey.allTab[0]
}
export default getters
src/store/index.js
@@ -4,6 +4,8 @@
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'
import openTab from './modules/openTab'
import tableKey from './modules/tableKey'
Vue.use(Vuex)
@@ -11,7 +13,9 @@
  modules: {
    app,
    settings,
    user
    user,
    openTab,
    tableKey
  },
  getters
})
src/store/modules/user.js
@@ -1,12 +1,15 @@
import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { login, logout, getInfo, tideLogin } from '@/api/user'
import { getToken, setToken, removeToken, getrefreshToken, setrefreshToken, removerefreshToken } from '@/utils/auth'
import { resetRouter } from '@/router'
var qs = require('qs')
const getDefaultState = () => {
  return {
    token: getToken(),
    refresh: getrefreshToken(),
    name: '',
    avatar: ''
    avatar: '',
    authority: ''
  }
}
@@ -19,23 +22,35 @@
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_REFRESH: (state, refresh) => {
    state.refresh = refresh
  },
  SET_NAME: (state, name) => {
    state.name = name
  },
  SET_AVATAR: (state, avatar) => {
    state.avatar = avatar
  },
  SET_AUTHORITY: (state, authority) => {
    state.authority = authority
  }
}
const actions = {
  // user login
  login({ commit }, userInfo) {
    console.log(userInfo)
    const { username, password } = userInfo
    console.log(typeof username)
    return new Promise((resolve, reject) => {
      login({ username: username.trim(), password: password }).then(response => {
      // login()
      login(qs.stringify({ username: typeof username === 'number' ? username.toString().trim() : username.trim(), password: password })).then(response => {
        const { data } = response
        console.log(data)
        commit('SET_TOKEN', data.token)
        commit('SET_REFRESH', data.refresh)
        setToken(data.token)
        setrefreshToken(data.refresh)
        resolve()
      }).catch(error => {
        reject(error)
@@ -47,16 +62,20 @@
  getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response
        const { data, message } = response
        console.log(response)
        if (response.code === 10010) {
          resolve(message)
        }
        if (!data) {
          return reject('Verification failed, please Login again.')
        }
        const { name, avatar } = data
        const { name, avatar, authority } = data
        commit('SET_NAME', name)
        commit('SET_AVATAR', avatar)
        commit('SET_AUTHORITY', authority)
        resolve(data)
      }).catch(error => {
        reject(error)
@@ -66,15 +85,25 @@
  // user logout
  logout({ commit, state }) {
    console.log('退出登录')
    return new Promise((resolve, reject) => {
      logout(state.token).then(() => {
        removeToken() // must remove  token  first
        resetRouter()
        commit('RESET_STATE')
        resolve()
      }).catch(error => {
        reject(error)
      })
      for (const key in state) {
        state[key] = ''
      }
      removeToken() // must remove  token  first
      removerefreshToken()
      resetRouter()
      commit('RESET_STATE')
      resolve()
      // logout(state.token).then(() => {
      //   removeToken() // must remove  token  first
      //   removerefreshToken()
      //   resetRouter()
      //   commit('RESET_STATE')
      //   resolve()
      // }).catch(error => {
      //   reject(error)
      // })
    })
  },
@@ -85,6 +114,29 @@
      commit('RESET_STATE')
      resolve()
    })
  },
  // flushed Token
  flushedToken({ commit }, newTokens) {
    console.log('刷新token')
    commit('SET_TOKEN', newTokens.token)
    commit('SET_REFRESH', newTokens.refresh)
  },
  tideLogin({ commit }, code) {
    return new Promise((resolve, reject) => {
      tideLogin(code).then(response => {
        const { data } = response
        console.log(data)
        commit('SET_TOKEN', data.token)
        commit('SET_REFRESH', data.refresh)
        setToken(data.token)
        setrefreshToken(data.refresh)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  }
}
src/styles/element-ui.scss
@@ -1,5 +1,10 @@
// cover some element-ui styles
// .el-input{
//   input{
//     background: #fff !important;
//     box-shadow: none !important;
//   }
// }
.el-breadcrumb__inner,
.el-breadcrumb__inner a {
  font-weight: 400 !important;
@@ -47,3 +52,4 @@
.el-range-separator {
  box-sizing: content-box;
}
src/styles/sidebar.scss
@@ -90,17 +90,17 @@
      }
    }
    .el-menu-item{
      height: auto;
      line-height: normal;
      font-size: 12px;
      .sub-el-icon{
        font-size: 36px;
        margin: 12px 0;
      }
      display: flex;
      flex-direction: column;
      align-items: center;
      margin-right: 0;
      // height: auto;
      // line-height: normal;
      // font-size: 12px;
      // .sub-el-icon{
      //   font-size: 36px;
      //   margin: 12px 0;
      // }
      // display: flex;
      // flex-direction: column;
      // align-items: center;
      // margin-right: 0;
      
    }
  }
@@ -108,6 +108,9 @@
  .hideSidebar {
    .sidebar-container {
      width: 54px !important;
      img{
        display: none !important;
      }
    }
    .main-container {
@@ -154,7 +157,7 @@
    .el-menu--collapse {
      .el-submenu {
        &>.el-submenu__title {
          &>span {
          &>span:nth-child(2) {
            height: 0;
            width: 0;
            overflow: hidden;
src/styles/variables.scss
@@ -1,10 +1,13 @@
// sidebar
$menuText:#ddecfd;
$menuText:#bfcbd9;
// $menuActiveText:#409EFF;
$menuActiveText:#fff;
$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
// $subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
$subMenuActiveText:#fff; //https://github.com/ElemeFE/element/issues/12951
$menuBg:#6095FB;
$menuHover:#4283fe;
$menuBg:#304156;
$menuHover:#263445;
$menuHover:#263445;
$subMenuBg:#1f2d3d;
$subMenuHover:#001528;
src/utils/auth.js
@@ -1,7 +1,7 @@
import Cookies from 'js-cookie'
const TokenKey = 'vue_admin_template_token'
const refreshToken = 'refreshToken'
export function getToken() {
  return Cookies.get(TokenKey)
}
@@ -13,3 +13,15 @@
export function removeToken() {
  return Cookies.remove(TokenKey)
}
export function getrefreshToken() {
  return Cookies.get(refreshToken)
}
export function setrefreshToken(token) {
  return Cookies.set(refreshToken, token)
}
export function removerefreshToken() {
  return Cookies.remove(refreshToken)
}
src/utils/request.js
@@ -2,19 +2,23 @@
import { MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import { refresh } from '@/api/user'
import getters from '@/store/getters'
import { setToken, setrefreshToken } from '@/utils/auth'
var qs = require('qs')
// create an axios instance
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
  timeout: 10000 // request timeout
})
// request interceptor
service.interceptors.request.use(
  config => {
    // console.log('请求拦截器===>', config)
    // do something before request is sent
    // console.log(config)
    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
@@ -42,39 +46,48 @@
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  response => {
    const res = response.data
    // if the custom code is not 20000, it is judged as an error.
    if (res.code !== 20000) {
      Message({
        message: res.message || 'Error',
        type: 'error',
        duration: 5 * 1000
      })
      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
        // to re-login
        MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
          confirmButtonText: 'Re-Login',
          cancelButtonText: 'Cancel',
          type: 'warning'
        }).then(() => {
          store.dispatch('user/resetToken').then(() => {
            location.reload()
          })
        })
      }
      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      return res
  async(response) => {
    // console.log(response)
    if (response.headers.requesttype === 'excel') {
      return response
    }
    const res = response.data
    // console.log(store)
    // console.log(store.state.user.refresh)
    if (res.code === 10010) {
      const { data: { token, refresh: refreshToken }} = await refresh(qs.stringify({ refresh: store.state.user.refresh }))
      store.commit('SET_TOKEN', token)
      store.commit('SET_REFRESH', refreshToken)
      //  console.log('重新刷新token成功', token, refreshToken)
      setToken(token)
      setrefreshToken(refreshToken)
      axios.request(response.config)
      // console.log('token刷新', getters.refresh())
      // refresh({ refresh : getters.refresh() })
      // refresh({ refresh : getters.refresh() }).then((res)=>{
      //   console.log(res)
      // })
      return Promise.resolve(res)
    }
    // if (res.code === 10010) {
    //   console.log('token刷新')
    //   refresh({ refresh : getters.refresh() }).then(async (res) => {
    //     console.log(res)
    //     await store.dispatch('flushedToken', res.data)
    //   })
    //   return axios.request(response.config)
    // }
    // console.log(res)
    // if the custom code is not 20000, it is judged as an error.
    return res
  },
  error => {
    console.log(error)
    console.log('err' + error) // for debug
    Message({
      message: error.message,
      message: '错误,请重新尝试',
      // message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
src/utils/validate.js
@@ -15,6 +15,8 @@
 * @returns {Boolean}
 */
export function validUsername(str) {
  const valid_map = ['admin', 'editor']
  return valid_map.indexOf(str.trim()) >= 0
  // const valid_map = ['admin', 'editor']
  // return valid_map.indexOf(str.trim()) >= 0
  console.log(str)
  return Number.isInteger(str)
}
src/views/add_operation/barcode/index.vue
@@ -1,15 +1,167 @@
<template>
  <div class="barcode">
    æ¡ç æ‰“印
<!--绑定id方法-->
<!-- <div id='box'>
   <p>打印内容</p>
</div>
<div v-print='#box'>打印</div> -->
<!--绑定对象方法-->
<div id='printMe'>
  <vue-barcode
  :value="value"
  >不支持vue-barcode</vue-barcode>
   <div>
    <div>产品名称</div>
    <div>数量</div>
    <div>单位</div>
   </div>
   <div>
    <div>时间</div>
    <div>规格</div>
   </div>
</div>
<div v-for="(item,index) in table" :key="index">
  {{item}}
</div>
<el-button @click="showCode">生成条形码</el-button>
<el-button v-print='printObj'>打印</el-button>
<el-input v-show="false" class="input" v-model="value" ref="input"></el-input>
  </div>
</template>
<script>
export default {
   import VueBarcode from 'vue-barcode'
export default{
   data(){
      return {
         printObj:{
            id: "printMe", // æ‰“印的区域
            // preview: false, // é¢„览工具是否启用
            previewTitle: '打印条码', // é¢„览页面的标题
            popTitle: '', // æ‰“印页面的页眉
            previewBeforeOpenCallback(vue) {
              console.log('正在加载预览窗口')
            },
            previewOpenCallback(vue) {
              console.log('已经加载完预览窗口')
            },
            clickMounted: (vue) => {
              console.log("触发点击打印回调");
              vue.isShowPrint = true  //弹框显示条码
            },
            beforeOpenCallback(vue) {
              console.log('打开之前',vue.barcodeNum)
            },
            openCallback (vue) {
              vue.isShowPrint = false  // å…³é—­æ¡ç æ˜¾ç¤ºå¼¹æ¡†
              console.log('执行了打印',vue.barcodeNum)
            },
         },
         value: '',
         table:[]
      }
   },
   components: { VueBarcode },
   mounted() {
    this.makeCode('1234567891234567')
    this.addScanMonitor()
   },
   methods: {
    // ç›‘听扫描
    showCode() {
      this.makeCode('1234567891234567')
// window.document.onkeypress=undefined
    },
    addScanMonitor() {
      window.document.onkeypress = e => {
        console.log(e)
        if (window.event) { // IE
          this.nextCode = e.keyCode
        } else if (e.which) { // Netscape/Firefox/Opera
          this.nextCode = e.which
        }
        if (e.which === 13) { // é”®ç›˜å›žè½¦äº‹ä»¶
          if (this.code.length < 3) return // æ‰«ç æžªçš„速度很快,手动输入的时间不会让code的长度大于2,所以这里不会对扫码枪有效
          console.log('扫码结束,条形码:', this.code)
          this.table.push(this.code)
          this.scanningForm.scanCode = this.code
          this.lastCode = ''
          this.lastTime = ''
          this.handleSubmitScanning()
          return
        }
        this.nextTime = new Date().getTime()
        if (!this.lastTime && !this.lastCode) {
          this.code = '' // æ¸…空上次的条形码
          // ç»§ç»­æ‰«æä¸€ä¸‹æ¡å‰å…³é—­å¼¹çª—
          // this.handleCloseTipsVisible()
          this.code += e.key
          console.log('扫码开始---', this.code)
        }
        if (this.lastCode && this.lastTime && this.nextTime - this.lastTime > 500) { // å½“扫码前有keypress事件时,防止首字缺失
          this.code = e.key
          console.log('防止首字缺失。。。', this.code)
        } else if (this.lastCode && this.lastTime) {
          this.code += e.key
          console.log('扫码中。。。', this.code)
        }
        this.lastCode = this.nextCode
        this.lastTime = this.nextTime
      }
    },
    makeCode(msg) {
      // let obj = {jack: '1212'}
     this.value = msg
    }
   }
}
</script>
<style>
<style lang="scss">
  #printMe{
  // height: 4cm;
  width: 8cm;
  display: flex;
  flex-direction: column;
  text-align: center;
  img{
    display: inline-block;
    text-align: center;
    width: 6cm;
    height: 2cm;
  }
  >div{
    width: 100%;
    display: flex;
    >div{
      flex: 1;
      // height: 30px;
      border: 1px solid #ddd;
    }
  }
}
@media print {
  @page {
    size: 8cm 4cm !important;
    // margin: 0cm;
    // padding: 0cm;
    // size: portrait;
    // border: 1px solid #ddd;
  }
  #printMe{
    display: block;
    width: 100%;
      overflow: hidden;
    }
  }
</style>
src/views/add_operation/index.vue
@@ -1,90 +1,164 @@
<template>
  <div class="addOperation">
    <div class="addOperation-main">
      <!-- <el-form v-model="statusType" ref="queryForm" size="small" :inline="true" label-width="68px">
            <el-form-item label="入库状态">
           <el-radio-group v-model="inStatus">
            <el-radio-button label="全部"></el-radio-button>
            <el-radio-button label="已入库"></el-radio-button>
            <el-radio-button label="已出库"></el-radio-button>
          </el-radio-group>
            </el-form-item>
            <el-form-item label="入库类型" prop="phonenumber">
             <el-radio-group v-model="inType">
            <el-radio-button label="条码打印"></el-radio-button>
          </el-radio-group>
          </el-form-item>
          <el-form-item label="条码打印">
            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">新增条码打印</el-button>
          </el-form-item>
      </el-form> -->
     <el-row type="flex" align="middle" class="main-top">
      <el-col :span="2"><el-button type="primary">新增入库</el-button></el-col>
      <el-col :span="20">
        <TableSearch></TableSearch>
      </el-col>
      <el-col :span="2"><el-button>条码打印</el-button></el-col>
     </el-row>
    <el-table
      :stripe="true"
      :data="tableData"
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
      :border="true"
      header-row-class-name="table-header"
    >
      <el-table-column
        prop="date"
        label="序号">
      </el-table-column>
      <el-table-column
        prop="name"
        label="产品编码">
      </el-table-column>
      <el-table-column
        prop="address"
        label="产品名称">
      </el-table-column>
      <el-table-column
        prop="date"
        label="规格型号">
      </el-table-column>
      <el-table-column
        prop="date"
        label="单位">
      </el-table-column>
      <el-table-column
        prop="date"
        label="入库数量">
      </el-table-column>
      <el-table-column
        prop="date"
        label="入库人">
      </el-table-column>
      <el-table-column
        prop="date"
        label="入库日期">
      </el-table-column>
    </el-table>
    </div>
    <div class="addOperation-foot">
      <el-pagination
      :current-page="searchModel.pageNo"
      :page-sizes="[10, 15, 20, 25]"
      :page-size="searchModel.pageSize"
      layout="->, total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      <el-row type="flex" align="middle" class="main-top">
        <el-col :span="2"><el-button icon="el-icon-plus" type="primary" @click="addOperation">新增入库</el-button></el-col>
        <el-col :span="20">
          <TableSearch :show="true" :excel-name="'入库表'" :file="file" :get-list="getList" :search-data="searchData" :search-params="searchModel" :options="options" />
        </el-col>
        <el-col :span="2"><el-button icon="iconfont icon-24px " @click="printFormVisible = true">条码打印</el-button></el-col>
      </el-row>
      <el-table
        :row-class-name="onTableRowClassName"
        :row-style="{height:0+'px'}"
        :cell-style="{padding:8+'px',textAlign: 'center'}"
        :header-cell-style="{borderRight:'0px',textAlign: 'center',background:'#52626F',color:'#fff', height:'10px', padding:'0px'}"
        :stripe="true"
        :data="tableData"
        :border="true"
        header-row-class-name="table-header"
      >
    </el-pagination>
        <el-table-column
          label="序号"
        >
          <template v-slot="scope">
            {{ (addPageParams.pageNo-1) * addPageParams.pageSize + scope.$index + 1 }}
          </template>
        </el-table-column>
        <el-table-column
          v-for="(item, index) in getKeys()"
          v-if="item.show"
          :key="index"
          :prop="item.prop"
          :label="item.name"
        />
      </el-table>
      <div class="addOperation-foot">
        <el-pagination
          :current-page="searchModel.pageNo"
          :page-sizes="[10, 15, 20, 25]"
          :page-size="searchModel.pageSize"
          layout="->, total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </div>
    <el-dialog title="新增入库" :visible.sync="addFormVisible" @close="addFormClose">
      <el-form :model="addParams" label-position="left">
        <el-table
          :height="250"
          :max-height="250"
          :row-class-name="onTableRowClassName"
          :row-style="{height:0+'px'}"
          :cell-style="{padding:8+'px',textAlign: 'center'}"
          :header-cell-style="{borderRight:'0px',textAlign: 'center',background:'#52626F',color:'#fff', height:'10px', padding:'0px'}"
          :stripe="true"
          :border="true"
          header-row-class-name="table-header"
          :data="this.addTable.slice(0, addPageParams.pageSize)"
        >
          <!-- <el-table-column property="addPerson" label="序号" >
          </el-table-column> -->
          <el-table-column property="productCode" label="产品编码" />
          <el-table-column property="productName" label="产品名称" />
          <el-table-column property="productModel" label="规格型号" />
          <el-table-column property="unit" label="单位" />
          <el-table-column property="incomingQuantity" label="入库数量" />
          <el-table-column property="addPerson" label="入库人" />
          <!-- <el-table-column property="address" label="入库日期"></el-table-column> -->
        </el-table>
        <div :style="{display: 'flex',justifyContent:'center',marginTop: '10px'}">
          <el-pagination
            :current-page="addPageParams.pageNo"
            :page-sizes="[3, 4, 5, 6]"
            :page-size="addPageParams.pageSize"
            layout="->, total, sizes, prev, pager, next, jumper"
            :total="addTable.length"
            @size-change="inHandleSizeChange"
            @current-change="inHandleCurrentChange"
          />
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="storage">ç¡® å®š</el-button>
        <el-button @click="addFormVisible = false">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
    <el-dialog title="条码打印" :visible.sync="printFormVisible">
      <el-form :model="printParams" label-position="left">
        <el-row :gutter="20">
          <el-col>
            <el-form-item label="产品名称/规格:" :label-width="formLabelWidth">
              <el-cascader
                v-model="chooseTypeName"
                :options="scanTypeNameOptions"
                @change="handleChange"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col>
            <el-form-item label="产品编码:" :label-width="formLabelWidth">
              <el-input :value="printParams.productCode" :disabled="true" autocomplete="off" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="单位:" :label-width="formLabelWidth">
              <el-input v-model="printParams.unit" autocomplete="off" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="入库数量:" :label-width="formLabelWidth">
              <el-input v-model="printParams.incomingQuantity" type="number" autocomplete="off" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="print">ç¡® å®š</el-button>
        <el-button @click="printFormVisible = false">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
    <el-dialog :visible.sync="printVisible" @close="printFormClose">
      <div class="printMian">
        <div id="printMe">
          <vue-barcode :height="50" :width="2" :value="code" />
          <div>
            <div>{{ printParams.productName }}</div>
            <div>{{ printParams.incomingQuantity }}</div>
            <div>{{ printParams.unit }}</div>
          </div>
          <div>
            <div :style="{flex:'2', paddingRight:'1px'}">2022-01-01 10:00</div>
            <div>{{ printParams.productModel }}</div>
          </div>
        </div>
      </div>
      <div class="btn" :style="{display: 'flex',justifyContent: 'center'}">
        <el-button v-print="printObj" :style="{width:'8cm',margin:'10px'}" type="primary">打印</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { getList } from '@/api/table'
import { getList, file, addCache, selectCache, add } from '@/api/addOperation'
import { selectAllName } from '@/api/productName'
import { selectAllModel } from '@/api/productModel'
import { mapGetters } from 'vuex'
import TableSearch from '@/components/TableSearch'
import VueBarcode from 'vue-barcode'
export default {
  filters: {
    statusFilter(status) {
@@ -98,86 +172,278 @@
  },
  data() {
    return {
      pickerOptions: {
          shortcuts: [{
            text: '最近一周',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
              picker.$emit('pick', [start, end]);
            }
          }, {
            text: '最近一个月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
              picker.$emit('pick', [start, end]);
            }
          }, {
            text: '最近三个月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
              picker.$emit('pick', [start, end]);
            }
          }]
      printObj: {
        id: 'printMe', // æ‰“印的区域
        // preview: false, // é¢„览工具是否启用
        previewTitle: '打印条码', // é¢„览页面的标题
        popTitle: '', // æ‰“印页面的页眉
        previewBeforeOpenCallback(vue) {
          console.log('正在加载预览窗口')
        },
      inType: '',
      inStatus: '',
      deptName: '',
      statusType: {},
      queryParams: {
        encode: '',
        type: '',
        depositor: ''
        previewOpenCallback(vue) {
          console.log('已经加载完预览窗口')
        },
        clickMounted: (vue) => {
          console.log('触发点击打印回调')
          // vue.isShowPrint = true // å¼¹æ¡†æ˜¾ç¤ºæ¡ç 
        },
        beforeOpenCallback(vue) {
          console.log('打开之前', vue.barcodeNum)
        },
        openCallback(vue) {
          // vue.isShowPrint = false // å…³é—­æ¡ç æ˜¾ç¤ºå¼¹æ¡†
          // æ¸…空条码打印数据
          vue.printFormVisible = false
          vue.printVisible = false
          vue.chooseTypeName = ''
          for (const key in vue.printParams) {
            vue.printParams[key] = ''
          }
          console.log('执行了打印', vue.barcodeNum)
        }
      },
      printVisible: false,
      file,
      getList,
      options: [],
      chooseTypeName: {},
      scanData: {},
      scanTypeNameOptions: [],
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 10
        pageSize: 10,
        endTime: '',
        productModel: '',
        startTime: ''
      },
      tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 å¼„'
      }, {
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 å¼„'
      }, {
        date: '2016-05-01',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1519 å¼„'
      }, {
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 å¼„'
      }, {
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 å¼„'
      }, {
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 å¼„'
      }]
      tableData: [],
      addFormVisible: false,
      printFormVisible: false,
      printParams: {
        addPerson: '',
        incomingQuantity: '',
        productModelId: '',
        productNameId: '',
        unit: '',
        productCode: ''
      },
      showAddTable: [],
      addTable: [],
      addCodeTable: [],
      addParams: {
        name: '', // äº§å“åç§°
        specs: '', // äº§å“è§„æ ¼
        unit: '', // å•位
        number: '', // æ•°é‡
        depositor: '', // å…¥åº“人,可以为入库人id
        date: '' // æ—¶é—´
      },
      formLabelWidth: '120px',
      addPageParams: {
        pageNo: 1,
        pageSize: 3
      },
      code: ''
    }
  },
  computed: {
    ...mapGetters([
      'sidebar',
      'avatar',
      'name',
      'addTab'
    ])
  },
  watch: {
    addFormVisible(to) {
      if (!to) {
        this.addTable = []
        this.addCodeTable = []
        window.document.onkeypress = undefined
      }
    }
  },
  created() {
    this.fetchData()
    this.setOptions()
    // console.log(this.$route,this.$router)
  },
  components: {
    TableSearch
    TableSearch,
    VueBarcode
  },
  mounted() {
    console.log(this.addTab[0])
  },
  beforeDestroy() {
    window.document.onkeypress = null
  },
  methods: {
    getKeys() {
      return this.$store.state.tableKey.allTab[0].keys
    },
    addScanMonitor() {
      window.document.onkeypress = e => {
        console.log(e)
        if (window.event) { // IE
          this.nextCode = e.keyCode
        } else if (e.which) { // Netscape/Firefox/Opera
          this.nextCode = e.which
        }
        if (e.which === 13) { // é”®ç›˜å›žè½¦äº‹ä»¶
          console.log(new Date().getTime())
          if (new Date().getTime() - this.lastTime > 40) {
            return this.$message.error('扫码时不可通过键盘输入')
          }
          // if (this.code.length < 3) return // æ‰«ç æžªçš„速度很快,手动输入的时间不会让code的长度大于2,所以这里不会对扫码枪有效
          console.log('扫码结束,条形码:', this.code)
          // å‘送请求
          if (this.addCodeTable.includes(this.code)) {
            this.$message.error('请勿重复扫描')
            this.handleSubmitScanning()
            return
          }
          selectCache({ code: this.code }).then(res => {
            // é€šè¿‡æ‰«ææ¡ç æŸ¥è¯¢äº§å“ä¿¡æ¯åŠ å…¥å…¥åº“æ•°ç»„ä¸­
            this.$message.success(`${this.code}扫描成功`)
            res.data.addPerson = this.name
            console.log(res, this.addCodeTable)
            this.addTable.push(res.data)
            this.addCodeTable.push(this.code)
          })
          this.scanningForm.scanCode = this.code
          this.lastCode = ''
          this.lastTime = ''
          this.handleSubmitScanning()
          return
        }
        this.nextTime = new Date().getTime()
        if (!this.lastTime && !this.lastCode) {
          this.code = '' // æ¸…空上次的条形码
          // ç»§ç»­æ‰«æä¸€ä¸‹æ¡å‰å…³é—­å¼¹çª—
          // this.handleCloseTipsVisible()
          this.code = this.code + '' + e.key
          console.log('扫码开始---', this.code)
        }
        if (this.lastCode && this.lastTime && this.nextTime - this.lastTime > 500) { // å½“扫码前有keypress事件时,防止首字缺失
          this.code = e.key
          console.log('防止首字缺失。。。', this.code)
        } else if (this.lastCode && this.lastTime) {
          this.code = this.code + '' + e.key
          console.log('扫码中。。。', this.code)
        }
        this.lastCode = this.nextCode
        this.lastTime = this.nextTime
      }
    },
    // å…³é—­æ‰«æå…¥åº“弹窗
    addFormClose() {
      console.log('清空数据')
      // æ¸…空数据
      this.addTable = []
      this.addCodeTable = []
    },
    // ç‚¹å‡»æ–°å¢žå…¥åº“
    addOperation() {
      this.addFormVisible = true
      this.addScanMonitor()
    },
    printFormClose() {
      for (const key in this.printParams) {
        this.printParams[key] = ''
      }
      this.chooseTypeName = ''
    },
    async setOptions() {
      const { data: nameRes } = await selectAllName()
      // console.log(nameRes)
      const nameArr = nameRes.productNames.map(item => {
        return { value: item.id, label: item.productName }
      })
      for (const nameItem of nameArr) {
        const { data } = await selectAllModel({ productNameId: nameItem.value })
        // console.log(data)
        this.options = [...this.options, ...data.models]
        nameItem.children = data.models.map(item => {
          return { value: item.id, label: item.productModel, productCode: item.productCode }
        })
      }
      this.options = this.options.map(item => {
        return { label: item.productModel, value: item.productModel, productCode: item.productCode }
      })
      this.scanTypeNameOptions = nameArr
      // console.log(this.options)
      // console.log(nameArr)
    },
    searchData(res) {
      console.log(res)
      const { row, total, productModel, startTime, endTime } = res
      this.tableData = row
      this.total = total
      this.searchModel.productModel = productModel
      this.searchModel.startTime = startTime
      this.searchModel.endTime = endTime
    },
    handleChange(value) {
      console.log(value)
      this.printParams.productNameId = value[0]
      this.printParams.productModelId = value[1]
      console.log(this.scanTypeNameOptions)
      const nameObj = this.scanTypeNameOptions.filter(item => item.value === value[0])
      console.log(nameObj[0].label)
      this.printParams.productName = nameObj[0].label
      const children = nameObj[0].children
      this.printParams.productCode = children.filter(item => item.value === value[1])[0].productCode
      console.log(children.filter(item => item.value === value[1])[0].label)
      this.printParams.productModel = children.filter(item => item.value === value[1])[0].label
    },
    onTableRowClassName({ row, rowIndex }) {
      if (rowIndex % 2 != 0) {
        return 'onAcitve'
      } else {
        return ''
      }
    },
    storage() {
      // è¾“出入库参数
      if (this.addCodeTable.length === 0) return this.$message.error('请先扫描数据入库')
      add({ code: this.addCodeTable, addPerson: this.name }).then(() => {
        this.addTable = []
        this.addCodeTable = []
        this.fetchData()
        this.addFormVisible = false
        this.$message.success('入库成功')
      })
    },
    async print() {
      console.log('生成条码')
      this.printParams.addPerson = this.name
      console.log(this.printParams)
      const res = await addCache(this.printParams)
      this.code = res.message
      this.printFormVisible = false
      // for( key in this.printParams){
      //   this.printParams[key] = ''
      // }
      this.printVisible = true
    },
    fetchData() {
      this.listLoading = true
      getList().then(response => {
        this.list = response.data.items
      const obj = {}
      const arr = Object.keys(this.searchModel).filter(key => this.searchModel[key])
      arr.forEach(item => obj[item] = this.searchModel[item])
      console.log(obj)
      getList(obj).then(response => {
        this.tableData = response.data.row
        this.total = response.data.total
        this.listLoading = false
        // console.log(this.tableData)
      })
    },
    handleSizeChange(val) {
@@ -185,31 +451,110 @@
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`)
      this.searchModel.pageNo = val
      this.fetchData()
    },
    inHandleSizeChange(val) {
      console.log(`每页 ${val} æ¡`)
    },
    inHandleCurrentChange(val) {
      console.log(`当前页: ${val}`)
      this.addPageParams.pageNo = val
      // console.log(this.addTable.slice((this.addPageParams.pageSize * (val - 1)), (this.addPageParams.pageSize * (val - 1)) + this.addPageParams.pageSize))
    }
  }
}
</script>
<style lang="scss" scoped>
.printMian{
  display: flex;
  justify-content: center;
  .btn{
    width: 100%;
    display: flex;
    justify-content: center;
    .el-button{
      width: 100%;
    }
  }
}
@import '../../styles/variables.scss';
  #printMe{
  // height: 4cm;
  // visibility:hidden;
  width: 8cm;
  display: flex;
  flex-direction: column;
  text-align: center;
  img{
    align-items: center;
    display: inline-block;
    text-align: center;
    width: 8cm;
    height: 1.5cm;
  }
  >div{
    width: 100%;
    display: flex;
    >div{
      flex: 1;
      // height: 30px;
      border: 1px solid #ddd;
      padding: 2px;
    }
  }
}
@media print {
  @page {
    size: 8cm 4cm !important;
    // margin: 0cm;
    // padding: 0cm;
    // size: portrait;
    // border: 1px solid #ddd;
  }
  }
.addOperation {
 min-height: calc(100vh - 50px);
 min-height: calc(100vh - 100px);
 max-height: calc(100vh - 100px);
 padding: 25px;
// margin: 25px;
 background: $mainBg;
 display: flex;
 flex-direction: column;
 .dialog-footer{
  text-align: center;
 }
 .addOperation-main{
  background: #fff;
  padding: 20px;
  flex: 80%;
  display: flex;
  flex-direction: column;
  .main-top{}
  .table-header{
    background: #6095FB;
  }
 }
 .addOperation-foot{
  margin-top: 25px;
  .el-pagination{
    display: flex;
    justify-content: center;
  ::v-deep .el-table{
    flex: 1;
   ::v-deep .onAcitve td{
    background-color: #F2F2F2 !important;
  }
  }
    .addOperation-foot{
    // flex: 20%;
    margin-top: 25px;
    .el-pagination{
      display: flex;
      justify-content: right;
    }
  }
 }
}
</style>
src/views/home/index.vue
@@ -1,87 +1,194 @@
<!-- eslint-disable vue/attributes-order -->
<template>
  <div class="dashboard-container">
      <div class="home-annular-list">
        <div class="annular-item" v-for="item in 4" :key="item">
        </div>
    <el-empty
      description="暂无数据"
      v-if="chartData.PieData&&chartData.DailyTotal&&
        chartData.WeekNumData&&chartData.ExceedThirtyDay.length!=0
      "
    />
    <template v-else>
      <div class="home-annular-list" v-show="chartData.PieData">
        <div v-for="item in 4" :key="item" class="annular-item " :class="'pie'+item" />
      </div>
      <div class="home-line-bar">
        <div class="left">
          <div class="top">1</div>
          <div class="bottom">1</div></div>
          <div class="top" />
          <div class="bottom">
            ä¸´è¿‘30天库存
            <div>
              <el-table
                :data="exceedThirtyDay"
                stripe
                style="width: 100%"
              >
                <el-table-column
                  prop="product_name"
                  label="产品名称"
                />
                <el-table-column
                  prop="RemainingDays"
                  label="产品库存"
                />
                <el-table-column
                  prop="product_code"
                  label="产品编码"
                />
                <el-table-column
                  prop="product_model"
                  label="产品规格"
                />
                <el-table-column
                  prop="unit"
                  label="单位"
                />
              </el-table>
            </div>
          </div>
        </div>
        <div class="right">
         1
          <div />
        </div>
      </div>
    </template>
  </div>
</template>
<script>
import { getList } from '@/api/home'
import { mapGetters } from 'vuex'
import * as echarts from 'echarts'
export default {
  name: 'Home',
  data() {
    return {
      exceedThirtyDay: [],
      show: true,
      chartData: {}
    }
  },
  computed: {
    ...mapGetters([
      'name'
    ])
  },
  mounted() {
    console.log(echarts)
    // console.log(echarts)
    this.echartsInit()
    // åˆ·æ–°æ—¶ä»¥å½“前路由做为tab加入tabs
    // å½“前路由不是首页时,添加首页以及另一页到store里,并设置激活状态
    // å½“当前路由是首页时,添加首页到store,并设置激活状态
    if (this.$route.path !== '/' && this.$route.path !== '/home') {
      console.log('1')
      this.$store.commit('ADD_TAB', { route: '/home', name: '主页' })
      this.$store.commit('ADD_TAB', { route: this.$route.path, name: this.$route.name })
      this.$store.commit('SET_ACTIVE_INDEX', this.$route.path)
    }
    // else {
    //   console.log('2');
    //   this.$store.commit('ADD_TAB', {route: '/home', name: 'home'});
    //   this.$store.commit('SET_ACTIVE_INDEX', '/home');
    //   this.$router.push('/');
    // }
    console.log(this.$store.state)
  },
  created() {
    this.echartsInit()
  },
  methods: {
    echartsInit() {
      let boxArr = document.querySelectorAll(".annular-item")
      boxArr.forEach((item) => {
        echarts.init(item).setOption({
          legend: {
            type: 'scroll',
            align: 'left',
            orient: 'vertical',
            x: 'right',
            y: 'center'
          },
          title: {
            text: '饼图纹理',
            textStyle: {
              color: '#235894'
            }
          },
          tooltip: {
            trigger: 'item'
          },
  series: [
    {
      name: 'Access From',
      type: 'pie',
      radius: ['40%', '70%'],
      center: ['25%', '50%'],
      avoidLabelOverlap: false,
      itemStyle: {
        borderRadius: 5,
        borderColor: '#fff',
        borderWidth: 2
      },
      label: {
        show: false,
        position: 'left'
      },
      labelLine: {
        show: false
      },
      data: [
        { value: 1048, name: 'Search Engine' },
        { value: 735, name: 'Direct' },
        { value: 580, name: 'Email' },
        { value: 484, name: 'Union Ads' },
        { value: 300, name: 'Video Ads' }
      ]
    }
  ]
})
    getData() {
    },
    getPie(PieData, className) {
      console.log(className)
      const box = document.querySelector(className)
      echarts.init(box).setOption({
        legend: {
          type: 'scroll',
          align: 'left',
          orient: 'vertical',
          x: 'right',
          y: 'center'
        },
        title: {
          text: '饼图纹理',
          textStyle: {
            color: '#235894'
          }
        },
        tooltip: {
          trigger: 'item'
        },
        series: [
          {
            name: PieData.datetime,
            type: 'pie',
            radius: ['40%', '70%'],
            center: ['25%', '50%'],
            avoidLabelOverlap: false,
            itemStyle: {
              borderRadius: 5,
              borderColor: '#fff',
              borderWidth: 2
            },
            label: {
              show: false,
              position: 'left'
            },
            labelLine: {
              show: false
            },
            data: [
              { value: PieData.addNum, name: '入库数目' },
              { value: PieData.outNum, name: '出库数目' },
              { value: PieData.beginningMonth, name: '月初库存' },
              { value: PieData.endOfMonth, name: '月末库存' }
            ]
          }
        ]
      })
      let letTop = document.querySelector(".top")
    },
    getLine(DailyTotal) {
      const right = document.querySelector('.right')
      echarts.init(right).setOption({
        legend: {
          x: 'center',
          slected: true
        },
        title: {
          text: '仓库统计',
          textStyle: {
            color: '#235894'
          }
        },
        tooltip: {
          trigger: 'item'
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: DailyTotal?.xList
        },
        yAxis: {
          type: 'value'
        },
        series: [
          {
            data: DailyTotal?.yList,
            type: 'line',
            smooth: true,
            name: '每日总计',
            areaStyle: {}
          }
        ]
      })
    },
    getBar(WeekNumData) {
      const letTop = document.querySelector('.top')
      echarts.init(letTop).setOption({
        grid: {
          left: '3%',
@@ -90,75 +197,52 @@
          containLabel: true
        },
        legend: {
            x: 'center',
            y: 'top'
          x: 'center',
          y: 'top'
        },
        title: {
          text: '仓库统计',
          textStyle: {
            color: '#235894'
          }
        },
        tooltip: {
          trigger: 'item'
        },
        xAxis: {
          type: 'category',
          data: WeekNumData.xList
        },
        yAxis: {
          type: 'value'
        },
        series: [
          {
            data: WeekNumData.yOutList,
            name: '出库数量',
            type: 'bar'
          },
          title: {
            text: '仓库统计',
            textStyle: {
              color: '#235894'
            }
          },
          tooltip: {
            trigger: 'item'
          },
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [120, 200, 150, 80, 70, 110, 130],
      name: '出库数量',
      type: 'bar'
          {
            data: WeekNumData.yEnterList,
            name: '入库数量',
            type: 'bar'
          }
        ]
      })
    },
    {
      data: [220, 210, 80, 110, 30, 80, 130],
      name: '入库数量',
      type: 'bar'
    }
  ]
})
    async echartsInit() {
      const res = await getList()
      const { data } = res
      this.chartData = { ...data }
      console.log(this.chartData)
      data.PieData?.forEach((item, index) => {
        console.log(item)
        this.getPie(item, '.pie' + (index + 1))
      })
      let right = document.querySelector(".right")
      echarts.init(right).setOption({
        legend: {
            x: 'center',
            slected: true
          },
          title: {
            text: '仓库统计',
            textStyle: {
              color: '#235894'
            }
          },
          tooltip: {
            trigger: 'item'
          },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [820, 932, 901, 934, 1290, 1330, 1320],
      type: 'line',
      smooth: true,
      name: '数据1',
      areaStyle: {}
    }
  ]
})
      this.getBar(data.WeekNumData)
      this.getLine(data.DailyTotal)
      this.exceedThirtyDay = data.ExceedThirtyDay
    }
  }
}
@@ -178,15 +262,14 @@
  }
}
.home-annular-list{
  margin: 12px;
  margin: 12px 0;
  display: flex;
  justify-content: space-between;
  .annular-item{
    width:   350px;
    height: 240px;
    width:  300px;
    height: 200px;
    border-radius: 10px;
    padding: 25px;
    padding: 20px;
    background: #fff;
    // margin: 0 12px;
  }
@@ -223,6 +306,8 @@
      background: #fff;
      padding: 25px;
      border-radius: 10px;
      // max-width: 500px;
      max-height: 328px;
    }
  }
}
src/views/login/index.vue
@@ -4,65 +4,71 @@
      <div class="logo">
        <img src="../../assets/images/logo.png" alt="">
      </div>
      <div>
        |
      </div>
      <div class="logo-title">
        ä¸­å¤©ç§‘技WMS系统
        WMS系统
      </div>
    </div>
    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
      <div class="title-container">
        <div>
        <div class="title">系统登录</div>
        <div class="scan-icon">小图标</div>
    <div class="logo-main">
      <div class="main-img">
        <img src="@/assets/images/loginbg.png" alt="">
      </div>
      <!-- <el-form ref="loginForm" :model="loginForm" :rules="loginRules" :rules="loginRules" class="login-form" auto-complete="on" label-position="left"> -->
      <el-form ref="loginForm" :status-icon="true" :model="loginForm"  class="login-form" auto-complete="on" label-position="left">
        <div v-show="!showCode" class="title-container">
          <div>
            <div class="title">登录</div>
            <div class="scan-icon iconfont icon-saoyisao" />
          </div>
        </div>
      </div>
        <el-form-item v-show="!showCode" size="size" prop="username">
          <span class="svg-container">
            <i class="el-icon-user" />
          </span>
          <el-input
            ref="username"
            v-model.number="loginForm.username"
            size="mini"
            placeholder="账号"
            name="username"
      <el-form-item prop="username">
        <span class="svg-container">
          <svg-icon icon-class="user" />
        </span>
        <el-input
          ref="username"
          v-model="loginForm.username"
          placeholder="Username"
          name="username"
          type="text"
          tabindex="1"
          auto-complete="on"
        />
      </el-form-item>
            tabindex="1"
            auto-complete="on"
          />
        </el-form-item>
      <el-form-item prop="password">
        <span class="svg-container">
          <svg-icon icon-class="password" />
        </span>
        <el-input
          :key="passwordType"
          ref="password"
          v-model="loginForm.password"
          :type="passwordType"
          placeholder="Password"
          name="password"
          tabindex="2"
          auto-complete="on"
          @keyup.enter.native="handleLogin"
        />
        <span class="show-pwd" @click="showPwd">
          <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
        </span>
      </el-form-item>
        <el-form-item v-show="!showCode" size="size" prop="password">
          <span class="svg-container">
            <i class="el-icon-lock" />
          </span>
          <el-input
            :key="passwordType"
            ref="password"
            v-model="loginForm.password"
            size="mini"
            :type="passwordType"
            placeholder="密码"
            name="password"
            show-password
            tabindex="2"
            auto-complete="on"
            @keyup.enter.native="handleLogin"
          />
          <span class="show-pwd" @click="showPwd">
            <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
          </span>
        </el-form-item>
      <el-form-item>
        <el-checkbox v-model="checked">自动登录</el-checkbox>
        <el-checkbox v-model="checked">忘记密码</el-checkbox>
      </el-form-item>
      <div class="login">
        <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登录</el-button>
      </div>
    </el-form>
        <el-form-item>
          <div v-show="!showCode" class="login">
            <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登录</el-button>
          </div>
        </el-form-item>
        <div v-show="showCode" class="code">
          <img src="../../assets/images/code.png">
        </div>
      </el-form>
    </div>
  </div>
</template>
@@ -73,23 +79,28 @@
  name: 'Login',
  data() {
    const validateUsername = (rule, value, callback) => {
      if (!validUsername(value)) {
        callback(new Error('请输入正确的账号!'))
      const reg = /^(?=.*\d).{6,11}$/
      if (!reg.test(value)) {
        callback(new Error('账号由6-10位数字组成,请输入正确的账号!'))
      } else {
        callback()
      }
    }
    const validatePassword = (rule, value, callback) => {
      if (value.length < 6) {
        callback(new Error('请输入6位密码!'))
      // let reg= /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{4,20}$/
      // let reg = /^(?![0-9]+$)(?![A-Z]+$)(?![a-z]+$)[0-9A-Za-z]{6,12}$/
      const reg = /^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{6,12}$/
      if (!reg.test(value)) {
        callback(new Error('密码必须是由6-12位包含大小写字母,数字组合'))
      } else {
        callback()
      }
    }
    return {
      loginForm: {
        username: 'admin',
        password: '111111'
        username: '',
        password: ''
      },
      loginRules: {
        username: [{ required: true, trigger: 'blur', validator: validateUsername }],
@@ -97,7 +108,8 @@
      },
      loading: false,
      passwordType: 'password',
      redirect: undefined
      redirect: undefined,
      showCode: false
    }
  },
  watch: {
@@ -109,6 +121,9 @@
    }
  },
  methods: {
    openCode() {
      this.showCode = true
    },
    showPwd() {
      if (this.passwordType === 'password') {
        this.passwordType = ''
@@ -120,32 +135,35 @@
      })
    },
    handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true
          this.$store.dispatch('user/login', this.loginForm).then(() => {
            this.$router.push({ path: this.redirect || '/' })
            this.loading = false
          }).catch(() => {
            this.loading = false
          })
        } else {
          console.log('error submit!!')
          return false
        }
      console.log('开始登录')
      // debugger
      console.log(this)
      this.loading = true
      this.$store.dispatch('user/login', this.loginForm).then((res) => {
        console.log(res)
        this.$router.push({ path: this.redirect || '/' })
        this.loading = false
      }).catch(() => {
        this.loading = false
      })
    }
  }
}
</script>
<style lang="scss">
<style lang="scss" >
#app .login-container .el-input input:-webkit-autofill {
  box-shadow: none !important;
}
/* ä¿®å¤input èƒŒæ™¯ä¸åè°ƒ å’Œå…‰æ ‡å˜è‰² */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
.login{
  text-align: center;
  .el-button{
    background: #285E77 ;
    border: 2px solid #8AA0AC;
  }
}
$bg:#283443;
$light_gray:#fff;
@@ -161,7 +179,7 @@
.login-container {
  .el-input {
    display: inline-block;
    height: 47px;
    height: 30px;
    width: 85%;
    input {
@@ -169,9 +187,9 @@
      border: 0px;
      -webkit-appearance: none;
      border-radius: 0px;
      padding: 12px 5px 12px 15px;
      padding: 6px 2px 6px 7px;
      color: $cursor;
      height: 47px;
      height: 30px;
      // caret-color: $cursor;
      &:-webkit-autofill {
@@ -186,6 +204,10 @@
    background: rgba(255, 255, 255);
    border-radius: 5px;
    color: #454545;
    margin-bottom: 40px;
    margin-right: 40px;
    margin-left: 40px;
    height: 40px;
    &:nth-child(4){
      // width: 100%;
      // display: flex;
@@ -205,44 +227,81 @@
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee;
::v-deep .el-form-item__content{
  .svg-container{
    text-align: center;
    line-height: 32px;
  }
  // display: flex;
}
.login-container {
  position: relative;
  min-height: 100%;
  width: 100%;
  background: url("../../assets/images/loginbg.png");
  background: #134666;
  background-size: cover;
  overflow: hidden;
  .login-logo{
    position: absolute;
    width: 520px;
    left: 60%;
    top: 25%;
    position: fixed;
    width: 100%;
    left: 0;
    top: 0;
    color: #fff;
    font-size: 30px;
    font-size: 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px;
    background: #0E3757;
    .logo{
      img{
        width: 150px;
        height: 50px;
        width: 80px;
        height: 30px;
      }
    }
    .logo-title{
      margin-left: 20px;
    }
  }
  .login-form {
  .logo-main{
    position: absolute;
    background: #fff;
    border-radius: 25px;
    width: 520px;
    height: 370px;
    padding: 40px;
    max-width: 100%;
    left: 50%;
    top: 50%;
    transform: translateY(-50%);
    left: 60%;
    transform: translate(-50%,-50%);
    width: 1000px;
    height: 400px;
    border-radius: 25px;
    overflow:hidden;
    display: flex;
    // border: 2px solid red;
    .main-img{
      // width: 550px;
      // height: 300px;
      flex: 1;
      height: 400px;
      text-align: center;
      background: #0D3155;
      img{
        width: 400px;
        height: 400px;
      }
    }
    .login-form {
    background: #285E77;
    width: 450px;
    height: 400px;
    padding: 30px;
    overflow: hidden;
    color: #fff;
    .code{
      text-align: center;
      img{
        width: 200px;
        height: 200px;
      }
    }
   }
  }
  .tips {
    font-size: 14px;
    color: #fff;
@@ -256,7 +315,7 @@
  }
  .svg-container {
    padding: 6px 5px 6px 15px;
    padding: 3px 2px 3px 7px;
    color: $dark_gray;
    vertical-align: middle;
    width: 30px;
@@ -265,20 +324,25 @@
  .title-container {
    position: relative;
    // height: 70px;
    // line-height: 70px;
    margin-bottom: 40px;
    .title {
      height: 30px;
      line-height: 30px;
      position: relative;
      // position: absolute;
      left: 50%;
      transform: translate(-50%);
      font-size: 20px;
      color: #454545;
      margin: 0px auto 24px auto;
      color: #fff;
      margin: 0px auto 0 auto;
      display: inline-block;
      // font-weight: bold;
    }
    .scan-icon{
      float: right;
      font-size: 30px;
    }
  }
src/views/out_operation/index.vue
@@ -1,90 +1,285 @@
<template>
  <div class="addOperation">
    <div class="addOperation-main">
      <!-- <el-form v-model="statusType" ref="queryForm" size="small" :inline="true" label-width="68px">
            <el-form-item label="入库状态">
           <el-radio-group v-model="inStatus">
            <el-radio-button label="全部"></el-radio-button>
            <el-radio-button label="已入库"></el-radio-button>
            <el-radio-button label="已出库"></el-radio-button>
          </el-radio-group>
            </el-form-item>
            <el-form-item label="入库类型" prop="phonenumber">
             <el-radio-group v-model="inType">
            <el-radio-button label="条码打印"></el-radio-button>
          </el-radio-group>
          </el-form-item>
          <el-form-item label="条码打印">
            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">新增条码打印</el-button>
          </el-form-item>
      </el-form> -->
     <el-row type="flex" align="middle" class="main-top">
      <el-col :span="2"><el-button type="primary">扫描出库</el-button></el-col>
      <el-col :span="20">
        <TableSearch></TableSearch>
      </el-col>
      <el-col :span="2"><el-button>押运单打印</el-button></el-col>
     </el-row>
    <el-table
      :stripe="true"
      :data="tableData"
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
      :border="true"
      header-row-class-name="table-header"
    >
      <el-table-column
        prop="date"
        label="序号">
      </el-table-column>
      <el-table-column
        prop="name"
        label="产品编码">
      </el-table-column>
      <el-table-column
        prop="address"
        label="产品名称">
      </el-table-column>
      <el-table-column
        prop="date"
        label="规格型号">
      </el-table-column>
      <el-table-column
        prop="date"
        label="单位">
      </el-table-column>
      <el-table-column
        prop="date"
        label="入库数量">
      </el-table-column>
      <el-table-column
        prop="date"
        label="入库人">
      </el-table-column>
      <el-table-column
        prop="date"
        label="入库日期">
      </el-table-column>
    </el-table>
    </div>
    <div class="addOperation-foot">
      <el-pagination
      :current-page="searchModel.pageNo"
      :page-sizes="[10, 15, 20, 25]"
      :page-size="searchModel.pageSize"
      layout="->, total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
  <div class="outOperation">
    <div class="outOperation-main">
      <el-row type="flex" align="middle" class="main-top">
        <el-col :span="2"><el-button type="primary" icon="iconfont icon-saoyisao" @click="scan">新增出库</el-button></el-col>
        <el-col :span="20">
          <TableSearch :show="true" :excel-name="'库存表'" :file="outFile" :get-list="getList" :search-data="searchData" :search-params="searchModel" :options="options" />
        </el-col>
        <!-- <el-col :span="2"><el-button type="primary" @click="printOrder ">打印押运单</el-button></el-col> -->
        <el-col :span="2"><el-button type="primary" :disabled="outTable.length==0" @click="printOrder ">打印押运单</el-button></el-col>
      </el-row>
      <el-table
        class="tableData"
        :row-class-name="onTableRowClassName"
        :row-style="{height:0+'px'}"
        :cell-style="{padding:8+'px',textAlign: 'center'}"
        :header-cell-style="{borderRight:'0px',textAlign: 'center',background:'#52626F',color:'#fff', height:'10px', padding:'0px'}"
        :stripe="true"
        :data="tableData"
        :border="true"
        header-row-class-name="table-header"
        @selection-change="handleSelectionChange"
      >
    </el-pagination>
        <el-table-column
          label="多选"
          type="selection"
          width="55"
        >
        <!-- <el-checkbox></el-checkbox> -->
        </el-table-column>
        <el-table-column
          prop="productCode"
          label="产品编码"
        />
        <el-table-column
          prop="productName"
          label="产品名称"
        />
        <el-table-column
          prop="productModel"
          label="规格型号"
        >
          <template slot="header" slot-scope="scope">
            <span>规格型号</span>
            <span :class="isMerge?'el-icon-sort-up':'el-icon-sort-down'" :style="{marginLeft:'5px'}" @click="merge" />
          </template>
        </el-table-column>
        <el-table-column
          prop="unit"
          label="单位"
        />
        <el-table-column
          prop="incomingQuantity"
          label="入库数量"
        />
        <el-table-column
          prop="addPerson"
          label="入库人"
        />
        <el-table-column
          v-if="!isMerge"
          prop="createTime"
          label="出库日期"
        />
      </el-table>
      <div class="outOperation-foot">
        <el-pagination
          :current-page="searchModel.pageNo"
          :page-sizes="[10, 15, 20, 25]"
          :page-size="searchModel.pageSize"
          layout="->, total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </div>
    <el-dialog title="扫描出库" :visible.sync="outFormVisible">
      <el-form :model="outParams" label-position="left">
        <el-table
          :height="250"
          :max-height="250"
          :row-class-name="onTableRowClassName"
          :row-style="{height:0+'px'}"
          :cell-style="{padding:8+'px',textAlign: 'center'}"
          :header-cell-style="{borderRight:'0px',textAlign: 'center',background:'#52626F',color:'#fff', height:'10px', padding:'0px'}"
          :stripe="true"
          :border="true"
          header-row-class-name="table-header"
          :data="this.outTable.slice(0,outPageParams.length)"
        >
          <el-table-column property="addPerson" label="序号" />
          <el-table-column property="productCode" label="产品编码" />
          <el-table-column property="productNameId" label="产品名称" />
          <el-table-column property="productModelId" label="规格型号" />
          <el-table-column property="unit" label="单位" />
          <el-table-column property="incomingQuantity" label="入库数量" />
          <el-table-column property="addPerson" label="入库人" />
          <!-- <el-table-column property="address" label="入库日期"></el-table-column> -->
        </el-table>
        <div :style="{display: 'flex',justifyContent:'center',marginTop: '10px'}">
          <el-pagination
            :current-page="outPageParams.pageNo"
            :page-sizes="[3, 4, 5, 6]"
            :page-size="outPageParams.pageSize"
            layout="->, total, sizes, prev, pager, next, jumper"
            :total="outTable.length"
            @size-change="outHandleSizeChange"
            @current-change="outHandleCurrentChange"
          />
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="orderFormVisible = true">生成押运单</el-button>
        <el-button @click="outFormVisible = false">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
    <el-dialog title="押运单打印" :visible.sync="orderFormVisible" @close="orderFormClose">
      <div id="order">
        <el-form label-position="right" :model="orderParams">
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="订单号:" :label-width="formLabelWidth">
                <el-input v-model="orderParams.orderNumber" autocomplete="off" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="押运单编号:" :label-width="formLabelWidth">
                <el-input v-model="orderParams.escortNoteNumber" autocomplete="off" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="客户订单号:" :label-width="formLabelWidth">
                <el-input v-model="orderParams.customerOrderNumber" autocomplete="off" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="发货日期:" :label-width="formLabelWidth">
                <el-date-picker
                  v-model="orderParams.createTime"
                  format="yyyy-MM-dd HH:mm"
                  type="datetime"
                  placeholder="选择日期时间"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="客户名称:" :label-width="formLabelWidth">
                <el-input v-model="orderParams.customerName" autocomplete="off" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="发货人:" :label-width="formLabelWidth">
                <el-input v-model="orderParams.consignor" autocomplete="off" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col>
              <el-form-item label="到货地址:" :label-width="formLabelWidth">
                <el-input v-model="orderParams.arrivalAddress" autocomplete="off" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col>
              <el-form-item label="收货联系人:" :label-width="formLabelWidth">
                <el-input v-model="orderParams.receivingContact" autocomplete="off" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col>
              <el-form-item label="手机号:" :label-width="formLabelWidth">
                <el-input v-model="orderParams.cellPhoneNumber" autocomplete="off" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col>
              <el-form-item>
                <el-table
                  :row-class-name="onTableRowClassName"
                  :row-style="{height:0+'px'}"
                  :cell-style="{padding:8+'px',textAlign: 'center'}"
                  :header-cell-style="{borderRight:'0px',textAlign: 'center',background:'#52626F',color:'#fff', height:'10px', padding:'0px'}"
                  :stripe="true"
                  :border="true"
                  :data="outTable"
                >
                  <el-table-column property="productName" label="产品名称" />
                  <el-table-column property="productModel" label="规格型号" />
                  <el-table-column property="unit" label="单位" />
                  <el-table-column property="incomingQuantity" label="发库数量" />
                </el-table>
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="goToPrint">打 å°</el-button>
        <el-button @click="orderFormVisible = false">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
    <el-dialog title="押运单打印" :visible.sync="templateOrderVisible" @close="templateOrderClose">
      <div id="templateOrder" class="templateOrder">
        <h3>押运单</h3>
        <div class="templateOrder-main">
          <div class="main-row">
            <div class="flex-2">订单号:</div>
            <div class="flex-8">{{ orderParams.orderNumber }}</div>
            <div class="flex-2">押运单编号:</div>
            <div class="flex-8">{{ orderParams.escortNoteNumber }}</div>
          </div>
          <div class="main-row">
            <div class="flex-2">客户订单号:</div>
            <div class="flex-8">{{ orderParams.customerOrderNumber }}</div>
            <div class="flex-2">发货日期:</div>
            <div class="flex-8">{{ orderParams.createTime }}</div>
          </div>
          <div class="main-row">
            <div class="flex-2">客户名称:</div>
            <div class="flex-8">{{ orderParams.customerName }}</div>
            <div class="flex-2">发货人:</div>
            <div class="flex-8">{{ orderParams.consignor }}</div>
          </div>
          <div class="main-row">
            <div class="flex-2">到货地址:</div>
            <div class="flex-18">{{ orderParams.arrivalAddress }}</div>
          </div>
          <div class="main-row">
            <div class="flex-2">收货联系人:</div>
            <div class="flex-18">{{ orderParams.receivingContact }}</div>
          </div>
          <div class="main-row">
            <div class="flex-2">手机号:</div>
            <div class="flex-18">{{ orderParams.cellPhoneNumber }}</div>
          </div>
          <div class="main-row">
            <!-- <div class="flex-2">手机号</div> -->
            <div class="flex-18" :style="{'textAlign': 'center'}">
              <h4>产品列表</h4>
            </div>
          </div>
          <div class="main-row">
            <div class="flex-4">产品名称</div>
            <div class="flex-4">规格型号</div>
            <div class="flex-4">单位</div>
            <div class="flex-4">发货数量</div>
          </div>
          <div v-for="item in outTable" :key="item.id" class="main-row">
            <div class="flex-4">{{ item.productName }}</div>
            <div class="flex-4">{{ item.productModel }}</div>
            <div class="flex-4">{{ item.unit }}</div>
            <div class="flex-4">{{ item.incomingQuantity }}</div>
          </div>
        </div>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button v-print="printObj" type="primary">按模板打印</el-button>
        <el-button @click="templateOrderVisible = false">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { getList } from '@/api/table'
import { getList, selectCacheOfIn, outOperation, outFile } from '@/api/addOperation'
import { selectAllName } from '@/api/productName'
import { selectAllModel } from '@/api/productModel'
import TableSearch from '@/components/TableSearch'
import { mapGetters } from 'vuex'
export default {
  filters: {
    statusFilter(status) {
@@ -96,88 +291,302 @@
      return statusMap[status]
    }
  },
  data() {
    return {
      pickerOptions: {
          shortcuts: [{
            text: '最近一周',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
              picker.$emit('pick', [start, end]);
            }
          }, {
            text: '最近一个月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
              picker.$emit('pick', [start, end]);
            }
          }, {
            text: '最近三个月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
              picker.$emit('pick', [start, end]);
            }
          }]
        },
      inType: '',
      inStatus: '',
      deptName: '',
      statusType: {},
      queryParams: {
        encode: '',
        type: '',
        depositor: ''
      },
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 10
      },
      tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 å¼„'
      }, {
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 å¼„'
      }, {
        date: '2016-05-01',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1519 å¼„'
      }, {
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 å¼„'
      }, {
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 å¼„'
      }, {
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 å¼„'
      }]
    }
  },
  created() {
    this.fetchData()
  },
  components: {
    TableSearch
  },
  data() {
    return {
      templateOrderVisible: false,
      outFile,
      printObj: {
        id: 'templateOrder', // æ‰“印的区域
        // preview: true, // é¢„览工具是否启用
        previewTitle: '打印押运单', // é¢„览页面的标题
        previewBeforeOpenCallback(vue) {
          console.log('正在加载预览窗口')
        },
        previewOpenCallback(vue) {
          console.log('已经加载完预览窗口')
        },
        clickMounted: (vue) => {
          console.log('触发点击打印回调')
          vue.isShowPrint = true // å¼¹æ¡†æ˜¾ç¤ºæ¡ç 
        },
        beforeOpenCallback(vue) {
          console.log('打开之前', vue.barcodeNum)
        },
        openCallback(vue) {
          //  let time =vue.orderParams.createTime
          // vue.orderParams.createTime =  `${time.getFullYear()}-${time.getMonth() + 1}-${time.getDate()} ${time.getHours()}:${time.getMinutes()}`
          // vue.orderParams.listId = vue.outCodeTable
          // vue.orderParams.outPerson = vue.name
          // outOperation(vue.orderParams).then((res) => {
          //   vue.$message.success("成功出库")
          //   vue.isShowPrint = false  // å…³é—­æ¡ç æ˜¾ç¤ºå¼¹æ¡†
          // })
          console.log('执行了打印', vue.barcodeNum)
        },
        clickMounted(vue) {
          console.log(1111)
          console.log(vue.orderParams.createTime)
          outOperation({ ...vue.orderParams, outPerson: vue.name, listCode: vue.outCodeTable }).then((res) => {
            vue.orderFormVisible = false
            vue.outCodeTable = []
            vue.outTable = []
            vue.tableData = []
            vue.fetchData()
            console.log('清空数据,同时刷新数据')
            vue.$message.success('成功出库')
            vue.fetchData()
            vue.isShowPrint = false // å…³é—­æ¡ç æ˜¾ç¤ºå¼¹æ¡†
          }, () => {
            vue.$message.err('请重新打印')
          }).finally(() => {
            vue.templateOrderVisible = false
            vue.orderParams = {}
          })
          console.log('执行了打印', vue.barcodeNum)
        }
      },
      outPageParams: {
        pageNo: 1,
        pageSize: 3
      },
      isMerge: false,
      outTable: [],
      outCodeTable: [],
      outParams: {},
      outFormVisible: false,
      getList,
      total: 0,
      options: [],
      searchModel: {
        pageNo: 1,
        pageSize: 10,
        productModel: '',
        endTime: '',
        startTime: ''
      },
      formLabelWidth: '120px',
      orderFormVisible: false,
      orderParams: {
        orderNumber: '',
        escortNoteNumber: '',
        customerOrderNumber: '',
        createTime: '',
        customerName: '',
        consignor: '',
        arrivalAddress: '',
        receivingContact: '',
        cellPhoneNumber: ''
      },
      total: 0,
      tableData: [],
      contentTable: [],
      isScan: false
    }
  },
  watch: {
    isScan(to) {
    }
  },
  created() {
    this.fetchData()
    this.setOptions()
  },
  beforeDestroy() {
    window.document.onkeypress = null
  },
  methods: {
    templateOrderClose() {
      this.orderFormClose()
    },
    orderFormClose() {
      // å…³é—­æ‰“印押运单输入弹窗清空数据
      for (const key in this.orderParams) {
        this.orderParams[key] = ''
      }
      // this.outTable = []
    },
    goToPrint() {
      let ok = false
      for (const key in this.orderParams) {
        if (!this.orderParams[key]) {
          ok = true
        }
      }
      if (ok) {
        return this.$message.error('请填写完整参数')
      }
      console.log('需要打印的参数', this.orderParams)
      const time = this.orderParams.createTime
      this.orderParams.createTime = `${time.getFullYear()}-${time.getMonth() + 1 < 10 ? '0' + (time.getMonth() + 1) : time.getMonth() + 1}-${time.getDate() < 10 ? '0' + time.getDate() : time.getDate()} ${time.getHours() < 10 ? '0' + time.getHours() : time.getHours()}:${time.getMinutes() < 10 ? '0' + time.getMinutes() : time.getMinutes()}`
      console.log('需要打印的东西==>', this.outTable)
      // this.orderFormVisible = false
      this.templateOrderVisible = true
    },
    merge() {
      this.isMerge = !this.isMerge
      if (this.isMerge) {
        this.contentTable = JSON.parse(JSON.stringify(this.tableData))
      } else {
        this.tableData = JSON.parse(JSON.stringify(this.contentTable))
        return
      }
      this.tableData = this.tableData.reduce((arr, next) => {
        for (const item of arr) {
          if (item.productModel === next.productModel) {
            item.children.push(next.id)
            item.incomingQuantity = item.incomingQuantity + next.incomingQuantity
            return arr
          }
        }
        next.children = [next.id]
        arr.push(next)
        return arr
        // arr.push(next)
      }, [])
      console.log(this.tableData)
    },
    printOrder() {
      console.log(this.outCodeTable, this.outTable)
      this.orderFormVisible = true
    },
    addScanMonitor() {
      window.document.onkeypress = e => {
        console.log(e)
        if (window.event) { // IE
          this.nextCode = e.keyCode
        } else if (e.which) { // Netscape/Firefox/Opera
          this.nextCode = e.which
        }
        if (e.which === 13) { // é”®ç›˜å›žè½¦äº‹ä»¶
          // if (this.code.length < 3) return // æ‰«ç æžªçš„速度很快,手动输入的时间不会让code的长度大于2,所以这里不会对扫码枪有效
          console.log(new Date().getTime())
          if (new Date().getTime() - this.lastTime > 30) {
            return this.$message.error('扫码时不可通过键盘输入')
          }
          // if (this.code.length < 3) return // æ‰«ç æžªçš„速度很快,手动输入的时间不会让code的长度大于2,所以这里不会对扫码枪有效
          console.log('扫码结束,条形码:', this.code)
          for (const item of this.tableData) {
            if (item.id == this.code) {
              this.$message.error('请勿重复扫描')
              this.handleSubmitScanning()
              return
            }
          }
          // å‘送请求
          selectCacheOfIn({ code: this.code }).then(res => {
            this.$message.success(`${this.code}扫描成功`)
            const { data } = res
            if (data) this.tableData.push(data)
          })
          this.scanningForm.scanCode = this.code
          this.lastCode = ''
          this.lastTime = ''
          this.handleSubmitScanning()
          return
        }
        this.nextTime = new Date().getTime()
        if (!this.lastTime && !this.lastCode) {
          this.code = '' // æ¸…空上次的条形码
          // ç»§ç»­æ‰«æä¸€ä¸‹æ¡å‰å…³é—­å¼¹çª—
          // this.handleCloseTipsVisible()
          this.code = this.code + '' + e.key
          console.log('扫码开始---', this.code)
        }
        if (this.lastCode && this.lastTime && this.nextTime - this.lastTime > 500) { // å½“扫码前有keypress事件时,防止首字缺失
          this.code = e.key
          console.log('防止首字缺失。。。', this.code)
        } else if (this.lastCode && this.lastTime) {
          this.code = this.code + '' + e.key
          console.log('扫码中。。。', this.code)
        }
        this.lastCode = this.nextCode
        this.lastTime = this.nextTime
      }
    },
    handleSelectionChange(val) {
      if (this.isMerge) {
        console.log(val)
        const arrChildren = val.map((item) => item.children)
        console.log(arrChildren)
        this.outCodeTable = arrChildren.reduce((arr, next) => {
          arr = [...arr, ...next]
          return arr
        }, [])
        console.log(this.contentTable, this.outCodeTable)
        this.contentTable.forEach(item => {
          if (this.outCodeTable.indexOf(item.id) > -1) {
            this.outTable.push(item)
          }
        })
      } else {
        this.outTable = val
        this.outCodeTable = this.outTable.map(item => item.id)
      }
      console.log(this.outTable, this.outCodeTable)
    },
    scan(e) {
      console.log('开始扫码出库')
      this.$message.success('请开始扫码出库')
      this.tableData = []
      this.addScanMonitor()
      e.srcElement.blur()
    },
    async setOptions() {
      const { data: nameRes } = await selectAllName()
      // console.log(nameRes)
      const nameArr = nameRes.productNames.map(item => {
        return { value: item.id, label: item.productName }
      })
      for (const nameItem of nameArr) {
        const { data } = await selectAllModel({ productNameId: nameItem.value })
        this.options = [...this.options, ...data.models]
        /* nameItem.children = data.models.map(item => {
          return { value: item.id, label: item.productModel }
        }) */
      }
      this.options = this.options.map(item => {
        return { label: item.productModel, value: item.productModel, productCode: item.productCode }
      })
      // console.log(this.options)
    },
    searchData(res) {
      console.log(res)
      const { row, total, productModel, startTime, endTime } = res
      this.tableData = row
      this.total = total
      this.searchModel.productModel = productModel
      this.searchModel.startTime = startTime
      this.searchModel.endTime = endTime
      window.document.onkeypress = undefined
    },
    onTableRowClassName({ row, rowIndex }) {
      if (rowIndex % 2 != 0) {
        return 'onAcitve'
      } else {
        return ''
      }
    },
    fetchData() {
      this.listLoading = true
      getList().then(response => {
        this.list = response.data.items
      const obj = {}
      const arr = Object.keys(this.searchModel).filter(key => this.searchModel[key])
      arr.forEach(item => obj[item] = this.searchModel[item])
      getList(obj).then(response => {
        this.tableData = response.data.row
        this.total = response.data.total
        this.listLoading = false
        // console.log(this.tableData)
      })
    },
    handleSizeChange(val) {
@@ -185,31 +594,118 @@
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`)
    },
    outHandleSizeChange(val) {
      console.log(`每页 ${val} æ¡`)
    },
    outHandleCurrentChange(val) {
      console.log(`当前页: ${val}`)
      this.outPageParams.pageNo = val
      // this.fetchData()
      // console.log()
      // console.log(this.addTable.slice((this.outPageParams.pageSize * (val - 1)), (this.outPageParams.pageSize * (val - 1)) + this.outPageParams.pageSize))
    }
  },
  computed: {
    ...mapGetters([
      'sidebar',
      'avatar',
      'name',
      'allTab'
    ])
  }
}
</script>
<style lang="scss" scoped>
@import '../../styles/variables.scss';
.addOperation {
 min-height: calc(100vh - 50px);
::v-deep .el-table__header .el-checkbox{
    display:none;
}
::v-deep .tableData .el-table__header th:nth-child(1) .cell::before{
content: '多选';
}
.templateOrder{
  border: 1px solid #000;
  padding: 8px;
  >h3{
    text-align: center;
  }
  &-main{
  border-top: 1px solid #000;
  border-left: 1px solid #000;
    .main-row{
      display: flex;
      font-size: 12px;
        >div{
        border-bottom: 1px solid #000;
        border-right: 1px solid #000;
        height: 40px;
        line-height: 20px;
        padding: 10px;
        // margin: 24px;
        >h4{
          margin: 0;
        }
      }
      .flex-2{
        min-width: 110px;
        max-width: 110px;
        text-align: right;
        padding: 10px 6px;
      }
      .flex-4{
        flex: 1;
        text-align: center;
      }
      .flex-8{
        flex: 8;
      }
      .flex-18{
        flex: 18;
      }
    }
  }
}
.outOperation {
 min-height: calc(100vh - 100px);
 padding: 25px;
 background: $mainBg;
 .addOperation-main{
 display: flex;
 flex-direction: column;
 .dialog-footer{
  text-align: center;
  display: flex;
  justify-content: space-around;
 }
 .outOperation-main{
  background: #fff;
  padding: 20px;
  flex: 1;
  display: flex;
  flex-direction: column;
  .main-top{}
  .table-header{
    background: #6095FB;
  }
 }
 .addOperation-foot{
  ::v-deep .el-table{
    flex: 1;
    // display: flex;
    // flex-direction: column;
   ::v-deep .onAcitve td{
    background-color: #F2F2F2 !important;
  }
  }
  .outOperation-foot{
  margin-top: 25px;
  .el-pagination{
    display: flex;
    justify-content: center;
    justify-content: right;
  }
 }
 }
}
</style>
src/views/out_operation/manual/index.vue
@@ -1,15 +1,330 @@
<template>
  <div class="manual">
    æ‰‹åŠ¨å‡ºåº“
  <div class="outOperation">
    <div class="outOperation-main">
     <el-row type="flex" align="middle" class="main-top">
      <el-col :span="2">出库台账</el-col>
      <el-col :span="20">
        <div class="table-search">
    <el-form
      v-model="queryParams"
      ref="queryForm"
      size="small"
      :inline="true"
      label-width="68px"
    >
      <el-form-item label="日期:">
        <el-date-picker
          v-model="queryParams.date"
          type="datetimerange"
          :picker-options="pickerOptions"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          align="right"
        >
        </el-date-picker>
      </el-form-item>
      <el-form-item label="客户名称">
        <el-select v-model="queryParams.type" placeholder="规格型号" clearable style="width: 240px">
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value">
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini"
          @click="search">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini">导出</el-button>
      </el-form-item>
    </el-form>
  </div>
      </el-col>
     </el-row>
    <el-table
      :stripe="true"
      :data="tableData"
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
      :border="true"
      header-row-class-name="table-header"
    >
      <el-table-column
        type="selection"
        width="55">
      </el-table-column>
      <el-table-column
        prop="name"
        label="产品编码">
      </el-table-column>
      <el-table-column
        prop="address"
        label="产品名称">
      </el-table-column>
      <el-table-column
        prop="date"
        label="规格型号">
      </el-table-column>
      <el-table-column
        prop="date"
        label="单位">
      </el-table-column>
      <el-table-column
        prop="date"
        label="出库数量">
      </el-table-column>
      <el-table-column
        prop="date"
        label="发货人">
      </el-table-column>
      <el-table-column
        prop="date"
        label="出库日期">
      </el-table-column>
    </el-table>
    </div>
    <div class="outOperation-foot">
        <el-pagination
        :current-page="searchModel.pageNo"
        :page-sizes="[10, 15, 20, 25]"
        :page-size="searchModel.pageSize"
        layout="->, total, sizes, prev, pager, next, jumper"
        :total="total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        >
      </el-pagination>
    </div>
    <el-dialog title="押运单打印" :visible.sync="orderFormVisible">
      <el-form label-position="left" :model="orderParams">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="订单号" :label-width="formLabelWidth">
              <el-input v-model="orderParams.number" autocomplete="off"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="押运单编号" :label-width="formLabelWidth">
              <el-input v-model="orderParams.noId" autocomplete="off"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="客户订单号" :label-width="formLabelWidth">
              <el-input v-model="orderParams.clientNumber" autocomplete="off"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="发货日期" :label-width="formLabelWidth">
              <el-input v-model="orderParams.date" autocomplete="off"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="客户名称" :label-width="formLabelWidth">
              <el-input v-model="orderParams.clientName" autocomplete="off"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="发货人" :label-width="formLabelWidth">
              <el-input v-model="orderParams.consigner" autocomplete="off"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col>
            <el-form-item label="到货地址" :label-width="formLabelWidth">
              <el-input v-model="orderParams.address" autocomplete="off"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col>
            <el-form-item label="收货联系人" :label-width="formLabelWidth">
              <el-input v-model="orderParams.consignee" autocomplete="off"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col>
            <el-form-item label="手机号" :label-width="formLabelWidth">
              <el-input v-model="orderParams.phoneNumber" autocomplete="off"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col>
            <el-form-item>
              <el-table :data="tableData" header-row-class-name="table-header">
                <el-table-column property="date" label="产品名称" ></el-table-column>
                <el-table-column property="name" label="规格型号"></el-table-column>
                <el-table-column property="address" label="单位"></el-table-column>
                <el-table-column property="number" label="发库数量"></el-table-column>
              </el-table>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer" >
        <el-button type="primary" @click="print">ç¡® å®š</el-button>
        <el-button @click="addFormVisible = false" >取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { getList } from '@/api/table'
import TableSearch from '@/components/TableSearch'
export default {
  filters: {
    statusFilter(status) {
      const statusMap = {
        published: 'success',
        draft: 'gray',
        deleted: 'danger'
      }
      return statusMap[status]
    }
  },
  data() {
    return {
      formLabelWidth: '120px',
      orderFormVisible: false,
      orderParams: {
        number: '',//订单号
        noId: '', //押运单编号
        orderParams: '', //客户订单号
        date: '',
        clientName: '',
        consigner: '',
        address: '',
        consignee: '',
        phoneNumber: ''
      },
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 10
      },
      tableData: [
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 å¼„',
          number: ''
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 å¼„',
          number: ''
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 å¼„',
          number: ''
        }
      ],
      queryParams: {
        date: '',
        type: ''
      },
      pickerOptions: {
          shortcuts: [{
            text: '最近一周',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
              picker.$emit('pick', [start, end]);
            }
          }, {
            text: '最近一个月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
              picker.$emit('pick', [start, end]);
            }
          }, {
            text: '最近三个月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
              picker.$emit('pick', [start, end]);
            }
          }]
      },
      options: [
        {
          value: '第一种型号',
          label: '第一种型号'
        }
      ]
    }
  },
  created() {
    this.fetchData()
  },
  components: {
    TableSearch
  },
  methods: {
    print() {
      //货运单打印参数
      console.log(this.orderParams)
    },
    fetchData() {
      this.listLoading = true
      getList().then(response => {
        this.list = response.data.items
        this.listLoading = false
      })
    },
    handleSizeChange(val) {
      console.log(`每页 ${val} æ¡`)
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`)
    },
    search() {
      // "查询条件:"时间需要格式化成yyyy-mm-dd hh-mm-ss
      console.log(this.queryParams)
    }
  }
}
</script>
<style>
</style>
<style lang="scss" scoped>
@import '../../../styles/variables.scss';
.outOperation {
 min-height: calc(100vh - 50px);
 padding: 25px;
 background: $mainBg;
 .dialog-footer{
  text-align: center;
 }
 .outOperation-main{
  background: #fff;
  padding: 20px;
  .main-top{}
  .table-header{
    background: #6095FB;
  }
 }
 .outOperation-foot{
  margin-top: 25px;
  .el-pagination{
    display: flex;
    justify-content: center;
  }
 }
}
</style>
src/views/out_operation/outboundLedger/index.vue
ÎļþÒÑɾ³ý
src/views/outbound/index.vue
@@ -1,6 +1,241 @@
<template>
  <div style="padding:30px;">
    åº“存台账
    <el-alert :closable="false" title="menu 2" />
  <div class="out-bound">
    <div class="out-bound-main">
      <el-row type="flex" align="middle" class="main-top">
        <el-col :span="2" :style="{color:'#409EFF'}"> <span class="iconfont icon-taizhangzhangbuxinxichaxun" /> æ”¶å‘存管理</el-col>
        <el-col :span="20">
          <TableSearch :excel-name="'收发存管理表'" :show="false" :file="file" :get-list="getInventoryList" :search-data="searchData" :search-params="searchModel" />
        </el-col>
        <el-col :span="2">
        <!-- <el-button @click="goToOutboundLedger" icon="iconfont icon-caiwushoufacunguanli">查看台账</el-button> -->
        </el-col>
      </el-row>
      <el-table
        :row-class-name="onTableRowClassName"
        :row-style="{height:0+'px'}"
        :cell-style="{padding:8+'px',textAlign: 'center'}"
        :header-cell-style="{borderRight:'0px',textAlign: 'center',background:'#52626F',color:'#fff', height:'10px', padding:'0px'}"
        :stripe="true"
        :data="tableData"
        :border="true"
        header-row-class-name="table-header"
      >
        <!-- <el-table-column
        type="selection"
        width="55">
      </el-table-column> -->
        <el-table-column
          type="index"
          label="序号"
        />
        <el-table-column
          prop="productCode"
          label="产品编码"
        />
        <el-table-column
          prop="productName"
          label="产品名称"
        />
        <el-table-column
          prop="productModel"
          label="规格型号"
        />
        <el-table-column
          prop="productUnit"
          label="单位"
        />
        <el-table-column
          prop="beginningInventory"
          label="初期库存数量"
        />
        <el-table-column
          prop="issueInCurrentPeriod"
          label="本期出库数量"
        />
        <el-table-column
          prop="currentPeriod"
          label="本期入库数量"
        />
        <el-table-column
          prop="closingInventory"
          label="期末库存数量"
        />
      <!-- <el-table-column
        label="操作">
        <el-button size="mini" type="text" @click="delItem()">删除</el-button>
      </el-table-column> -->
      </el-table>
      <div class="out-bound-foot">
        <el-pagination
          :current-page="searchModel.pageNo"
          :page-sizes="[10, 15, 20, 25]"
          :page-size="searchModel.pageSize"
          layout="->, total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </div>
  </div>
</template>
<script>
import { getInventoryList, file } from '@/api/outbound'
import TableSearch from '@/components/TableSearch'
export default {
  filters: {
    statusFilter(status) {
      const statusMap = {
        published: 'success',
        draft: 'gray',
        deleted: 'danger'
      }
      return statusMap[status]
    }
  },
  components: {
    TableSearch
  },
  data() {
    return {
      file,
      getInventoryList,
      pickerOptions: {
        shortcuts: [{
          text: '最近一周',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近一个月',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近三个月',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
            picker.$emit('pick', [start, end])
          }
        }]
      },
      inType: '',
      inStatus: '',
      deptName: '',
      statusType: {},
      queryParams: {
        encode: '',
        type: '',
        depositor: ''
      },
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 10,
        endTime: '',
        startTime: ''
      },
      tableData: []
    }
  },
  created() {
    this.fetchData()
  },
  methods: {
    delItem() {
      console.log('删除')
    },
    searchData(res) {
      console.log(res)
      const { row, total, startTime, endTime } = res
      this.tableData = row
      this.total = total
      this.searchModel.startTime = startTime
      this.searchModel.endTime = endTime
    },
    onTableRowClassName({ row, rowIndex }) {
      if (rowIndex % 2 != 0) {
        return 'onAcitve'
      } else {
        return ''
      }
    },
    goToOutboundLedger() {
    },
    fetchData() {
      this.listLoading = true
      this.listLoading = true
      const obj = {}
      const arr = Object.keys(this.searchModel).filter(key => this.searchModel[key])
      arr.forEach(item => obj[item] = this.searchModel[item])
      console.log(obj)
      getInventoryList(obj).then(response => {
        this.tableData = response.data.row
        this.total = response.data.total
        this.listLoading = false
      })
    },
    handleSizeChange(val) {
      console.log(`每页 ${val} æ¡`)
    },
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`)
    }
  }
}
</script>
<style lang="scss" scoped>
@import '../../styles/variables.scss';
.out-bound {
 min-height: calc(100vh - 100px);
 padding: 25px;
 background: $mainBg;
 display: flex;
 flex-direction: column;
 .out-bound-main{
  background: #fff;
  flex: 1;
  padding: 20px;
  display: flex;
  flex-direction: column;
//  .el-table--striped .el-table__body tr.el-table__row--striped td {
//     background: #F2F2F2 !important;
// }
  .main-top{}
  .table-header{
    background: #6095FB;
  }
  .el-table{
    flex: 1;
   ::v-deep .onAcitve td{
    background-color: #F2F2F2 !important;
  }
  }
  .out-bound-foot{
  margin-top: 25px;
  .el-pagination{
    display: flex;
    justify-content: right;
  }
 }
 }
}
// /deep/.el-table--striped .el-table__body tr.el-table__row--striped td {
//     background: #1e116d;
// }
</style>
src/views/system/dict/index.vue
@@ -1,14 +1,34 @@
<template>
  <div class="systemDict">
    è¿™æ˜¯å­—典管理
    <vue-barcode
  :value="value()"
  >不支持vue-barcode</vue-barcode>
  </div>
</template>
<script>
export default {
import VueBarcode from 'vue-barcode'
export default{
    components: { VueBarcode },
    data () {
        return {
           //条形码内容
        }
    },
    methods: {
      value() {
        let obj = {name:'jack'}
        return JSON.stringify(obj)
      }
    }
}
</script>
<style>
src/views/system/user/index.vue
@@ -1,15 +1,414 @@
<template>
  <div class="system-user">
    <SettingTitle left="你的用户配置" right="小图标"></SettingTitle>
    <div class="user-info"></div>
    <SettingTitle v-if="authority" left="你的用户配置" :click-fun="showAdd" right="新增用户" icon="el-icon-plus" />
    <SettingTitle v-else left="你的用户配置" />
    <div class="user-info">
      <div class="info-avatar">
        <el-upload
          :headers="{'X-Token':token}"
          class="avatar-uploader"
          :action="baseUrl+'/user/update'"
          :show-file-list="false"
          :on-success="handleAvatarSuccess"
        >
          <img v-if="avatar" :src="baseUrl+'/img'+avatar" class="avatar">
          <i v-else class="el-icon-plus avatar-uploader-icon" />
        </el-upload>
      </div>
      <div class="info-msg">
        <div>{{ msgInfo.name }}</div>
        <div>账号:{{ msgInfo.account }}</div>
      </div>
      <div class="info-logout">
        <el-button type="primary" plain @click="logout">退出登录</el-button>
      </div>
    </div>
    <div class="setting-list">
      <div v-for="(item,index) in serviceArr" :key="index" class="setting-item">
        <div class="item-icon  iconfont" :class="item.icon" />
        <div class="item-msg">{{ item.name }}</div>
        <div class="item-right" :class="item.right" @click="showDialog(item.name)" />
      </div>
    </div>
    <!-- åŒæ—¶ç”¨æˆ·åˆ—表为0也不展示 -->
    <template v-if="userList.length>1">
      <SettingTitle left="用户列表" />
      <div class="setting-list">
        <div v-for="item in userList" v-if="name !== item.username" :key="item.id" class="setting-item">
          <div class="item-icon">
            <el-avatar :size="40" :src="baseUrl+'/img'+item.avatar" />
          </div>
          <div class="item-msg">{{ item.username }}</div>
          <div class="item-right">
            <el-button v-if="authority" type="text" :style="{color:'red'}" @click="clear(item)">删除</el-button>
          </div>
        </div>
      </div>
    </template>
    <template>
      <SettingTitle left="表格" />
      <div class="setting-list">
        <div class="setting-item">
          <div class="item-icon iconfont icon-biaogeziduan" />
          <div class="item-msg">修改查看表头</div>
          <el-dropdown trigger="click" @command="showTableDialog($event)">
            <span class="el-dropdown-link">
              <i class="el-icon-arrow-down el-icon--right" />
            </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item v-for="(item ,index) in allTab" :key="index" :command="item">{{ item.name }}</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        <!-- <div class="item-right  el-icon-arrow-down" @click="showDialog('修改表单')"></div> -->
        </div>
      </div>
    </template>
    <SettingTitle left="添加型号" />
    <div class="setting-model">
      <el-row :gutter="20">
        <el-col :span="4">
          <div :style="{display:'flex'}">
            <el-input
              v-model="filterText"
              placeholder="输入关键字进行过滤"
            />
            <!-- <el-button>添加名称</el-button> -->
          </div>
          <el-tree
            ref="tree"
            :style="{marginTop:'20px'}"
            class="filter-tree"
            :data="treeData"
            :props="defaultProps"
            default-expand-all
            :filter-node-method="filterNode"
          >
            <span slot-scope="{ node, data }" class="custom-tree-node">
              <div :style="{height:'100%', display:'flex',alignItems: 'center'}">
                <div :style="{marginRight: '8px',display:'flex',alignItem: 'center'}">
                  <span>{{ node.label }}</span>
                  <span :style="{marginLeft: '20px',fontSize: '10px'}" class="edit el-icon-edit" @click="changeName(node,data)">修改</span>
                  <span :style="{marginLeft: '20px',fontSize: '10px'}" class="edit el-icon-delete" @click="deleteName(node,data)" />
                </div>
                <!-- ç²¾åº¦ä¸é«˜ å¯¼è‡´çš„问题-->
              </div>
            </span>
          </el-tree>
        </el-col>
        <el-col :span="20">
          <div class="addName">
            <el-row :gutter="20">
              <el-col :span="8">
                <div :style="{display: 'flex'}">
                  <el-input v-model="newName" :style="{marginRight: '8px'}" />
                  <el-button @click="addNewName">添加名称</el-button>
                </div>
              </el-col>
              <el-col :span="14">
                <el-row :gutter="20">
                  <el-col :span="4">
                    <el-select v-model="checkNameId" clearable placeholder="请选择">
                      <el-option
                        v-for="item in nameOptions"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                      />
                    </el-select>
                  </el-col>
                  <el-col :span="10">
                    <el-input v-model="newModel" :style="{marginLeft: '8px'}" placeholder="请输入型号名称" />
                  </el-col>
                  <el-col :span="10">
                    <el-input v-model="newProductCode" :style="{marginLeft: '8px'}" placeholder="请输入产品编码" />
                  </el-col>
                </el-row>
              </el-col>
              <el-col :span="2">
                <el-button @click="addNewModel">添加型号</el-button>
              </el-col>
            </el-row>
          </div>
          <el-table
            class="tableData"
            :height="450"
            :max-height="450"
            :row-class-name="onTableRowClassName"
            :row-style="{height:0+'px'}"
            :cell-style="{padding:8+'px',textAlign: 'center'}"
            :header-cell-style="{borderRight:'0px',textAlign: 'center',background:'#52626F',color:'#fff', height:'10px', padding:'0px'}"
            :stripe="true"
            :data="tableData"
            :border="true"
            header-row-class-name="table-header"
          >
            <el-table-column
              type="index"
              label="序号"
            />
            <el-table-column
              prop="productCode"
              label="产品编码"
            />
            <el-table-column
              prop="productModel"
              label="型号名称"
            />
            <el-table-column
              prop="productName"
              label="产品名称"
            />
            <el-table-column
              label="更多操作"
            >
              <template slot-scope="scope">
                <el-button type="text" @click="changeModel(scope.row)">修改</el-button>
                <el-button type="text danger" @click="deleteModel(scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-col>
      </el-row>
    </div>
    <el-dialog class="changePassword" :visible.sync="passwordFormVisible" @close="handleClose('passwordParams')">
      <div slot="title" class="title">
        <span />
        <span>修改密码</span>
      </div>
      <el-form ref="passwordParams" :model="passwordParams" :rules="passwordRules">
        <el-row>
          <el-col>
            <el-form-item prop="oldPassword">
              <el-input v-model="passwordParams.oldPassword" :validate-event="false" show-password type="password" placeholder="请输入旧密码" autocomplete="off" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col>
            <el-form-item prop="newPassword">
              <el-input v-model="passwordParams.newPassword" :validate-event="false" show-password type="password" placeholder="请输入新密码" autocomplete="off" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="changePwd">ç¡® å®š</el-button>
      </div>
    </el-dialog>
    <el-dialog class="tableHead" :visible.sync="tableFormVisible" @close="handleClose('userParams')">
      <div slot="title" class="title">
        <span />
        <span>修改表单</span>
      </div>
      <el-form ref="userParams" :model="userParams">
        <el-row>
          <el-col>
            <el-checkbox-group v-model="checkList">
              <el-checkbox v-for="(item, index) in commandList" :key="index" :label="item" :checked="item.show" @change="changeCheck(!item.show,item)">{{ item.name }}</el-checkbox>
            </el-checkbox-group>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="changeTable">ç¡® å®š</el-button>
        <!-- <el-button @click="tableFormVisible = false" >取 æ¶ˆ</el-button> -->
      </div>
    </el-dialog>
    <el-dialog class="userInfo" title="个人资料" :visible.sync="infoFormVisible" @close="handleClose('addUserForm')">
      <div slot="title" class="title">
        <span />
        <span>个人资料</span>
      </div>
      <el-form ref="addUserForm" :model="infoParams" :rules="addUserRules">
        <el-row>
          <el-col>
            <el-form-item prop="username">
              <el-input v-model="infoParams.username" placeholder="用户名" autocomplete="off" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col>
            <el-form-item prop="account">
              <el-input v-model="infoParams.account" placeholder="账号" autocomplete="off" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col />
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="changeInfo">ç¡® å®š</el-button>
        <!-- <el-button @click="infoFormVisible = false" >取 æ¶ˆ</el-button> -->
      </div>
    </el-dialog>
    <el-dialog class="addUser" :visible.sync="addVisible" @close="handleClose('addParams')">
      <div slot="title" class="title">
        <span />
        <span>新增用户</span>
      </div>
      <el-form ref="addParams" label-position="left" label-width="80px" :model="addParams" :rules="addUserRules">
        <el-form-item prop="username" label="用户名:">
          <el-input v-model="addParams.username" placeholder="用户名" autocomplete="off" />
        </el-form-item>
        <el-form-item prop="account" label="账号">
          <el-input v-model="addParams.account" placeholder="账号" autocomplete="off" />
        </el-form-item>
        <el-form-item prop="password" label="密码:">
          <el-input v-model="addParams.password" placeholder="密码" show-password type="password" autocomplete="off" />
        </el-form-item>
        <el-form-item prop="authority" label="身份:">
          <el-select v-model="addParams.authority" placeholder="请选择身份">
            <el-option
              v-for="item in powerOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="addNewUser">ç¡® å®š</el-button>
        <!-- <el-button @click="infoFormVisible = false" >取 æ¶ˆ</el-button> -->
      </div>
    </el-dialog>
    <el-dialog width="30%" handle-close-change-name-params- class="changeName" :visible.sync="changeNameVisible">
      <div slot="title" class="title">
        <span />
        <span>修改名称</span>
      </div>
      <el-form>
        <el-form-item ref="changeNameParams" :model="changeNameParams">
          <el-input v-model="changeNameParams.productName" />
        </el-form-item>
        <div :style="{display: 'flex'}">
          <el-button type="primary" :style="{flex:'1'}" @click="ConfirmChange">确定修改</el-button>
        </div>
      </el-form>
    </el-dialog>
    <el-dialog handle-close-change-model-params- width="30%" class="changeModel" :visible.sync="changeModelVisible">
      <div slot="title" class="title">
        <span />
        <span>修改型号</span>
      </div>
      <el-form>
        <el-form-item ref="changeModelParams" :model="changeModelParams">
          <el-input v-model="changeModelParams.productModel" placeholder="请输入新型号" />
        </el-form-item>
        <el-form-item :model="changeModelParams">
          <el-input v-model="changeModelParams.productCode" placeholder="请输入编码" />
        </el-form-item>
        <div :style="{display: 'flex'}">
          <el-button type="primary" :style="{flex:'1'}" @click="confirmChangeModel">确定修改</el-button>
        </div>
      </el-form>
    </el-dialog>
  </div>
</template>
<script>
import { mapGetters } from 'vuex'
import { getInfo, addUser, getUserList, updateUserPwd, delUser, updateUserProfile } from '@/api/user'
import { selectAllName, addName, updateName, delName } from '@/api/productName'
import { selectAllModel, addModel, updateModel, delModel } from '@/api/productModel'
import { getToken } from '@/utils/auth'
import SettingTitle from '@/components/SettingTitle'
export default {
  data() {
    const validateAccount = (rule, value, callback) => {
      const reg = /^(?=.*\d).{6,11}$/
      if (!reg.test(value)) {
        callback(new Error('账号由6-10位数字组成,请输入正确的账号!'))
      } else {
        callback()
      }
    }
    const validatePassword = (rule, value, callback) => {
      // console.log(value)
      const reg = /^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{6,12}$/
      // console.log(!reg.test(value))
      if (!reg.test(value)) {
        callback(new Error('密码必须是由6-12位包含大小写字母,数字组合'))
      } else {
        callback()
      }
    }
    return {
      changeNameVisible: false,
      changeModelVisible: false,
      changeNameParams: {
        id: '',
        productName: ''
      },
      changeModelParams: {
      },
      newModel: '',
      newProductCode: '',
      newName: '',
      checkNameId: '',
      nameOptions: [
        {
          label: 'abc',
          value: '1'
        }
      ],
      tableData: [],
      treeData: [],
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      filterText: '',
      addModelFormVisible: false,
      addVisible: false,
      powerOptions: [
        {
          value: '1',
          label: '管理员'
        },
        {
          value: '0',
          label: '普通用户'
        }
      ],
      addParams: {
        account: '',
        authority: '',
        password: '',
        username: ''
      },
      checkList: [],
      tableSelectVisible: false,
      baseUrl: process.env.VUE_APP_BASE_API,
      msgInfo: {},
      infoParams: {
      },
      infoFormVisible: false,
      userParams: {
        user: '',
        power: ''
      },
      tableFormVisible: false,
      passwordParams: {},
      passwordFormVisible: false,
      deptName: '',
      queryParams: {
        pageNum: 1,
@@ -20,26 +419,471 @@
        deptId: undefined
      },
      dateRange: [],
      userList: null
      serviceArr: [
        { name: '修改密码', icon: 'icon-mima', right: 'el-icon-arrow-right' },
        { name: '个人资料', icon: 'icon-gerenziliao', right: 'el-icon-arrow-right' }
      ],
      formLabelWidth: '120px',
      userList: [],
      commandList: [],
      tableName: '',
      addUserRules: {
        account: [{ required: true, trigger: 'blur', validator: validateAccount }],
        password: [{ required: true, trigger: 'blur', validator: validatePassword }]
      },
      passwordRules: {
        oldPassword: [{ required: true, validator: validatePassword }],
        newPassword: [{ required: true, validator: validatePassword }]
      },
      addNameParams: {}
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val)
    }
  },
  computed: {
    ...mapGetters([
      'sidebar',
      'avatar',
      'name',
      'allTab',
      'authority',
      'token'
    ])
  },
  created() {
    this.getUserInfo()
    this.getAllUser()
    this.setOptions()
  },
  components: {
    SettingTitle
  },
  mounted() {
  },
  methods: {
    handleClose(refName) {
      // console.log(refName)
      this.$refs[refName]?.resetFields()
    },
    ConfirmChange() {
      console.log(this.changeNameParams)
      if (!this.changeNameParams.productName) return this.$message.error('请认真填写不可为空')
      updateName(this.changeNameParams).then((res) => {
        this.changeNameParams.id = ''
        this.changeNameParams.productName = ''
        console.log('清空修改名称输入框内容')
        this.changeNameVisible = false
        this.$message.success(res)
        this.setOptions()
      })
    },
    confirmChangeModel() {
      console.log('修改型号参数', this.changeModelParams)
      updateModel(this.changeModelParams).then((res) => {
        this.changeModelVisible = false
        this.changeModelParams = {}
        this.$message.success(res)
        this.setOptions()
      })
    },
    addNewName() {
      console.log(this.newName)
      if (!this.newName) return this.$message.error('添加名称不能为空')
      addName({ productName: this.newName }).then((res) => {
        this.newName = ''
        this.$message.success(res)
        this.setOptions()
      }, () => {
        // this.$message.error('添加失败请重新尝试')
      })
    },
    changeName(node, data) {
      // console.log(node, data)
      this.changeNameParams.id = data.value
      this.changeNameParams.productName = data.label
      console.log(this.changeNameParams)
      this.changeNameVisible = true
    },
    deleteName(node, data) {
      console.log(data)
      this.$alert('确定删除', '删除名称', {
        confirmButtonText: '确定',
        callback: action => {
          delName({ id: data.value, productName: data.label }).then((res) => {
            this.$message.success(res)
            this.setOptions()
          })
        }
      })
    },
    addNewModel() {
      addModel({ productNameId: this.checkNameId, productModel: this.newModel, productCode: this.newProductCode }).then((res) => {
        this.checkNameId = ''
        this.newModel = ''
        this.newProductCode = ''
        this.$message.success(res)
        this.setOptions()
      })
    },
    deleteModel(row) {
      delModel({ id: row.id, productModel: row.productModel }).then((res) => {
        this.$message.success(res)
        this.setOptions()
      })
    },
    changeModel(row) {
      this.changeModelVisible = true
      const params = { ...row }
      delete params.productName
      this.changeModelParams = { ... params }
    },
    async setOptions() {
      this.tableData = []
      this.treeData = []
      const { data: nameRes } = await selectAllName()
      // console.log(nameRes)
      const nameArr = nameRes.productNames.map(item => {
        return { value: item.id, label: item.productName }
      })
      this.nameOptions = nameArr
      // console.log(nameArr)
      for (const nameItem of nameArr) {
        const { data } = await selectAllModel({ productNameId: nameItem.value })
        data.models = data.models.map(item => {
          item.productNameId = nameItem.value
          item.productName = nameItem.label
          return item
        })
        this.tableData = [...this.tableData, ...data.models]
        const children = data.models.map(item => {
          return { id: item.id, label: item.productModel }
        })
        this.treeData.push({ ...nameItem, children })
      }
      this.tableData = this.tableData.map(item => {
        return { id: item.id, productModel: item.productModel, productCode: item.productCode, productName: item.productName }
      })
      // console.log(this.tableData)
    },
    onTableRowClassName({ row, rowIndex }) {
      if (rowIndex % 2 != 0) {
        return 'onAcitve'
      } else {
        return ''
      }
    },
    async logout() {
      console.log(1)
      await this.$store.dispatch('user/logout')
      this.$router.push(`/login?redirect=/home`)
    },
    filterNode(value, data) {
      if (!value) return true
      return data.label.indexOf(value) !== -1
    },
    changeCheck(newShow, item) {
      item.show = newShow
    },
    changeUser(item) {
    },
    clear(item) {
      // console.log()
      delUser(item).then(res => {
        this.$message.success('删除成功')
        // this.logout()
        this.getAllUser()
      }, () => {
        this.$message.error('删除失败')
      })
    },
    handleAvatarSuccess(res, file) {
      this.$message.success('上传成功')
      // this.$router.go(0)
    },
    async getAllUser() {
      const { data } = await getUserList()
      this.userList = data.user
      console.log(this.userList)
    },
    addNewUser() {
      // æ·»åŠ æ ¡éªŒè§„åˆ™
      this.$refs.addParams.validate(valid => {
        if (valid) {
          addUser(this.addParams).then(res => {
            this.addParams.account = ''
            this.addParams.authority = ''
            this.addParams.password = ''
            this.addParams.username = ''
            this.addVisible = false
            this.getAllUser()
            this.$message({
              message: '恭喜你,添加成功',
              type: 'success'
            })
          }, () => {
            this.$message.error({
              message: '添加用户失败请重新尝试'
            })
          })
        } else {
          this.$message.error('错误提交,表格校验出错')
        }
      })
      console.log(this.addParams)
    },
    showAdd() {
      this.addVisible = true
    },
    showTableDialog(command) {
      this.commandList = command.keys
      this.tableName = command.name
      this.tableFormVisible = true
    },
    getUserInfo() {
      getInfo(getToken()).then(res => {
        this.msgInfo = res.data
        // console.log(用户信息:res)
      })
    },
    showDialog(name) {
      if (name == '修改密码') {
        this.passwordFormVisible = true
      } else if (name == '修改表单') {
        this.tableSelectVisible = true
      } else if (name == '个人资料') {
        this.infoFormVisible = true
      }
    },
    async changePwd() {
      // ä¿®æ”¹å¯†ç å‚æ•°
      // this.logout()
      this.$refs.passwordParams.validate(valid => {
        if (valid) {
          updateUserPwd(this.passwordParams).then(async res => {
            this.passwordFormVisible = false
            await this.logout()
            this.$message({
              message: '恭喜你,修改成功',
              type: 'success'
            })
          }, () => {
            // this.$message.error({
            //   message: '添加用户失败请重新尝试'
            // })
          })
        } else {
          this.$message.error('错误提交,请检查密码格式')
        }
      })
    },
    changeTable() {
      console.log(this.commandList)
      this.$store.commit('CHANGE_TAB_KEY', { name: this.tableName, keys: this.commandList })
      this.tableFormVisible = false
      console.log(this.$store.state)
    },
    async changeInfo() {
      console.log(this.infoParams)
      const res = await updateUserProfile(this.infoParams)
      console.log(res)
      // this.$refs
      this.infoFormVisible = false
      this.getUserInfo()
      this.getAllUser()
      this.setOptions()
    }
  }
}
</script>
<style lang="scss" >
<style lang="scss" scoped>
@import '../../../styles/variables.scss';
//  ::v-deep .el-tree-node__content{
//   height: 70px;
// }
.changeName{
  .el-dialog{
     width: 30% !important;
  }
}
.el-tree-node__children{
  .edit{
    display: none;
  }
}
 ::v-deep .el-dropdown-menu__item {
      padding: 0 40px;
      font-size: 16px;
      border-bottom: 1px solid #efeeee;
  }
.el-icon-plus,.el-icon-arrow-down,.el-icon-arrow-right,.el-icon-arrow-left,.el-icon-arrow-up{
  color: #409EFF;
}
.system-user{
    min-height: calc(100vh - 50px);
    padding: 40px;
    background: $mainBg;
    .changePassword,.tableHead,.userInfo{
      .title{
        display: flex;
        align-items: center;
        span:nth-child(1){
          margin-right: 8px;
          display: inline-block;
          width: 4px;
          height: 18px;
          background: #409EFF;
        }
      }
      ::v-deep >div{
        width: 600px;
        border-radius: 10px;
      }
      ::v-deep .el-dialog__body{
        padding: 30px 100px;
        input{
          border: 0px;
          background: #f3f4f5;
        }
      }
      ::v-deep .el-dialog__footer{
        padding: 10px 100px 30px 100px;
        // margin-right: ;
        .dialog-footer{
          display: flex;
          button{
            flex: 1;
          }
        }
      }
    }
    .tableHead{
      ::v-deep >div{
        width: 300px;
      }
      ::v-deep .el-dialog__body{
        padding: 30px 50px;
      }
      ::v-deep .el-checkbox{
        margin-right: 0;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      ::v-deep .el-checkbox__label{
        width: 140px;
        margin: 5px 10px;
        padding: 10px 40px;
        background: #f3f4f5;
        border-radius: 6px;
      }
    }
}
.user-info{
  width: 100%;
  height: 125px;
  border-radius: 10px;
  background: #fff;
  padding: 25px;
  display: flex;
  align-items: center;
  .info-avatar{
     .avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }
  .avatar-uploader .el-upload:hover {
    border-color: #409EFF;
  }
  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 75px;
    height: 75px;
    line-height: 75px;
    text-align: center;
  }
  .avatar {
    width: 75px;
    height: 75px;
    display: block;
    border-radius: 50%;
  }
  }
  .info-logout{
    // width: 100px;
    .el-button--primary.is-plain{
          background: #fff;
          color: #409EFF;
          border-color: #b3d8ff;
    }
  }
  .info-msg{
    flex: 1;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding-left: 25px;
    >div:nth-child(1){
      font-weight: 700;
      font-size: 24px;
    }
  }
}
</style>
.setting-model{
   margin-top: 24px;
  border-radius: 10px;
  background: #fff;
  border: 1px solid #ddd;
  padding: 15px;
  .addName{
    // display: flex;
    margin-bottom: 20px;
  }
}
.setting-list{
  margin-top: 24px;
  border-radius: 10px;
  background: #fff;
  border: 1px solid #ddd;
  .setting-item{
    height: 70px;
    padding: 15px;
    width: 100%;
    display: flex;
    align-items: center;
    .item-icon{
      // width: 40px;
      // height: 40px;
    }
    .item-msg{
      flex: 1;
      padding-left: 15px;
    }
  }
  .setting-item{
    // border-top: 1px solid #ddd;
    border-bottom: 1px solid #ddd;
  }
}
</style>
vue.config.js
@@ -13,7 +13,7 @@
// For example, Mac: sudo npm run
// You can change the port by the following methods:
// port = 9528 npm run dev OR npm run dev --port = 9528
const port = process.env.port || process.env.npm_config_port || 9527 // dev port
const port = process.env.port || process.env.npm_config_port || 8010 // dev port
// All configuration item explanations can be find in https://cli.vuejs.org/config/
module.exports = {