潘超林 7 mēneši atpakaļ
vecāks
revīzija
ab609af0d1

+ 16 - 0
.env.development

@@ -0,0 +1,16 @@
+# 页面标题
+VUE_APP_TITLE = 农商网管理系统
+
+# 开发环境配置
+ENV = 'development'
+
+# 农商云管理系统/开发环境
+VUE_APP_BASE_API = '/api'
+
+
+#本地测试打印机绑定
+VUE_APP_PRINT_SWITCH = true
+
+VUE_APP_NSY_UPLOAD_API="https://app.sxdirectpurchase.com"
+# 路由懒加载
+VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 17 - 0
.env.production

@@ -0,0 +1,17 @@
+# 页面标题
+VUE_APP_TITLE = 农商网管理系统
+
+# 生产环境配置
+ENV = 'production'
+
+# 农商云管理系统/生产环境
+VUE_APP_BASE_API = '/api'
+
+#本地测试打印机绑定
+VUE_APP_PRINT_SWITCH = false
+
+VUE_APP_NSY_UPLOAD_API="https://app.sxdirectpurchase.com"
+
+# 农商云管理系统/生产环境
+VUE_APP_BASE_URL_BASE = '/manage'
+

+ 10 - 0
.env.test

@@ -0,0 +1,10 @@
+# 页面标题
+VUE_APP_TITLE = 农商网管理系统
+
+NODE_ENV = production
+
+# 测试环境配置
+ENV = 'test'
+
+# 农商云管理系统/测试环境
+VUE_APP_BASE_API = '/api'

+ 25 - 0
.gitignore

@@ -0,0 +1,25 @@
+.DS_Store
+node_modules
+/dist
+node_modules/
+node_modules
+dist
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 5 - 0
babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 30049 - 0
package-lock.json


+ 52 - 0
package.json

@@ -0,0 +1,52 @@
+{
+  "name": "order-web-vue",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "dev": "vue-cli-service serve",
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "axios": "0.24.0",
+    "core-js": "^3.6.5",
+    "element-ui": "2.15.14",
+    "js-cookie": "3.0.1",
+    "moment": "^2.30.1",
+    "nprogress": "^0.2.0",
+    "vue": "^2.6.11",
+    "vue-router": "3.4.9"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "~4.5.15",
+    "@vue/cli-plugin-eslint": "~4.5.15",
+    "@vue/cli-service": "~4.5.15",
+    "babel-eslint": "^10.1.0",
+    "compression-webpack-plugin": "6.1.2",
+    "eslint": "^6.7.2",
+    "eslint-plugin-vue": "^6.2.2",
+    "vue-template-compiler": "^2.6.11",
+    "sass": "1.32.13",
+    "sass-loader": "10.1.1"
+  },
+  "eslintConfig": {
+    "root": true,
+    "env": {
+      "node": true
+    },
+    "extends": [
+      "plugin:vue/essential",
+      "eslint:recommended"
+    ],
+    "parserOptions": {
+      "parser": "babel-eslint"
+    },
+    "rules": {}
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not dead"
+  ]
+}

BIN
public/favicon.ico


BIN
public/favicon.png


+ 21 - 0
public/index.html

@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="">
+
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width,initial-scale=1.0">
+  <link rel="icon" href="<%= BASE_URL %>favicon.png">
+  <title>农商网订单管理系统</title>
+</head>
+
+<body>
+  <noscript>
+    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
+        Please enable it to continue.</strong>
+  </noscript>
+  <div id="app"></div>
+  <!-- built files will be auto injected -->
+</body>
+
+</html>

+ 18 - 0
src/App.vue

@@ -0,0 +1,18 @@
+<template>
+  <div id="app">
+    <router-view />
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'App',
+}
+</script>
+
+<style>
+body{
+  padding: 0px;
+  margin: 0px;
+}
+</style>

+ 30 - 0
src/api/equipment.js

@@ -0,0 +1,30 @@
+import request from '@/utils/request'
+
+export function printerList(data) {
+    return request({
+        url: `/user/app/v1/printer/list?page=${data.page}&size=${data.size}&sn=${data.sn || ''}&name=${data.name || ''}`,
+        method: 'get',
+    })
+}
+
+
+export function printer(data) {
+    return request({
+        url: `/user/app/v1/printer`,
+        method: 'post',
+        data: data
+    })
+}
+export function printerEdit(data) {
+    return request({
+        url: `/user/app/v1/printer`,
+        method: 'put',
+        data: data
+    })
+}
+export function printerRemove(id) {
+    return request({
+        url: `/user/app/v1/printer/` + id,
+        method: 'delete',
+    })
+}

+ 41 - 0
src/api/login.js

@@ -0,0 +1,41 @@
+import request from '@/utils/request'
+
+// 注册方法
+export function register(data) {
+  return request({
+    url: '/register',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data: data
+  })
+}
+
+
+// 
+export function getSMSCode(phone) {
+  return request({
+    url: '/third/app/v1/third/getSMSCode?phone=' + phone,
+    method: 'post',
+  })
+}
+
+export function phoneLogin(phone, code) {
+  return request({
+    url: '/user/app/v1/user/phoneLogin?phone=' + phone + '&code=' + code,
+    method: 'post',
+  })
+}
+
+// 获取验证码
+export function getCodeImg() {
+  return request({
+    url: '/captchaImage',
+    headers: {
+      isToken: false
+    },
+    method: 'get',
+    timeout: 20000
+  })
+}

+ 27 - 0
src/api/order.js

@@ -0,0 +1,27 @@
+import request from '@/utils/request'
+
+export function orderlist(data) {
+    return request({
+        url: `/order/app/v1/seller/order/list-v2?page=${data.page}&size=${data.size}&orderStatus=${data.orderStatus}&scopes=${data.scopes}`,
+        method: 'get',
+    })
+}
+export function orderDetail(id) {
+    return request({
+        url: `/order/app/v1/seller/order/detail-v2/` + id,
+        method: 'get',
+    })
+}
+export function printerPrint(data) {
+    return request({
+        url: `/user/app/v1/printer/print`,
+        method: 'post',
+        data: data
+    })
+}
+export function invoiceV2(id) {
+    return request({
+        url: `/order/app/v1/seller/order/invoice-v2/` + id,
+        method: 'get',
+    })
+}

BIN
src/assets/back.png


BIN
src/assets/logo.png


BIN
src/assets/password.png


BIN
src/assets/title.png


BIN
src/assets/user.png


+ 93 - 0
src/layout/index.vue

@@ -0,0 +1,93 @@
+<template>
+  <div class="app-wrapper" style="height: 100vh">
+    <el-container style="height: 100%">
+      <el-menu
+        text-color="#fff"
+        background-color="#001529"
+        :collapse="isCollapse"
+        :default-active="$router.currentRoute.fullPath"
+        :router="true"
+        class="el-menu-vertical-demo"
+      >
+        <el-menu-item :index="item.path" v-for="(item, index) in routeList" :key="index" style="padding-right:40px">
+          <i class="el-icon-menu"></i>
+          <span slot="title">{{ item.meta.title }}</span>
+        </el-menu-item>
+      </el-menu>
+      <el-container>
+        <el-header class="header">
+          <i
+            class="el-icon-s-fold"
+            style="font-size: 20px"
+            @click="ChangeIcon(true)"
+            v-if="!isCollapse"
+          ></i>
+          <i
+            class="el-icon-s-unfold"
+            style="font-size: 20px"
+            @click="ChangeIcon(false)"
+            v-if="isCollapse"
+          ></i>
+          <div
+            style="
+              margin-left: 20px;
+              display: flex;
+              width: 100%;
+              justify-content: space-between;
+            "
+          >
+            <div>农商网订单管理系统</div>
+            <div @click="close" style="cursor: pointer">退出登录</div>
+          </div>
+        </el-header>
+        <el-main>
+          <router-view></router-view>
+        </el-main>
+      </el-container>
+    </el-container>
+  </div>
+</template>
+
+<script>
+import Cookies from "js-cookie";
+export default {
+  name: "Layout",
+  data() {
+    return {
+      isCollapse: false,
+      routeList: [],
+    };
+  },
+  mounted() {
+    console.log(this.$router.currentRoute.fullPath);
+
+    this.routeInit();
+  },
+  methods: {
+    close() {
+      Cookies.remove("Admin-Token");
+      localStorage.removeItem("userInfo");
+      location.reload();
+    },
+    routeInit() {
+      let list = this.$router.options.routes;
+      list.forEach((e) => {
+        if (e.redirect == "index") {
+          this.routeList = e.children;
+        }
+      });
+    },
+    ChangeIcon(type) {
+      this.isCollapse = type;
+    },
+  },
+};
+</script>
+<style scoped>
+.header {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  background: #f4f4f4;
+}
+</style>

+ 21 - 0
src/main.js

@@ -0,0 +1,21 @@
+import Vue from 'vue'
+import App from './App.vue'
+import Cookies from 'js-cookie'
+import router from './router'
+import './permission' // permission control
+import Element from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css';
+import moment from 'moment'
+import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
+Vue.prototype.resetForm = resetForm
+// import './assets/styles/element-variables.scss'
+Vue.prototype.$moment = moment
+Vue.use(Element, {
+  size: Cookies.get('size') || 'medium' // set element-ui default size
+})
+Vue.config.productionTip = false
+new Vue({
+  el: '#app',
+  router,
+  render: h => h(App),
+}).$mount('#app')

+ 60 - 0
src/permission.js

@@ -0,0 +1,60 @@
+import router from './router'
+import { Message } from 'element-ui'
+import NProgress from 'nprogress'
+import 'nprogress/nprogress.css'
+import { getToken } from '@/utils/auth'
+// import { isRelogin } from '../utils/request'
+
+NProgress.configure({ showSpinner: false })
+
+const whiteList = ['/login', '/register']
+
+router.beforeEach((to, from, next) => {
+  NProgress.start()
+  console.log('123123', getToken());
+
+  if (getToken()) {
+    // to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
+    /* has token*/
+    if (to.path === '/login') {
+      next({ path: '/' })
+      NProgress.done()
+    } else if (whiteList.indexOf(to.path) !== -1) {
+      next()
+    } else {
+      // next({ path: '/index' })
+      // if (store.getters.roles.length === 0) {
+      // isRelogin.show = true
+      // 判断当前用户是否已拉取完user_info信息
+      // store.dispatch('GetInfo').then(() => {
+      //   isRelogin.show = false
+      //   store.dispatch('GenerateRoutes').then(accessRoutes => {
+      //     // 根据roles权限生成可访问的路由表
+      //     router.addRoutes(accessRoutes) // 动态添加可访问路由表
+      //     next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
+      //   })
+      // }).catch(err => {
+      //   store.dispatch('LogOut').then(() => {
+      //     Message.error(err)
+      //     next({ path: '/' })
+      //   })
+      // })
+      // } else {
+      next()
+      // }
+    }
+  } else {
+    // 没有token
+    if (whiteList.indexOf(to.path) !== -1) {
+      // 在免登录白名单,直接进入
+      next()
+    } else {
+      next(`/login?redirect=${encodeURIComponent(to.fullPath)}`) // 否则全部重定向到登录页
+      NProgress.done()
+    }
+  }
+})
+
+router.afterEach(() => {
+  NProgress.done()
+})

+ 60 - 0
src/plugins/auth.js

@@ -0,0 +1,60 @@
+import store from '@/store'
+
+function authPermission(permission) {
+  const all_permission = "*:*:*";
+  const permissions = store.getters && store.getters.permissions
+  if (permission && permission.length > 0) {
+    return permissions.some(v => {
+      return all_permission === v || v === permission
+    })
+  } else {
+    return false
+  }
+}
+
+function authRole(role) {
+  const super_admin = "admin";
+  const roles = store.getters && store.getters.roles
+  if (role && role.length > 0) {
+    return roles.some(v => {
+      return super_admin === v || v === role
+    })
+  } else {
+    return false
+  }
+}
+
+export default {
+  // 验证用户是否具备某权限
+  hasPermi(permission) {
+    return authPermission(permission);
+  },
+  // 验证用户是否含有指定权限,只需包含其中一个
+  hasPermiOr(permissions) {
+    return permissions.some(item => {
+      return authPermission(item)
+    })
+  },
+  // 验证用户是否含有指定权限,必须全部拥有
+  hasPermiAnd(permissions) {
+    return permissions.every(item => {
+      return authPermission(item)
+    })
+  },
+  // 验证用户是否具备某角色
+  hasRole(role) {
+    return authRole(role);
+  },
+  // 验证用户是否含有指定角色,只需包含其中一个
+  hasRoleOr(roles) {
+    return roles.some(item => {
+      return authRole(item)
+    })
+  },
+  // 验证用户是否含有指定角色,必须全部拥有
+  hasRoleAnd(roles) {
+    return roles.every(item => {
+      return authRole(item)
+    })
+  }
+}

+ 77 - 0
src/plugins/cache.js

@@ -0,0 +1,77 @@
+const sessionCache = {
+  set (key, value) {
+    if (!sessionStorage) {
+      return
+    }
+    if (key != null && value != null) {
+      sessionStorage.setItem(key, value)
+    }
+  },
+  get (key) {
+    if (!sessionStorage) {
+      return null
+    }
+    if (key == null) {
+      return null
+    }
+    return sessionStorage.getItem(key)
+  },
+  setJSON (key, jsonValue) {
+    if (jsonValue != null) {
+      this.set(key, JSON.stringify(jsonValue))
+    }
+  },
+  getJSON (key) {
+    const value = this.get(key)
+    if (value != null) {
+      return JSON.parse(value)
+    }
+  },
+  remove (key) {
+    sessionStorage.removeItem(key);
+  }
+}
+const localCache = {
+  set (key, value) {
+    if (!localStorage) {
+      return
+    }
+    if (key != null && value != null) {
+      localStorage.setItem(key, value)
+    }
+  },
+  get (key) {
+    if (!localStorage) {
+      return null
+    }
+    if (key == null) {
+      return null
+    }
+    return localStorage.getItem(key)
+  },
+  setJSON (key, jsonValue) {
+    if (jsonValue != null) {
+      this.set(key, JSON.stringify(jsonValue))
+    }
+  },
+  getJSON (key) {
+    const value = this.get(key)
+    if (value != null) {
+      return JSON.parse(value)
+    }
+  },
+  remove (key) {
+    localStorage.removeItem(key);
+  }
+}
+
+export default {
+  /**
+   * 会话级缓存
+   */
+  session: sessionCache,
+  /**
+   * 本地缓存
+   */
+  local: localCache
+}

+ 79 - 0
src/plugins/download.js

@@ -0,0 +1,79 @@
+import axios from 'axios'
+import {Loading, Message} from 'element-ui'
+import { saveAs } from 'file-saver'
+import { getToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { blobValidate } from "@/utils/ruoyi";
+
+const baseURL = process.env.VUE_APP_BASE_API
+let downloadLoadingInstance;
+
+export default {
+  name(name, isDelete = true) {
+    var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete
+    axios({
+      method: 'get',
+      url: url,
+      responseType: 'blob',
+      headers: { 'Auth': 'Bearer ' + getToken() }
+    }).then((res) => {
+      const isBlob = blobValidate(res.data);
+      if (isBlob) {
+        const blob = new Blob([res.data])
+        this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
+      } else {
+        this.printErrMsg(res.data);
+      }
+    })
+  },
+  resource(resource) {
+    var url = baseURL + "/common/download/resource?resource=" + encodeURIComponent(resource);
+    axios({
+      method: 'get',
+      url: url,
+      responseType: 'blob',
+      headers: { 'Auth': 'Bearer ' + getToken() }
+    }).then((res) => {
+      const isBlob = blobValidate(res.data);
+      if (isBlob) {
+        const blob = new Blob([res.data])
+        this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
+      } else {
+        this.printErrMsg(res.data);
+      }
+    })
+  },
+  zip(url, name) {
+    var url = baseURL + url
+    downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
+    axios({
+      method: 'get',
+      url: url,
+      responseType: 'blob',
+      headers: { 'Auth': 'Bearer ' + getToken() }
+    }).then((res) => {
+      const isBlob = blobValidate(res.data);
+      if (isBlob) {
+        const blob = new Blob([res.data], { type: 'application/zip' })
+        this.saveAs(blob, name)
+      } else {
+        this.printErrMsg(res.data);
+      }
+      downloadLoadingInstance.close();
+    }).catch((r) => {
+      console.error(r)
+      Message.error('下载文件出现错误,请联系管理员!')
+      downloadLoadingInstance.close();
+    })
+  },
+  saveAs(text, name, opts) {
+    saveAs(text, name, opts);
+  },
+  async printErrMsg(data) {
+    const resText = await data.text();
+    const rspObj = JSON.parse(resText);
+    const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
+    Message.error(errMsg);
+  }
+}
+

+ 20 - 0
src/plugins/index.js

@@ -0,0 +1,20 @@
+import tab from './tab'
+import auth from './auth'
+import cache from './cache'
+import modal from './modal'
+import download from './download'
+
+export default {
+  install(Vue) {
+    // 页签操作
+    Vue.prototype.$tab = tab
+    // 认证对象
+    Vue.prototype.$auth = auth
+    // 缓存对象
+    Vue.prototype.$cache = cache
+    // 模态框对象
+    Vue.prototype.$modal = modal
+    // 下载文件
+    Vue.prototype.$download = download
+  }
+}

+ 83 - 0
src/plugins/modal.js

@@ -0,0 +1,83 @@
+import { Message, MessageBox, Notification, Loading } from 'element-ui'
+
+let loadingInstance;
+
+export default {
+  // 消息提示
+  msg(content) {
+    Message.info(content)
+  },
+  // 错误消息
+  msgError(content) {
+    Message.error(content)
+  },
+  // 成功消息
+  msgSuccess(content) {
+    Message.success(content)
+  },
+  // 警告消息
+  msgWarning(content) {
+    Message.warning(content)
+  },
+  // 弹出提示
+  alert(content) {
+    MessageBox.alert(content, "系统提示")
+  },
+  // 错误提示
+  alertError(content) {
+    MessageBox.alert(content, "系统提示", { type: 'error' })
+  },
+  // 成功提示
+  alertSuccess(content) {
+    MessageBox.alert(content, "系统提示", { type: 'success' })
+  },
+  // 警告提示
+  alertWarning(content) {
+    MessageBox.alert(content, "系统提示", { type: 'warning' })
+  },
+  // 通知提示
+  notify(content) {
+    Notification.info(content)
+  },
+  // 错误通知
+  notifyError(content) {
+    Notification.error(content);
+  },
+  // 成功通知
+  notifySuccess(content) {
+    Notification.success(content)
+  },
+  // 警告通知
+  notifyWarning(content) {
+    Notification.warning(content)
+  },
+  // 确认窗体
+  confirm(content) {
+    return MessageBox.confirm(content, "系统提示", {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: "warning",
+    })
+  },
+  // 提交内容
+  prompt(content) {
+    return MessageBox.prompt(content, "系统提示", {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: "warning",
+    })
+  },
+  // 打开遮罩层
+  loading(content) {
+    loadingInstance = Loading.service({
+      lock: true,
+      text: content,
+      spinner: "el-icon-loading",
+      background: "rgba(0, 0, 0, 0.7)",
+    })
+  },
+  // 关闭遮罩层
+  closeLoading() {
+    loadingInstance.close();
+  }
+}

+ 71 - 0
src/plugins/tab.js

@@ -0,0 +1,71 @@
+import store from '@/store'
+import router from '@/router';
+
+export default {
+  // 刷新当前tab页签
+  refreshPage(obj) {
+    const { path, query, matched } = router.currentRoute;
+    if (obj === undefined) {
+      matched.forEach((m) => {
+        if (m.components && m.components.default && m.components.default.name) {
+          if (!['Layout', 'ParentView'].includes(m.components.default.name)) {
+            obj = { name: m.components.default.name, path: path, query: query };
+          }
+        }
+      });
+    }
+    return store.dispatch('tagsView/delCachedView', obj).then(() => {
+      const { path, query } = obj
+      router.replace({
+        path: '/redirect' + path,
+        query: query
+      })
+    })
+  },
+  // 关闭当前tab页签,打开新页签
+  closeOpenPage(obj) {
+    store.dispatch("tagsView/delView", router.currentRoute);
+    if (obj !== undefined) {
+      return router.push(obj);
+    }
+  },
+  // 关闭指定tab页签
+  closePage(obj) {
+    if (obj === undefined) {
+      return store.dispatch('tagsView/delView', router.currentRoute).then(({ visitedViews }) => {
+        const latestView = visitedViews.slice(-1)[0]
+        if (latestView) {
+          return router.push(latestView.fullPath)
+        }
+        return router.push('/');
+      });
+    }
+    return store.dispatch('tagsView/delView', obj);
+  },
+  // 关闭所有tab页签
+  closeAllPage() {
+    return store.dispatch('tagsView/delAllViews');
+  },
+  // 关闭左侧tab页签
+  closeLeftPage(obj) {
+    return store.dispatch('tagsView/delLeftTags', obj || router.currentRoute);
+  },
+  // 关闭右侧tab页签
+  closeRightPage(obj) {
+    return store.dispatch('tagsView/delRightTags', obj || router.currentRoute);
+  },
+  // 关闭其他tab页签
+  closeOtherPage(obj) {
+    return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute);
+  },
+  // 添加tab页签
+  openPage(title, url, params) {
+    const obj = { path: url, meta: { title: title } }
+    store.dispatch('tagsView/addView', obj);
+    return router.push({ path: url, query: params });
+  },
+  // 修改tab页签
+  updatePage(obj) {
+    return store.dispatch('tagsView/updateVisitedView', obj);
+  }
+}

+ 86 - 0
src/router/index.js

@@ -0,0 +1,86 @@
+
+import Vue from 'vue'   //引入Vue
+import Router from 'vue-router'  //引入vue-router
+Vue.use(Router)  //Vue全局使用Router
+import Layout from '@/layout'
+
+// 公共路由
+export const constantRoutes = [
+    {
+        path: '/redirect',
+        component: Layout,
+        hidden: true,
+        children: [
+            {
+                path: '/redirect/:path(.*)',
+                component: () => import('@/views/redirect')
+            }
+        ]
+    },
+    {
+        path: '/login',
+        name: "login",
+        component: () => import('@/views/login'),
+        hidden: true
+    },
+    {
+        path: '',
+        component: Layout,
+        redirect: 'index',
+        children: [
+            {
+                path: '/index',
+                component: () => import('@/views/index'),
+                name: 'index',
+                meta: { title: '订单列表', icon: 'dashboard', affix: true }
+            },
+            {
+                path: '/equipment',
+                component: () => import('@/views/equipment'),
+                name: 'equipment',
+                meta: { title: '设备管理', icon: 'dashboard', affix: true }
+            },
+
+            // {
+            //     path: 'index',
+            //     component: () => import('@/views/index'),
+            //     name: 'Index',
+            //     meta: { title: '首页', icon: 'dashboard', affix: true }
+            // }
+        ]
+    },
+    // {
+    //     path: '/register',
+    //     component: () => import('@/views/register'),
+    //     hidden: true
+    // },
+    // {
+    //     path: '/404',
+    //     component: () => import('@/views/error/404'),
+    //     hidden: true
+    // },
+    // {
+    //     path: '/401',
+    //     component: () => import('@/views/error/401'),
+    //     hidden: true
+    // },
+
+
+]
+
+
+// 防止连续点击多次路由报错
+let routerPush = Router.prototype.push;
+let routerReplace = Router.prototype.replace;
+// push
+Router.prototype.push = function push(location) {
+    return routerPush.call(this, location).catch(err => err)
+}
+// replace
+Router.prototype.replace = function push(location) {
+    return routerReplace.call(this, location).catch(err => err)
+}
+
+export default new Router({
+    routes: constantRoutes
+})

+ 15 - 0
src/utils/auth.js

@@ -0,0 +1,15 @@
+import Cookies from 'js-cookie'
+
+const TokenKey = 'Admin-Token'
+
+export function getToken() {
+  return Cookies.get(TokenKey)
+}
+
+export function setToken(token) {
+  return Cookies.set(TokenKey, token)
+}
+
+export function removeToken() {
+  return Cookies.remove(TokenKey)
+}

+ 6 - 0
src/utils/errorCode.js

@@ -0,0 +1,6 @@
+export default {
+  '401': '认证失败,无法访问系统资源',
+  '403': '当前操作没有权限',
+  '404': '访问资源不存在',
+  'default': '系统未知错误,请反馈给管理员'
+}

+ 133 - 0
src/utils/request.js

@@ -0,0 +1,133 @@
+import axios from 'axios'
+import { Notification, MessageBox, Message, Loading } from 'element-ui'
+// import store from '@/store'
+import Cookies from "js-cookie";
+
+import { getToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { tansParams, blobValidate } from "@/utils/ruoyi";
+import cache from '@/plugins/cache'
+
+let downloadLoadingInstance;
+// 是否显示重新登录
+export let isRelogin = { show: false };
+
+axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
+// 创建axios实例
+const service = axios.create({
+  // axios中请求配置有baseURL选项,表示请求URL公共部分
+  baseURL: process.env.VUE_APP_BASE_API,
+  // 超时
+  timeout: 10000,
+})
+
+// request拦截器
+service.interceptors.request.use(config => {
+  // 是否需要设置 token
+  const isToken = (config.headers || {}).isToken === false
+  // 是否需要防止数据重复提交
+  const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
+  if (getToken() && !isToken) {
+    config.headers['TokenShop'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
+  }
+  // get请求映射params参数
+  if (config.method === 'get' && config.params) {
+    let url = config.url + '?' + tansParams(config.params);
+    url = url.slice(0, -1);
+    config.params = {};
+    config.url = url;
+  }
+  if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
+    const requestObj = {
+      url: config.url,
+      data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
+      time: new Date().getTime()
+    }
+    const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
+    const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
+    if (requestSize >= limitSize) {
+      console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。')
+      return config;
+    }
+    const sessionObj = cache.session.getJSON('sessionObj')
+    if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
+      cache.session.setJSON('sessionObj', requestObj)
+    } else {
+      const s_url = sessionObj.url;                  // 请求地址
+      const s_data = sessionObj.data;                // 请求数据
+      const s_time = sessionObj.time;                // 请求时间
+      const interval = 1000;                         // 间隔时间(ms),小于此时间视为重复提交
+      if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
+        const message = '数据正在处理,请勿重复提交';
+        console.warn(`[${s_url}]: ` + message)
+        return Promise.reject(new Error(message))
+      } else {
+        cache.session.setJSON('sessionObj', requestObj)
+      }
+    }
+  }
+  return config
+}, error => {
+  console.log(error)
+  Promise.reject(error)
+})
+
+// 响应拦截器
+service.interceptors.response.use(res => {
+  // 未设置状态码则默认成功状态
+  const code = res.data.code || 200;
+  // 获取错误信息
+  const msg = errorCode[code] || res.data.msg || errorCode['default']
+  // 二进制数据则直接返回
+  if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
+    return res.data
+  }
+  if (code === 401 || code == 403) {
+    if (!isRelogin.show) {
+      isRelogin.show = true;
+      MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
+        isRelogin.show = false;
+        // store.dispatch('LogOut').then(() => {
+        Cookies.remove('Admin-Token');
+        localStorage.removeItem('userInfo')
+        // this.$router.push({
+        //   path: '/login'
+        // });
+        location.reload();
+        // })
+      }).catch(() => {
+        isRelogin.show = false;
+      });
+    }
+    return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
+  } else if (code === 500) {
+    Message({ message: msg, type: 'error' })
+    return Promise.reject(new Error(msg))
+  } else if (code === 601) {
+    Message({ message: msg, type: 'warning' })
+    return Promise.reject('error')
+  } else if (code !== 200) {
+    Notification.error({ title: msg })
+    return Promise.reject('error')
+  } else {
+    return res.data
+  }
+},
+  error => {
+    console.log('err' + error)
+    let { message } = error;
+    if (message == "Network Error") {
+      message = "后端接口连接异常";
+    } else if (message.includes("timeout")) {
+      message = "系统接口请求超时";
+    } else if (message.includes("Request failed with status code")) {
+      message = "系统接口" + message.substr(message.length - 3) + "异常";
+    }
+    Message({ message: message, type: 'error', duration: 5 * 1000 })
+    return Promise.reject(error)
+  }
+)
+
+
+
+export default service

+ 235 - 0
src/utils/ruoyi.js

@@ -0,0 +1,235 @@
+
+
+/**
+ * 通用js方法封装处理
+ * Copyright (c) 2019 ruoyi
+ */
+
+// 日期格式化
+export function parseTime(time, pattern) {
+  if (arguments.length === 0 || !time) {
+    return null
+  }
+  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
+  let date
+  if (typeof time === 'object') {
+    date = time
+  } else {
+    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
+      time = parseInt(time)
+    } else if (typeof time === 'string') {
+      time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
+    }
+    if ((typeof time === 'number') && (time.toString().length === 10)) {
+      time = time * 1000
+    }
+    date = new Date(time)
+  }
+  const formatObj = {
+    y: date.getFullYear(),
+    m: date.getMonth() + 1,
+    d: date.getDate(),
+    h: date.getHours(),
+    i: date.getMinutes(),
+    s: date.getSeconds(),
+    a: date.getDay()
+  }
+  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
+    let value = formatObj[key]
+    // Note: getDay() returns 0 on Sunday
+    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
+    if (result.length > 0 && value < 10) {
+      value = '0' + value
+    }
+    return value || 0
+  })
+  return time_str
+}
+
+// 表单重置
+export function resetForm(refName) {
+  if (this.$refs[refName]) {
+    this.$refs[refName].resetFields();
+  }
+}
+
+// 添加日期范围
+export function addDateRange(params, dateRange, propName) {
+  let search = params;
+  search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
+  dateRange = Array.isArray(dateRange) ? dateRange : [];
+  if (typeof (propName) === 'undefined') {
+    search.params['beginTime'] = dateRange[0];
+    search.params['endTime'] = dateRange[1];
+  } else {
+    search.params['begin' + propName] = dateRange[0];
+    search.params['end' + propName] = dateRange[1];
+  }
+  return search;
+}
+
+// 回显数据字典
+export function selectDictLabel(datas, value) {
+  if (value === undefined) {
+    return "";
+  }
+  var actions = [];
+  Object.keys(datas).some((key) => {
+    if (datas[key].value == ('' + value) || datas[key].typeCode == ('' + value) || datas[key].itemValue == (
+      '' + value)) {
+      actions.push(datas[key].label || datas[key].name || datas[key].typeName || datas[key].title ||
+        datas[key].itemText);
+      return true;
+    }
+  })
+  if (actions.length === 0) {
+    actions.push(value);
+  }
+  return actions.join('');
+}
+
+// 回显数据字典(字符串、数组)
+export function selectDictLabels(datas, value, separator) {
+  if (value === undefined || value.length === 0) {
+    return "";
+  }
+  if (Array.isArray(value)) {
+    value = value.join(",");
+  }
+  var actions = [];
+  var currentSeparator = undefined === separator ? "," : separator;
+  var temp = value.split(currentSeparator);
+  Object.keys(value.split(currentSeparator)).some((val) => {
+    var match = false;
+    Object.keys(datas).some((key) => {
+      if (datas[key].value == ('' + temp[val])) {
+        actions.push(datas[key].label + currentSeparator);
+        match = true;
+      }
+    })
+    if (!match) {
+      actions.push(temp[val] + currentSeparator);
+    }
+  })
+  return actions.join('').substring(0, actions.join('').length - 1);
+}
+
+// 字符串格式化(%s )
+export function sprintf(str) {
+  var args = arguments, flag = true, i = 1;
+  str = str.replace(/%s/g, function () {
+    var arg = args[i++];
+    if (typeof arg === 'undefined') {
+      flag = false;
+      return '';
+    }
+    return arg;
+  });
+  return flag ? str : '';
+}
+
+// 转换字符串,undefined,null等转化为""
+export function parseStrEmpty(str) {
+  if (!str || str == "undefined" || str == "null") {
+    return "";
+  }
+  return str;
+}
+
+// 数据合并
+export function mergeRecursive(source, target) {
+  for (var p in target) {
+    try {
+      if (target[p].constructor == Object) {
+        source[p] = mergeRecursive(source[p], target[p]);
+      } else {
+        source[p] = target[p];
+      }
+    } catch (e) {
+      source[p] = target[p];
+    }
+  }
+  return source;
+};
+
+/**
+ * 构造树型结构数据
+ * @param {*} data 数据源
+ * @param {*} id id字段 默认 'id'
+ * @param {*} parentId 父节点字段 默认 'parentId'
+ * @param {*} children 孩子节点字段 默认 'children'
+ */
+export function handleTree(data, id, parentId, children) {
+  let config = {
+    id: id || 'id',
+    parentId: parentId || 'parentId',
+    childrenList: children || 'children'
+  };
+
+  var childrenListMap = {};
+  var nodeIds = {};
+  var tree = [];
+
+  for (let d of data) {
+    let parentId = d[config.parentId];
+    if (childrenListMap[parentId] == null) {
+      childrenListMap[parentId] = [];
+    }
+    nodeIds[d[config.id]] = d;
+    childrenListMap[parentId].push(d);
+  }
+
+  for (let d of data) {
+    let parentId = d[config.parentId];
+    if (nodeIds[parentId] == null) {
+      tree.push(d);
+    }
+  }
+
+  for (let t of tree) {
+    adaptToChildrenList(t);
+  }
+
+  function adaptToChildrenList(o) {
+    if (childrenListMap[o[config.id]] !== null) {
+      o[config.childrenList] = childrenListMap[o[config.id]];
+    }
+    if (o[config.childrenList]) {
+      for (let c of o[config.childrenList]) {
+        adaptToChildrenList(c);
+      }
+    }
+  }
+  return tree;
+}
+
+/**
+* 参数处理
+* @param {*} params  参数
+*/
+export function tansParams(params) {
+  let result = ''
+  for (const propName of Object.keys(params)) {
+    const value = params[propName];
+    var part = encodeURIComponent(propName) + "=";
+    if (value !== null && value !== "" && typeof (value) !== "undefined") {
+      if (typeof value === 'object') {
+        for (const key of Object.keys(value)) {
+          if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
+            let params = propName + '[' + key + ']';
+            var subPart = encodeURIComponent(params) + "=";
+            result += subPart + encodeURIComponent(value[key]) + "&";
+          }
+        }
+      } else {
+        result += part + encodeURIComponent(value) + "&";
+      }
+    }
+  }
+  return result
+}
+
+// 验证是否为blob格式
+export function blobValidate(data) {
+  return data.type !== 'application/json'
+}

+ 408 - 0
src/views/equipment.vue

@@ -0,0 +1,408 @@
+<template>
+  <div>
+    <el-row :gutter="20">
+      <!--用户数据-->
+      <el-col :span="24" :xs="24">
+        <el-form
+          :model="queryParams"
+          ref="queryForm"
+          size="small"
+          :inline="true"
+          label-width="100px"
+        >
+          <el-form-item label="打印机编号" prop="sn">
+            <el-input
+              v-model="queryParams.sn"
+              placeholder="请输入打印机编号"
+              clearable
+              style="width: 180px"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+
+          <el-form-item label="打印机名称" prop="name">
+            <el-input
+              v-model="queryParams.name"
+              placeholder="请输入打印机名称"
+              clearable
+              style="width: 180px"
+              @keyup.enter.native="handleQuery"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button
+              type="primary"
+              icon="el-icon-search"
+              size="mini"
+              @click="handleQuery"
+              >搜索</el-button
+            >
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
+              >重置</el-button
+            >
+          </el-form-item>
+        </el-form>
+        <el-button type="primary" size="mini" @click="handleAdd">新增设备</el-button>
+        <el-table v-loading="loading" :data="tableList">
+          <el-table-column
+            label="用户ID"
+            align="center"
+            prop="userId"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column
+            label="打印机编号"
+            align="center"
+            prop="sn"
+            :show-overflow-tooltip="true"
+          />
+
+          <el-table-column label="打印机key" align="center" prop="pkey">
+          </el-table-column>
+
+          <el-table-column label="打印机名称" align="center" prop="name">
+          </el-table-column>
+
+          <el-table-column label="自动切刀开关" align="center">
+            <template slot-scope="scope">
+              {{ scope.row.autocut == 1 ? "开" : "关" }}
+              <!-- <el-switch
+                v-model="scope.row.autocut"
+                active-text="开"
+                inactive-text="关"
+                :active-value="1"
+                :inactive-value="0"
+              >
+              </el-switch> -->
+            </template>
+          </el-table-column>
+          <el-table-column label="语音开关" align="center">
+            <template slot-scope="scope">
+              {{
+                scope.row.voice == "N"
+                  ? "关"
+                  : scope.row.voice == "Y"
+                  ? "滴滴滴"
+                  : scope.row.voice == "U"
+                  ? "小语音"
+                  : scope.row.voice == "V"
+                  ? "中语音"
+                  : scope.row.voice == "W"
+                  ? "大语音"
+                  : ""
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column label="是否在线" align="center">
+            <template slot-scope="scope">
+              <el-tag type="success" v-if="scope.row.online == 1">在线</el-tag>
+              <el-tag type="warning" v-if="scope.row.online == 0">离线</el-tag>
+            </template>
+          </el-table-column>
+
+          <el-table-column
+            label="备注"
+            align="center"
+            prop="remark"
+            :show-overflow-tooltip="true"
+          >
+          </el-table-column>
+          <el-table-column
+            label="操作"
+            align="center"
+            prop="orderStatus"
+            :show-overflow-tooltip="true"
+          >
+            <template slot-scope="scope">
+              <el-button size="mini" type="text" @click="handleEdit(scope.row)"
+                >编辑</el-button
+              >
+              <el-button
+                size="mini"
+                type="text"
+                style="color: red"
+                @click="handleRemove(scope.row)"
+                >删除</el-button
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+        <div style="text-align: right; margin-top: 10px" v-if="!loading">
+          <el-pagination
+            background
+            layout="prev, pager, next"
+            :total="pagination.total"
+            @current-change="handleCurrentChange"
+          >
+          </el-pagination>
+        </div>
+      </el-col>
+    </el-row>
+    <!-- 添加或修改用户配置对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="800px" @close="resetQuery">
+      <el-form
+        :model="form"
+        ref="form"
+        size="small"
+        :rules="rules"
+        :inline="true"
+        label-width="100px"
+      >
+        <el-row :gutter="20">
+          <!--用户数据-->
+          <el-col :span="12" :xs="12" v-if="type == ''">
+            <el-form-item label="打印机编号" prop="sn">
+              <el-input
+                v-model="form.sn"
+                placeholder="请输入打印机编号"
+                clearable
+                style="width: 100%"
+                @keyup.enter.native="handleQuery"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" :xs="12" v-if="type == ''">
+            <el-form-item label="打印机Key" prop="pkey">
+              <el-input
+                v-model="form.pkey"
+                placeholder="请输入打印机Key"
+                clearable
+                style="width: 100%"
+                @keyup.enter.native="handleQuery"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" :xs="12">
+            <el-form-item label="打印机名称" prop="name">
+              <el-input
+                v-model="form.name"
+                placeholder="请输入打印机名称"
+                clearable
+                style="width: 100%"
+                @keyup.enter.native="handleQuery"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" :xs="12">
+            <el-form-item label="语音开关" prop="voice">
+              <el-select v-model="form.voice" placeholder="请选择">
+                <el-option label="关" value="N" />
+                <el-option label="滴滴滴" value="Y" />
+                <el-option label="小语音" value="U" />
+                <el-option label="中语音" value="V" />
+                <el-option label="大语音" value="W" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12" :xs="12">
+            <el-form-item label="自动切刀" prop="autocut">
+              <el-switch
+                v-model="form.autocut"
+                active-text="开"
+                inactive-text="关"
+                :active-value="1"
+                :inactive-value="0"
+              >
+              </el-switch>
+            </el-form-item>
+          </el-col>
+
+          <el-col :span="12" :xs="12">
+            <el-form-item label="备注" prop="remark">
+              <el-input
+                v-model="form.remark"
+                placeholder="请输入备注"
+                clearable
+                style="width: 100%"
+                @keyup.enter.native="handleQuery"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template slot="footer">
+        <div>
+          <el-button type="primary" size="mini" @click="submitForm">确定</el-button>
+          <el-button size="mini" @click="resetQuery">取消</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { printerList, printer, printerRemove, printerEdit } from "@/api/equipment.js";
+export default {
+  data() {
+    return {
+      isCollapse: false,
+      menuIndex: 1,
+      queryParams: {
+        sn: "",
+        name: "",
+        page: 1,
+        size: 10,
+      },
+      form: {
+        pkey: null,
+        sn: null,
+        name: "",
+        autocut: 0,
+        voice: "",
+        remark: "",
+      },
+      open: false,
+      loading: false,
+      tableList: [],
+      pagination: {
+        total: 0,
+        size: 10,
+        page: 1,
+      },
+      loading: false,
+      title: "",
+      rules: {
+        name: [{ required: true, message: "打印机名称不能为空", trigger: "blur" }],
+        sn: [{ required: true, message: "打印机编号不能为空", trigger: "change" }],
+        pkey: [{ required: true, message: "打印机key不能为空", trigger: "change" }],
+      },
+      type: "",
+    };
+  },
+  mounted() {
+    this.getList();
+  },
+  methods: {
+    handleAdd() {
+      this.type = "";
+      this.title = "新增设备";
+      this.form = {
+        pkey: null,
+        sn: null,
+        name: "",
+        autocut: 0,
+        voice: "",
+        remark: "",
+      };
+      const debugMode = process.env.VUE_APP_PRINT_SWITCH;
+      if (debugMode) {
+        this.form["type"] = 1;
+      } else {
+        this.form["type"] = 0;
+      }
+      this.open = true;
+    },
+    handleEdit(record) {
+      this.title = "编辑设备";
+      this.type = "edit";
+      this.open = true;
+      this.form = record;
+    },
+    handleRemove(record) {
+      this.$confirm("是否确认删除该设备?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          printerRemove(record.id).then((res) => {
+            if (res.code == 200) {
+              this.$message.success("删除成功!");
+              this.getList();
+              this.queryParams.page = 1;
+            } else {
+              this.$message.success(res.msg);
+              this.getList();
+              this.queryParams.page = 1;
+            }
+          });
+        })
+        .catch(() => {
+          // this.$message({
+          //   type: "info",
+          //   message: "已取消删除",
+          // });
+        });
+    },
+    resetQuery() {
+      this.resetForm("form");
+      this.open = false;
+    },
+    handleCurrentChange(size) {
+      this.queryParams.page = size;
+      this.getList();
+    },
+    submitForm() {
+      this.$refs["form"].validate((valid) => {
+        if (valid) {
+          if (this.form.id) {
+            printerEdit(this.form).then((res) => {
+              if (res.code == 200) {
+                this.open = false;
+                this.$message.success("编辑成功!");
+                this.getList();
+                this.queryParams.page = 1;
+              } else {
+                this.$message.error(res.msg);
+                this.open = false;
+                this.getList();
+                this.queryParams.page = 1;
+              }
+              this.resetForm("form");
+            });
+          } else {
+            printer(this.form).then((res) => {
+              if (res.code == 200) {
+                this.open = false;
+                this.$message.success("添加成功!");
+                this.getList();
+                this.queryParams.page = 1;
+              } else {
+                console.log("1231231", res);
+
+                this.$message.error(res.msg);
+                this.open = false;
+                this.getList();
+                this.queryParams.page = 1;
+              }
+              this.resetForm("form");
+            });
+          }
+        }
+      });
+    },
+    handleQuery() {
+      this.getList();
+      this.queryParams.page = 1;
+    },
+    getList() {
+      this.loading = true;
+      printerList(this.queryParams)
+        .then((res) => {
+          if (res.code == 200) {
+            this.tableList = res.data.content;
+            this.pagination.total = res.data.total;
+            this.loading = false;
+          } else {
+            this.loading = false;
+          }
+        })
+        .catch((err) => {
+          this.$message.error(err);
+          this.loading = false;
+        });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.item {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  .label {
+    min-width: 80px;
+  }
+}
+</style>

+ 839 - 0
src/views/index.vue

@@ -0,0 +1,839 @@
+<template>
+  <div>
+    <el-row :gutter="20">
+      <!--用户数据-->
+      <el-col :span="24" :xs="24">
+        <el-form
+          :model="queryParams"
+          ref="queryForm"
+          size="small"
+          :inline="true"
+          label-width="100px"
+        >
+          <el-form-item label="订单编号" prop="orderSn">
+            <el-input
+              v-model="queryParams.orderSn"
+              placeholder="请输入订单编号"
+              clearable
+              style="width: 180px"
+            />
+          </el-form-item>
+
+          <el-form-item label="订单状态" prop="orderStatus">
+            <el-select
+              v-model="queryParams.orderStatus"
+              placeholder="请选择订单状态"
+              clearable
+              style="width: 180px"
+            >
+              <el-option
+                :label="item.label"
+                :value="item.value"
+                v-for="(item, index) in orderStatusList"
+                :key="index"
+              />
+            </el-select>
+          </el-form-item>
+
+          <!-- <el-form-item label="物流状态" prop="status">
+            <el-select
+              v-model="queryParams.status"
+              placeholder="请选择商品状态"
+              clearable
+              style="width: 180px"
+            >
+              <el-option label="全部" value="" />
+              <el-option label="待支付" value="10" />
+              <el-option label="待装货" value="20" />
+              <el-option label="运送中" value="30" />
+              <el-option label="待签收" value="40" />
+              <el-option label="已完成" value="50" />
+              <el-option label="已取消" value="60" />
+            </el-select>
+          </el-form-item> -->
+          <el-form-item>
+            <el-button
+              type="primary"
+              icon="el-icon-search"
+              size="mini"
+              @click="handleQuery"
+              >搜索</el-button
+            >
+            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
+              >重置</el-button
+            >
+          </el-form-item>
+        </el-form>
+        <el-table v-loading="loading" :data="tableList">
+          <el-table-column
+            label="订单编号"
+            align="center"
+            prop="orderSn"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column
+            label="商品名称"
+            align="center"
+            prop="title"
+            :show-overflow-tooltip="true"
+          />
+
+          <el-table-column label="下单人ID" align="center" prop="createUserId">
+          </el-table-column>
+
+          <el-table-column label="付款金额" align="center" prop="goodsAmount">
+            <template slot-scope="scope">
+              <span>{{
+                (
+                  scope.row.orderItemList[0].orderInfo.goodsAmount +
+                  scope.row.orderItemList[0].orderInfo.serviceFee +
+                  scope.row.orderItemList[0].orderInfo.freightFee
+                ).toFixed(2)
+              }}</span>
+            </template>
+          </el-table-column>
+
+          <el-table-column label="下单时间" align="center" width="200">
+            <template slot-scope="scope">
+              {{
+                scope.row.orderItemList
+                  ? $moment(scope.row.orderItemList[0].orderInfo.createTime).format(
+                      "YYYY-MM-DD hh:mm:ss"
+                    )
+                  : ""
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column label="支付方式" align="center">
+            <template slot-scope="scope">
+              {{
+                scope.row.orderItemList
+                  ? scope.row.orderItemList[0].orderInfo.paymentType == "alipay"
+                    ? "支付宝支付"
+                    : scope.row.orderItemList[0].orderInfo.paymentType == "wechat"
+                    ? "微信支付"
+                    : scope.row.orderItemList[0].orderInfo.paymentType == "card"
+                    ? "银行卡"
+                    : ""
+                  : ""
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column label="支付时间" align="center">
+            <template slot-scope="scope">
+              {{
+                scope.row.orderItemList
+                  ? scope.row.orderItemList[0].orderInfo.paymentTime
+                    ? $moment(scope.row.orderItemList[0].orderInfo.paymentTime).format(
+                        "YYYY-MM-DD hh:mm:ss"
+                      )
+                    : ""
+                  : ""
+              }}
+            </template>
+          </el-table-column>
+
+          <el-table-column
+            label="订单状态"
+            align="center"
+            prop="orderStatus"
+            :show-overflow-tooltip="true"
+          >
+            <template slot-scope="scope">
+              <span>
+                {{
+                  scope.row.orderStatus == 0
+                    ? "待修改"
+                    : scope.row.orderStatus == 10
+                    ? "待付款"
+                    : scope.row.orderStatus == 20
+                    ? "待发货"
+                    : scope.row.orderStatus == 30
+                    ? "待收货"
+                    : scope.row.orderStatus == 40
+                    ? "交易完成"
+                    : scope.row.orderStatus == 50
+                    ? "交易关闭"
+                    : scope.row.orderStatus == 70
+                    ? "已退款"
+                    : scope.row.orderStatus == 110
+                    ? "待装货"
+                    : scope.row.orderStatus == 120
+                    ? "运输中"
+                    : scope.row.orderStatus == 130
+                    ? "待处理售后"
+                    : scope.row.orderStatus == 140
+                    ? "已处理售后"
+                    : ""
+                }}
+              </span>
+            </template>
+          </el-table-column>
+
+          <el-table-column label="收货人手机号" align="center">
+            <template slot-scope="scope">
+              {{
+                scope.row.orderItemList
+                  ? scope.row.orderItemList[0].consigneeAddress.contact.contactMobile
+                  : ""
+              }}
+            </template>
+          </el-table-column>
+          <!-- <el-table-column label="物流状态" align="center"> </el-table-column> -->
+          <el-table-column label="发货时间" align="center"> </el-table-column>
+          <el-table-column
+            label="操作"
+            align="center"
+            prop="orderStatus"
+            :show-overflow-tooltip="true"
+          >
+            <template slot-scope="scope">
+              <el-button size="mini" type="text" @click="handleDetail(scope.row)"
+                >详情</el-button
+              >
+              <el-button size="mini" type="text" @click="printOrder(scope.row)"
+                >打印订单</el-button
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+        <div style="text-align: right; margin-top: 10px" v-if="!loading">
+          <el-pagination
+            background
+            layout="prev, pager, next"
+            :total="pagination.total"
+            :current-page="pagination.page"
+            @current-change="handleCurrentChange"
+          >
+          </el-pagination>
+        </div>
+      </el-col>
+    </el-row>
+    <!-- 添加或修改用户配置对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="1000px">
+      <el-row>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">订单状态</div>
+            <div class="value">
+              <span v-if="form.afterSaleStatus > 0">
+                {{
+                  form.afterSaleStatus == 0
+                    ? "未申请售后"
+                    : form.afterSaleStatus == 1
+                    ? "已申请售后"
+                    : form.afterSaleStatus == 2
+                    ? "售后审核失败"
+                    : form.afterSaleStatus == 3
+                    ? "售后审核成功(退款中)"
+                    : form.afterSaleStatus == 4
+                    ? "退款成功"
+                    : form.afterSaleStatus == 5
+                    ? "退款失败(联系客服处理)"
+                    : ""
+                }}
+              </span>
+              <span v-else>
+                {{
+                  form.orderStatus == 0
+                    ? "待修改"
+                    : form.orderStatus == 10
+                    ? "待支付"
+                    : form.orderStatus == 20
+                    ? "待发货"
+                    : form.orderStatus == 90
+                    ? "正在寻找司机"
+                    : form.orderStatus == 100
+                    ? "等待司机支付保证金"
+                    : form.orderStatus == 110
+                    ? "等待司机装货"
+                    : form.orderStatus == 120
+                    ? "运输中"
+                    : form.orderStatus == 30
+                    ? "已到达"
+                    : form.orderStatus == 40
+                    ? "交易完成"
+                    : form.orderStatus == 50
+                    ? "交易关闭"
+                    : form.orderStatus == 60
+                    ? "退款中"
+                    : form.orderStatus == 70
+                    ? "退款成功"
+                    : form.orderStatus == 80
+                    ? "退款失败"
+                    : form.orderStatus == 130
+                    ? "待处理售后"
+                    : form.orderStatus == 140
+                    ? "已处理售后"
+                    : ""
+                }}
+              </span>
+            </div>
+          </div>
+        </el-col>
+        <!-- <el-col :span="8">
+          <div class="item">
+            <div class="label">物流状态</div>
+            <div class="label">
+              {{
+                form.status == 10
+                  ? "待支付"
+                  : form.status == 20
+                  ? "待装货"
+                  : form.status == 30
+                  ? "运送中"
+                  : form.status == 40
+                  ? "已完成"
+                  : form.status == 50
+                  ? "已完成"
+                  : form.status == 60
+                  ? "已取消"
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col> -->
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">订单类型</div>
+            <div class="label">
+              {{
+                form.orderType == "1"
+                  ? "整车订单"
+                  : form.orderType == "2"
+                  ? "拼车订单"
+                  : form.orderType == "3"
+                  ? "零售订单"
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col>
+      </el-row>
+      <h3 style="font-weight: bold">订单明细</h3>
+      <el-row style="line-height: 30px">
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">商品金额</div>
+            <div class="value">{{ form.orderAmount }} 元</div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">商品数量</div>
+            <div class="value">
+              {{ form.quantity }}
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">运费</div>
+            <div class="value">{{ form.freightFee }}元</div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">平台服务费</div>
+            <div class="value">{{ form.serviceFee }}元</div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">订单备注</div>
+            <div class="value">
+              {{ form.orderRemark }}
+            </div>
+          </div>
+        </el-col>
+      </el-row>
+      <h3 style="font-weight: bold">订单信息</h3>
+      <el-row>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">订单编号</div>
+            <div class="value">
+              {{ form.orderSn }}
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">支付时间</div>
+            <div class="value">
+              {{
+                form.orderItemList
+                  ? $moment(form.orderItemList[0].orderInfo.paymentTime).format(
+                      "YYYY-MM-DD hh:mm:ss"
+                    )
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">支付方式</div>
+            <div class="value">
+              {{
+                form.orderItemList
+                  ? form.orderItemList[0].orderInfo.paymentType == "alipay"
+                    ? "支付宝支付"
+                    : form.orderItemList[0].orderInfo.paymentType == "wechat"
+                    ? "微信支付"
+                    : form.orderItemList[0].orderInfo.paymentType == "card"
+                    ? "银行卡"
+                    : ""
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col>
+      </el-row>
+      <h3 style="font-weight: bold">物流信息</h3>
+      <el-row>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">运单号</div>
+            <div class="value">
+              {{ form.driverInfo ? form.driverInfo.orderDetails.orderSn : "" }}
+            </div>
+          </div>
+        </el-col>
+
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">车长车型</div>
+            <div class="value">
+              {{ form.driverInfo ? form.driverInfo.car.carLength : "" }}米 |
+              {{ form.driverInfo ? form.driverInfo.car.carType : "" }}
+            </div>
+          </div>
+        </el-col>
+        <!-- <el-col :span="8">
+          <div class="item">
+            <div class="label">装货时间</div>
+            <div class="value">
+              {{
+                form.shipmentStartDate
+                  ? $moment(form.shipmentStartDate).format("YYYY-MM-DD hh:mm:ss")
+                  : ""
+              }}-
+              {{
+                form.shipmentEndDate
+                  ? $moment(form.shipmentEndDate).format("YYYY-MM-DD hh:mm:ss")
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">电话号码</div>
+            <div class="value">
+              {{ form.phone }}
+            </div>
+          </div>
+        </el-col> -->
+        <!-- <el-col :span="8">
+          <div class="item">
+            <div class="label">预计送达时间</div>
+            <div class="value">
+              {{
+                form.exceptArriveDate
+                  ? $moment(form.exceptArriveDate).format("YYYY-MM-DD")
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col> -->
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">装货地址</div>
+            <div class="value">
+              {{ form.driverInfo ? form.driverInfo.deliveryAddress.addressDetail : "" }}
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">卸货地址</div>
+            <div class="value">
+              {{ form.driverInfo ? form.driverInfo.consigneeAddress.addressDetail : "" }}
+            </div>
+          </div>
+        </el-col>
+      </el-row>
+
+      <h3 style="font-weight: bold">买家信息</h3>
+      <el-row style="line-height: 30px">
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">收货人</div>
+            <div class="value">
+              {{
+                form.orderItemList
+                  ? form.orderItemList[0].consigneeAddress.contact.contactName
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">收货电话</div>
+            <div class="value">
+              {{
+                form.orderItemList
+                  ? form.orderItemList[0].consigneeAddress.contact.contactMobile
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">收货地址</div>
+            <div class="value">
+              {{
+                form.orderItemList
+                  ? form.orderItemList[0].consigneeAddress.addressName
+                  : ""
+              }}-
+              {{
+                form.orderItemList
+                  ? form.orderItemList[0].consigneeAddress.addressDetail
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="item">
+            <div class="label">买家手机号</div>
+            <div class="value">
+              {{
+                form.orderItemList
+                  ? form.orderItemList[0].consigneeAddress.contact.contactMobile
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col>
+        <!-- <el-col :span="12">
+          <div class="item">
+            <div class="label">仓库名称</div>
+            <div class="value">
+              {{ form.wareHouseName }}
+            </div>
+          </div>
+        </el-col> -->
+      </el-row>
+
+      <h3 style="font-weight: bold">店铺信息</h3>
+      <el-row>
+        <el-col :span="12">
+          <div class="item">
+            <div class="label">店铺名称</div>
+            <div class="value">{{ form.shopInfo ? form.shopInfo.shopName : "" }}</div>
+          </div>
+        </el-col>
+      </el-row>
+      <h3 style="font-weight: bold">发货人信息</h3>
+      <el-row>
+        <el-col :span="12">
+          <div class="item">
+            <div class="label">发货人</div>
+            <div class="value">
+              {{
+                form.orderItemList
+                  ? form.orderItemList[0].deliveryAddress.contact.contactName
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="12">
+          <div class="item">
+            <div class="label">发货人电话</div>
+            <div class="value">
+              {{
+                form.orderItemList
+                  ? form.orderItemList[0].deliveryAddress.contact.contactMobile
+                  : ""
+              }}
+            </div>
+          </div>
+        </el-col>
+      </el-row>
+      <h3 style="font-weight: bold">商品信息</h3>
+
+      <el-row
+        v-for="(item, index) in form.orderItemList ? form.orderItemList[0].goodsInfo : []"
+        :key="index"
+      >
+        <el-col :span="2">
+          <div class="item">
+            <div class="value">
+              <el-image
+                style="width: 60px; height: 60px"
+                :src="item.skuPic"
+                :preview-src-list="[item.skuPic]"
+              >
+              </el-image>
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="6">
+          <div class="item">
+            <div class="label" style="width: 70px">商品名称</div>
+            <div class="value">{{ item.skuName }}</div>
+          </div>
+        </el-col>
+        <el-col :span="6">
+          <div class="item">
+            <div class="label" style="width: 50px">价格</div>
+            <div class="value">{{ item.price }}/{{ item.unit }}</div>
+          </div>
+        </el-col>
+        <el-col :span="4">
+          <div class="item">
+            <div class="label" style="width: 50px">数量</div>
+            <div class="value">{{ item.quantity }}/{{ item.unit }}</div>
+          </div>
+        </el-col>
+        <el-col :span="4">
+          <div class="item">
+            <div class="label" style="width: 50px">金额</div>
+            <div class="value">{{ item.amount }}元</div>
+          </div>
+        </el-col>
+        <el-col :span="6">
+          <div class="item" v-for="(res, i) in item.specsValue" :key="i">
+            <div class="label">{{ res.specsName }}</div>
+            <div class="value">{{ res.specsValue }}</div>
+          </div>
+        </el-col>
+      </el-row>
+    </el-dialog>
+    <!-- 添加或修改用户配置对话框 -->
+    <el-dialog
+      title="订单打印"
+      :visible.sync="dyOpen"
+      width="500px"
+      :close-on-click-modal="false"
+    >
+      <div
+        v-loading="printloading"
+        element-loading-text="正在打印中"
+        element-loading-spinner="el-icon-loading"
+      >
+        <el-form
+          :model="form"
+          ref="print"
+          size="small"
+          :inline="true"
+          label-width="100px"
+        >
+          <el-form-item label="打印设备" prop="sn">
+            <el-select v-model="print.sn" placeholder="请选择">
+              <el-option
+                :label="item.name"
+                :value="item.sn"
+                v-for="(item, index) in printList"
+                :key="index"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="打印次数" prop="sn">
+            <el-input-number v-model="print.times" :min="1"></el-input-number>
+          </el-form-item>
+        </el-form>
+      </div>
+      <template slot="footer">
+        <div>
+          <el-button
+            type="primary"
+            size="mini"
+            @click="printSubmit"
+            :disabled="printloading"
+            >确定</el-button
+          >
+          <el-button size="mini" @click="dyOpen = false" :disabled="printloading"
+            >取消</el-button
+          >
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { printerList } from "@/api/equipment.js";
+import { orderlist, orderDetail, printerPrint, invoiceV2 } from "@/api/order.js";
+export default {
+  data() {
+    return {
+      isCollapse: false,
+      menuIndex: 1,
+      queryParams: {
+        orderSn: "",
+        status: "",
+        wareHouseId: "",
+        page: 1,
+        size: 10,
+        orderStatus: "ALL",
+        scopes: "1,2",
+      },
+      dyOpen: false,
+      orderStatusList: [
+        {
+          label: "全部",
+          value: "ALL",
+        },
+        {
+          label: "待修改",
+          value: "WAIT_FIX",
+        },
+        {
+          label: "待支付",
+          value: "WAIT_PAY",
+        },
+        {
+          label: "待发货",
+          value: "WAIT_DELIVERY",
+        },
+        {
+          label: "待收货",
+          value: "WAIT_RECEIVE",
+        },
+        {
+          label: "待评价",
+          value: "WAIT_COMMENT",
+        },
+        {
+          label: "取消/售后 ",
+          value: "CANCEL",
+        },
+        {
+          label: "等待司机接单",
+          value: "WAIT_DRIVER_ERCEIVE",
+        },
+        {
+          label: "待发布货运信息",
+          value: "WAIT_PUBLISH_INVOICE",
+        },
+      ],
+      open: false,
+      optionsList: [],
+      loading: false,
+      tableList: [],
+      pagination: {
+        total: 0,
+        size: 10,
+        page: 1,
+      },
+      loading: false,
+      title: "",
+      form: {},
+      printloading: false,
+      print: {
+        sn: "",
+        id: null,
+        times: 1,
+      },
+      printList: [],
+    };
+  },
+  mounted() {
+    this.getList();
+    this.printSelect();
+  },
+  methods: {
+    printSelect() {
+      printerList({ page: 1, size: 999 }).then((res) => {
+        if (res.code == 200) {
+          this.printList = res.data.content;
+        }
+      });
+    },
+    printSubmit() {
+      this.printloading = true;
+      printerPrint(this.print).then((res) => {
+        if (res.code == 200) {
+          this.printloading = false;
+          this.$message.success("打印成功!");
+          this.pagination.page = 1;
+          this.dyOpen = false;
+          this.getList();
+        } else {
+          this.$message.error(res.msg);
+          this.pagination.page = 1;
+          this.printloading = false;
+          this.dyOpen = false;
+          this.getList();
+        }
+      });
+    },
+    printOrder(record) {
+      this.print.id = record.id;
+      this.dyOpen = true;
+    },
+    handleDetail(record) {
+      orderDetail(record.id).then((res) => {
+        if (res.code == 200) {
+          this.form = res.data;
+          invoiceV2(record.id).then((res1) => {
+            if (res1.code == 200) {
+              this.form.driverInfo = res1.data;
+            } else {
+              this.$message.error(res1.msg);
+            }
+          });
+        } else {
+          this.$message.error(res.msg);
+        }
+      });
+
+      this.title = "订单详情";
+      this.open = true;
+    },
+    handleCurrentChange(size) {
+      console.log(size);
+      this.queryParams.page = size;
+      this.getList();
+    },
+    handleQuery() {
+      this.getList();
+      this.queryParams.page = 1;
+    },
+    getList() {
+      this.loading = true;
+      orderlist(this.queryParams).then((res) => {
+        if (res.code == 200) {
+          console.log(res);
+          this.tableList = res.data.content;
+          this.pagination.total = res.data.total;
+          this.pagination.page = res.data.page;
+
+          this.loading = false;
+        } else {
+          this.$message.error(res.msg);
+          this.loading = false;
+        }
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.item {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  .label {
+    min-width: 80px;
+  }
+}
+</style>

+ 312 - 0
src/views/login.vue

@@ -0,0 +1,312 @@
+<template>
+  <div class="login">
+    <div class="main">
+      <div class="left"></div>
+      <div class="rq">
+        <el-form
+          ref="loginForm"
+          :model="loginForm"
+          :rules="loginRules"
+          class="login-form right"
+        >
+          <h3 class="title">
+            <img src="@/assets/title.png" style="width: 363px; height: 59px" />
+          </h3>
+          <el-form-item prop="username">
+            <div class="input-div">
+              <img src="@/assets/user.png" style="width: 25px; height: 25px" />
+              <input
+                type="text"
+                class="input"
+                v-model="loginForm.username"
+                placeholder="请输手机号	"
+              />
+            </div>
+          </el-form-item>
+          <el-form-item prop="password">
+            <div class="input-div">
+              <img src="@/assets/password.png" style="width: 25px; height: 25px" />
+              <input
+                type="text"
+                class="input"
+                v-model="loginForm.password"
+                placeholder="请输入验证码"
+              />
+              <button @click="sendVerificationCode" :disabled="isCounting" class="btn">
+                {{ isCounting ? countdown + "秒后重发" : "发送验证码" }}
+              </button>
+            </div>
+          </el-form-item>
+          <el-form-item style="width: 100%">
+            <el-button
+              :loading="loading"
+              size="medium"
+              class="login_btn"
+              @click.native.prevent="handleLogin"
+            >
+              <span v-if="!loading">登 录</span>
+              <span v-else>登 录 中...</span>
+            </el-button>
+            <div style="float: right" v-if="register">
+              <router-link class="link-type" :to="'/register'">立即注册</router-link>
+            </div>
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+    <!--  底部  -->
+    <div class="el-login-footer">
+      <span>Copyright © 2018-2024 ruoyi.vip All Rights Reserved.</span>
+    </div>
+  </div>
+</template>
+
+<script>
+import Cookies from "js-cookie";
+import { getSMSCode, phoneLogin } from "@/api/login.js";
+export default {
+  data() {
+    return {
+      codeUrl: "",
+      loginForm: {
+        username: "",
+        password: "",
+        rememberMe: false,
+        code: "",
+        uuid: "",
+      },
+      loginRules: {
+        username: [
+          {
+            required: true,
+            trigger: "blur",
+            message: "请输入您的手机号",
+          },
+        ],
+        password: [
+          {
+            required: true,
+            trigger: "blur",
+            message: "请输入验证码",
+          },
+        ],
+      },
+      loading: false,
+      // 验证码开关
+      captchaEnabled: true,
+      // 注册开关
+      register: false,
+      redirect: undefined,
+      isCounting: false,
+      countdown: 60,
+      timer: null,
+    };
+  },
+  watch: {
+    $route: {
+      handler: function (route) {
+        this.redirect = route.query && route.query.redirect;
+      },
+      immediate: true,
+    },
+  },
+  methods: {
+    handleLogin() {
+      // this.$router.push({ path: "/index" }).catch(() => {});
+      this.$refs.loginForm.validate(async (valid) => {
+        if (valid) {
+          phoneLogin(this.loginForm.username, this.loginForm.password).then((res) => {
+            if (res.code == 200) {
+              console.log(res);
+              this.$message.success(res.msg);
+              Cookies.set("Admin-Token", res.data.token);
+              localStorage.setItem("userInfo", JSON.stringify(res.data));
+              this.$router.push({ path: this.redirect || "/index" }).catch(() => {});
+            } else {
+              this.$message.error(res.msg);
+            }
+          });
+        }
+      });
+    },
+    async sendVerificationCode() {
+      if (!this.loginForm.username) {
+        this.$message.error("手机号不能为空!");
+        // return false;
+      } else {
+        this.isCounting = true;
+        this.countdown = 60;
+        this.timer = setInterval(() => {
+          this.countdown--;
+          if (this.countdown <= 0) {
+            clearInterval(this.timer);
+            this.isCounting = false;
+          }
+        }, 1000);
+        getSMSCode(this.loginForm.username).then((res) => {
+          console.log(res);
+          if (res.code == 200) {
+            this.$message.success(res.msg);
+          } else {
+            this.$message.error(res.msg);
+          }
+        });
+
+        // const res = await axios.post(
+        //   "https://app.sxdirectpurchase.com/api/third/app/v1/third/getSMSCode?phone=" +
+        //     this.loginForm.username
+        // );
+        // console.log(res);
+        // if (res.data.code == 200) {
+        //   this.$message.success(res.data.msg);
+        // } else {
+        //   this.$message.error(res.data.msg);
+        // }
+      }
+    },
+  },
+};
+</script>
+
+<style>
+.btn {
+  background: none;
+  border: none;
+  color: #1362e0;
+}
+
+.rq {
+  width: 70%;
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+}
+
+.login {
+  height: 100vh;
+  background-size: cover;
+  width: 100vw;
+}
+
+.input-div {
+  padding: 0px 0px 0px 20px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  border: 1px solid #dad7d7;
+}
+
+.input {
+  outline: none;
+  height: 45px;
+  width: 70%;
+  border: none;
+  font-size: 16px;
+  padding: 0px 20px;
+}
+
+.login_btn {
+  width: 100%;
+  height: 53px;
+  background: #00d384;
+  border-radius: 3px;
+  color: white;
+  font-size: 18px;
+}
+
+::v-deep .el-input__inner:focus {
+  border-color: #00d384;
+}
+
+::v-deep .el-button:hover {
+  background-color: #10e595;
+}
+
+::v-deep .enterpriseName .el-input__prefix {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  flex-direction: row;
+  left: 10px;
+}
+
+::v-deep .enterpriseName .el-input__inner {
+  padding-left: 45px;
+}
+
+body {
+  padding: 0px;
+  margin: 0px;
+}
+
+.left {
+  background-image: url("../assets/back.png");
+  background-size: 100% 100%;
+  width: 35%;
+  height: 100%;
+}
+
+.main {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 100%;
+  height: 100%;
+}
+
+.title {
+  margin: 0px auto 30px auto;
+  text-align: center;
+  color: #707070;
+}
+
+.login-form {
+  border-radius: 6px;
+  background: #ffffff;
+  width: 600px;
+}
+
+.login-form > .input-icon {
+  height: 39px;
+  width: 14px;
+  margin-left: 2px;
+}
+
+.login-tip {
+  font-size: 13px;
+  text-align: center;
+  color: #bfbfbf;
+}
+
+.login-code {
+  width: 35%;
+  height: 53px;
+  float: right;
+}
+
+.login-code > img {
+  width: 100%;
+  height: 100%;
+  cursor: pointer;
+  vertical-align: middle;
+}
+
+.el-login-footer {
+  height: 40px;
+  line-height: 40px;
+  position: fixed;
+  bottom: 0;
+  width: 100%;
+  text-align: center;
+  color: #fff;
+  font-family: Arial;
+  font-size: 12px;
+  letter-spacing: 1px;
+}
+
+.login-code-img {
+  height: 38px;
+}
+</style>

+ 12 - 0
src/views/redirect.vue

@@ -0,0 +1,12 @@
+<script>
+export default {
+  created() {
+    const { params, query } = this.$route
+    const { path } = params
+    this.$router.replace({ path: '/' + path, query })
+  },
+  render: function(h) {
+    return h() // avoid warning message
+  }
+}
+</script>

+ 127 - 0
vue.config.js

@@ -0,0 +1,127 @@
+'use strict'
+const path = require('path')
+
+function resolve(dir) {
+    return path.join(__dirname, dir)
+}
+
+const CompressionPlugin = require('compression-webpack-plugin')
+
+const name = process.env.VUE_APP_TITLE || '农商网管理系统' // 网页标题
+
+const port = process.env.port || process.env.npm_config_port || 9001 // 端口
+
+// vue.config.js 配置说明
+//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
+// 这里只列一部分,具体配置参考文档
+module.exports = {
+    // 部署生产环境和开发环境下的URL。
+    // 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
+    // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
+    publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
+    // 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist)
+    outputDir: 'dist',
+    // 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
+    assetsDir: 'static',
+    // 是否开启eslint保存检测,有效值:ture | false | 'error'
+    lintOnSave: process.env.NODE_ENV === 'development',
+    // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
+    productionSourceMap: false,
+    // webpack-dev-server 相关配置
+    devServer: {
+        host: '0.0.0.0',
+        port: port,
+        open: false,
+        proxy: {
+            [process.env.VUE_APP_BASE_API]: {
+                target: `http://192.168.3.31:9001/api`,
+                changeOrigin: true,
+                pathRewrite: {
+                    ['^' + process.env.VUE_APP_BASE_API]: ''
+                }
+            },
+
+        },
+        disableHostCheck: true
+    },
+    css: {
+        loaderOptions: {
+            sass: {
+                sassOptions: { outputStyle: "expanded" }
+            }
+        }
+    },
+    configureWebpack: {
+        name: name,
+        resolve: {
+            alias: {
+                '@': resolve('src')
+            }
+        },
+        plugins: [
+            // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
+            new CompressionPlugin({
+                cache: false,                                  // 不启用文件缓存
+                test: /\.(js|css|html|jpe?g|png|gif|svg)?$/i,  // 压缩文件格式
+                filename: '[path][base].gz[query]',            // 压缩后的文件名
+                algorithm: 'gzip',                             // 使用gzip压缩
+                minRatio: 0.8,                                 // 压缩比例,小于 80% 的文件不会被压缩
+                deleteOriginalAssets: false                    // 压缩后删除原文件
+            })
+        ],
+    },
+    chainWebpack(config) {
+        config.plugins.delete('preload') // TODO: need test
+        config.plugins.delete('prefetch') // TODO: need test
+
+        // set svg-sprite-loader
+        config.module
+            .rule('svg')
+            .exclude.add(resolve('src/assets/icons'))
+            .end()
+        config.module
+            .rule('icons')
+            .test(/\.svg$/)
+            .include.add(resolve('src/assets/icons'))
+            .end()
+            .use('svg-sprite-loader')
+            .loader('svg-sprite-loader')
+            .options({
+                symbolId: 'icon-[name]'
+            })
+            .end()
+
+        // config.when(process.env.NODE_ENV !== 'development', config => {
+        //     config
+        //         .plugin('ScriptExtHtmlWebpackPlugin')
+        //         .after('html')
+        //         .end()
+
+        //     config.optimization.splitChunks({
+        //         chunks: 'all',
+        //         cacheGroups: {
+        //             libs: {
+        //                 name: 'chunk-libs',
+        //                 test: /[\\/]node_modules[\\/]/,
+        //                 priority: 10,
+        //                 chunks: 'initial' // only package third parties that are initially dependent
+        //             },
+        //             elementUI: {
+        //                 name: 'chunk-elementUI', // split elementUI into a single package
+        //                 test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
+        //                 priority: 20 // the weight needs to be larger than libs and app or it will be packaged into libs or app
+        //             },
+        //             commons: {
+        //                 name: 'chunk-commons',
+        //                 test: resolve('src/components'), // can customize your rules
+        //                 minChunks: 3, //  minimum common number
+        //                 priority: 5,
+        //                 reuseExistingChunk: true
+        //             }
+        //         }
+        //     })
+        //     config.optimization.runtimeChunk('single')
+        // })
+    }
+}
+

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 9392 - 0
yarn.lock