技术栈:vue + vuex + webpack + axios + sass
修改参数
直接下载原始模板
删除不必要数据
删除src / mock文件夹
删除src / main.js文件下的mock
依赖下载
npm un i sass -s
npm i node-sass@4.14.1 --save-dev
npm i sass-loader@7.3.1 --save-dev
汉化
修改:src/lang/zh.js
export default {
route: {
Dashboard: '首页',
// 基础资料
BasicData: '基础资料',
institution: '机构设置',
group: '集团',
organization: '组织',
customerVendor: '往来单位',
customers: '客户',
vendors: '供应商',
inventory: '存货设置',
paperLeng: '原纸楞别',
paperData: '纸质资料',
cartonSetting: '纸箱设置',
cartonTypeSetting: '箱型设置',
cartonProfile: '纸箱档案',
cartonProcess: '工序设置',
// 人力资源
HR: '人力资源',
personnel: '人事',
employee: '人员档案管理',
// 销售管理
salesManage: '销售管理',
paperOrder: '纸板订单',
cartonOrder: '纸箱订单',
// 生产管理
ProduceManage: '生产管理',
cartonScheduling: '纸箱排程',
cartonWarehouse: '纸箱入库',
// 库存管理
InventoryManage: '库存管理',
carton: '纸箱',
cartonLoadingUp: '纸箱装车',
cartonDelivery: '纸箱送货',
cartonReturn: '纸箱退货',
InventoryDish: '库存盘点',
vehicle: '车辆',
deliveryVehicle: '送货车辆',
deliveryRoute: '送货路线',
seeCar: '车辆定位',
// 财务管理
FinancialManage: '财务管理',
payableManage: '应付账管理',
payableStatement: '应付对账单',
orderPay: '物料付款单',
otherPay: '其他付款单',
receivableManage: '应收账管理',
receivableStatement: '应收对账单',
orderReceive: '货款收款单',
otherReceive: '其他收款单',
// 系统设置
systemSetting: '系统管理',
organ: '组织',
organSetting: '组织设置',
basic: '基本',
basicSetting: '基本设置',
roleSetting: '角色管理',
permissionSetting: '权限管理',
operationRecord: '操作日志',
feedbackIssue: '问题反馈',
InternetManagement: '外网管理',
NoticeManagement: '通知管理',
payOrderManage: '订单管理'
},
login: {
title: '胜源集团ERP系统(纸箱)',
logIn: '登录',
reset: '重置',
username: '账号',
password: '密码',
forgotPassword: '忘记密码?',
any: '随便填',
thirdparty: '第三方登录',
ToRegister: '去注册',
NoAccount: '没有账号',
passwordInput: '请输入新密码',
passwordConfirm: '请确认密码',
thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!'
},
tagsView: {
refresh: '刷新',
close: '关闭',
closeOthers: '关闭其他',
closeAll: '关闭所有'
}
}
登录页面
修改文件:src/views/login/index.vue
<template>
<div class="login-container">
<div
class="form-container"
:style="formContainerStyle"
>
<div style="text-align: center;margin-bottom:15px">
<img
src="../../assets/imges/carton_logo.png"
alt=""
style="width:160px;height:40px"
>
</div>
<el-tabs
v-model="activeName"
style="margin-bottom: 25px"
@tab-click="handleClick"
>
<el-tab-pane
label="密码登录"
name="login"
>
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
autocomplete="on"
label-position="left"
>
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<el-input
id="username"
ref="username"
v-model="loginForm.username"
:placeholder="$t('login.username')"
name="username"
type="text"
tabindex="1"
autocomplete="on"
@keyup.enter.native="handleUserName"
/>
</el-form-item>
<el-tooltip
v-model="capsTooltip"
content="Caps lock is On"
placement="right"
manual
>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<el-input
id="password"
ref="password"
v-model="displayPassword"
show-password
type="password"
:placeholder="$t('login.password')"
tabindex="2"
@keyup.enter.native="handleLogin"
/>
</el-form-item>
</el-tooltip>
<div style="font-size: 13px; margin-bottom: -10px;margin-top: 10px">
<a
style="margin-left: 5px;color: blue"
@click="handleForgetPwdClick"
>{{ $t('login.forgotPassword') }}</a>
<span>
<a style="margin-left: 150px;cursor: auto">{{ $t('login.NoAccount') }}?</a> <a
style="color: blue"
@click="handleRegister"
>{{ $t('login.ToRegister') }}</a>
</span>
</div>
<div class="handbutton">
<el-button
:loading="loading"
type="primary"
round
style="width:50%;height:47px;"
@click.native.prevent="handleLogin"
>
{{ $t('login.logIn') }}
</el-button>
<el-button
type="primary"
plain
class="pause-button"
style="width:50%;height:47px;"
@click.native.prevent="handleReset"
>
{{ $t('login.reset') }}
</el-button>
</div>
</el-form>
</el-tab-pane>
<el-tab-pane
label="验证码登录"
name="loginByPhone"
>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script>
import { validUsername } from '@/utils/validate'
export default {
name: 'Login',
components: {
},
data() {
const validateUsername = (rule, value, callback) => {
if (!validUsername(value)) {
callback(new Error('请输入正确的用户名'))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (!this.password) {
callback(new Error('请输入密码'))
} else {
callback()
}
}
return {
loginForm: {
username: '',
password: ''
},
loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
password: [{ required: true, trigger: 'change', validator: validatePassword }]
},
activeName: 'login',
formContainerStyle: {
// width: window.innerHeight * 0.95 * 1083 / 1850 * 0.8 + 'px',
width: 460 + 'px',
marginTop: window.innerHeight * 0.95 * 0.36 + 'px'
},
redirect: undefined,
displayPassword: '',
loading: false,
capsTooltip: false,
registerInfo: false,
}
},
watch: {
$route: {
handler: function (route) {
const query = route.query
if (query) {
this.redirect = query.redirect
}
},
immediate: true
},
displayPassword: function (value) {
this.password = value
}
},
methods: {
// 登录
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loginForm.password = this.password
this.$nextTick(() => {
this.loading = true
this.$store.dispatch('user/login', this.loginForm)
.then(() => {
localStorage.setItem('username', this.loginForm.username)
this.$router.push({ path: this.redirect || '/' })
this.loading = false
})
.catch(() => {
this.loading = false
})
})
} else {
console.log('error submit!!')
return false
}
})
},
// 重置
handleReset() {
this.displayPassword = ''
this.loginForm.username = ''
this.loginForm.password = ''
},
// 忘记密码
handleForgetPwdClick() {
console.log('忘记密码');
},
// 去注册
handleRegister() {
console.log('去注册');
},
handleUserName() {
this.$refs.password.focus()
},
handleClick(tab, event) {
console.log('tab, event: ', tab, event);
},
getOtherQuery(query) {
return Object.keys(query).reduce((acc, cur) => {
if (cur !== 'redirect') {
acc[cur] = query[cur]
}
return acc
}, {})
},
}
}
</script>
<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
$bg: #283443;
$light_gray: #fff;
$cursor: #000000;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input {
color: $cursor;
}
}
.login-container {
.el-input {
display: inline-block;
background: #f7f8f7;
height: 47px;
width: 85%;
input {
background: #f7f8f7;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
height: 47px;
&:-webkit-autofill {
box-shadow: 0 0 0px 1000px #f7f8f7 inset !important;
-webkit-text-fill-color: black !important;
}
}
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: #f7f8f7;
color: #454545;
margin-bottom: 20px;
border-radius: 10px;
/deep/ .el-icon-view {
font-size: 20px;
}
}
}
</style>
<style lang="scss" scoped>
$bg: #2d3a4b;
$dark_gray: #889aa4;
$light_gray: #f49f36;
.login-container {
min-height: 100%;
width: 100%;
background: url('../../assets/imges/loginBackground.jpg') no-repeat;
background-size: 100% 100%;
overflow: hidden;
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
}
.login {
color: $light_gray;
margin: 0px auto 50px auto;
text-align: center;
font-weight: bold;
border-bottom: 1px #fff solid;
.title {
font-size: 30px;
color: #ffff;
}
p {
margin-top: 0px;
font-size: 16px;
color: #d2d2d2;
}
img {
width: 60px;
height: 60px;
margin-top: -10px;
}
}
.form-container {
position: absolute;
width: 380px !important;
margin: 200px auto;
padding-top: 10px;
margin-left: 70%;
margin-top: 7% !important;
.login-form {
position: relative;
width: 100%;
max-width: 100%;
overflow: hidden;
}
/deep/ .el-tabs {
padding: 20px;
border-radius: 10px;
background: #fffeff;
}
.registerClass {
color: red;
font-size: 12px;
}
}
.handbutton {
display: flex;
padding-top: 10px;
margin-top: 5px;
margin-bottom: 15px;
.el-button {
border-radius: 5px;
}
}
/deep/ .el-tabs__header {
margin-bottom: 25px;
}
/deep/ .el-tabs__nav {
width: 100% !important;
}
/deep/ .el-tabs__item {
width: 50%;
font-size: 16px;
text-align: center;
}
/deep/ .el-tabs__active-bar {
width: 50% !important;
}
/deep/ .el-form-item__error {
margin-top: 5px !important;
}
}
</style>
侧边栏
新建 src/views 相关文件夹和所需 svg 图标,直接从项目源码中获取
修改文件:src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
/* Layout */
import Layout from '@/layout'
export const constantRoutes = [
{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/index'),
meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
}
]
},
// 基本资料
{
path: '/bd',
component: Layout,
redirect: '/bd/institution/group',
name: 'BasicData',
meta: {
title: 'BasicData',
icon: 'table'
},
children: [
{
path: 'institution',
component: () => import('@/views/bd/institution/index'),
name: 'Institution',
meta: { title: 'institution' },
redirect: '/bd/institution/group',
children: [
{
path: 'group',
component: () => import('@/views/bd/institution/group/index'),
name: 'Group',
meta: { title: 'group', icon: 'group' }
},
{
path: 'organization',
component: () => import('@/views/bd/institution/organization/index'),
name: 'Organization',
meta: { title: 'organization', icon: 'organization' }
}
]
},
{
path: 'customerVendor',
component: () => import('@/views/bd/customerVendor/index'),
name: 'CustomerVendor',
meta: { title: 'customerVendor' },
redirect: '/bd/customerVendor/customers',
children: [
{
path: 'customers',
component: () => import('@/views/bd/customerVendor/customers/index'),
name: 'Customers',
meta: { title: 'customers', icon: 'customers' }
},
{
path: 'vendors',
component: () => import('@/views/bd/customerVendor/vendors/index'),
name: 'Vendors',
meta: { title: 'vendors', icon: 'vendors' }
}
]
},
{
path: 'inventory',
component: () => import('@/views/bd/inventory/index'),
name: 'Inventory',
meta: { title: 'inventory' },
redirect: '/bd/inventory/paperLeng',
children: [
{
path: 'paperLeng',
component: () => import('@/views/bd/inventory/paperLeng/index'),
name: 'paperLeng',
meta: { title: 'paperLeng', icon: 'paperLeng' }
},
{
path: 'paperdata',
component: () => import('@/views/bd/inventory/paperData/index'),
name: 'PaperData',
meta: { title: 'paperData', icon: 'paperData' }
}
]
},
{
path: 'cartonSetting',
component: () => import('@/views/bd/cartonSetting/index'),
name: 'CartonSetting',
meta: { title: 'cartonSetting' },
redirect: '/bd/cartonSetting/cartonTypeSetting',
children: [
{
path: 'cartonTypeSetting',
component: () => import('@/views/bd/cartonSetting/cartonTypeSetting/index'),
name: 'cartonTypeSetting',
meta: { title: 'cartonTypeSetting', icon: 'cartonTypeSetting' }
},
{
path: 'cartonProfile',
component: () => import('@/views/bd/cartonSetting/cartonProfile/index'),
name: 'cartonProfile',
meta: { title: 'cartonProfile', icon: 'cartonProfile' }
},
{
path: 'cartonProcess',
component: () => import('@/views/bd/cartonSetting/cartonProcess/index'),
name: 'cartonProcess',
meta: { title: 'cartonProcess', icon: 'cartonProcess' }
}
]
}
]
},
// 人力资源
{
path: '/hr',
component: Layout,
redirect: '/hr/personnel/employee',
name: 'HR',
meta: {
title: 'HR',
icon: 'HR'
},
children: [
{
path: 'personnel',
component: () => import('@/views/hr/personnel/index'),
name: 'personnel',
meta: { title: 'personnel' },
redirect: '/hr/personnel/employee',
children: [
{
path: 'employee',
component: () => import('@/views/hr/personnel/employee/index'),
name: 'employee',
meta: { title: 'employee', icon: 'employee' }
}
]
}
]
},
// 销售管理
{
path: '/salesManage',
component: Layout,
redirect: '/salesManage/cartonOrder',
name: 'salesManage',
meta: {
title: 'salesManage',
icon: 'sales'
},
children: [
{
path: 'cartonOrder',
component: () => import('@/views/salesManage/cartonOrder/index'),
name: 'cartonOrder',
meta: { title: 'cartonOrder' },
redirect: '/salesManage/cartonOrder',
children: [
{
path: '',
component: () => import('@/views/salesManage/cartonOrder/index'),
name: 'cartonOrder',
meta: { title: 'cartonOrder', icon: 'cartonOrder' }
}
]
}
]
},
// 生产管理
{
path: '/produce',
component: Layout,
redirect: '/produce/cartonScheduling',
name: 'ProduceManage',
meta: {
title: 'ProduceManage',
icon: 'factory'
},
children: [
{
path: 'cartonScheduling',
component: () => import('@/views/produce/cartonScheduling/index'),
name: 'cartonScheduling',
meta: { title: 'cartonScheduling' },
redirect: '/produce/cartonScheduling',
children: [
{
path: '',
component: () => import('@/views/produce/cartonScheduling/index'),
name: 'cartonScheduling',
meta: { title: 'cartonScheduling', icon: 'cartonScheduling' }
}
]
},
{
path: 'cartonWarehouse',
component: () => import('@/views/produce/cartonWarehouse/index'),
name: 'cartonWarehouse',
meta: { title: 'cartonWarehouse' },
redirect: '/produce/cartonWarehouse',
children: [
{
path: '',
component: () => import('@/views/produce/cartonWarehouse/index'),
name: 'cartonWarehouse',
meta: { title: 'cartonWarehouse', icon: 'cartonWarehouse' }
}
]
}
]
},
// 库存管理
{
path: '/inventory',
component: Layout,
redirect: '/inventory/carton',
name: 'InventoryManage',
meta: {
title: 'InventoryManage',
icon: 'inventory'
},
children: [
{
path: 'carton',
component: () => import('@/views/inventory/carton/index'),
name: 'carton',
meta: { title: 'carton' },
redirect: '/inventory/carton',
children: [
{
path: 'cartonLoadingUp',
component: () => import('@/views/inventory/carton/cartonLoadingUp/index'),
name: 'cartonLoadingUp',
meta: { title: 'cartonLoadingUp', icon: 'cartonLoadingUp' }
},
{
path: 'cartonDelivery',
component: () => import('@/views/inventory/carton/cartonDelivery/index'),
name: 'cartonDelivery',
meta: { title: 'cartonDelivery', icon: 'cartonDelivery' }
},
{
path: 'cartonReturn',
component: () => import('@/views/inventory/carton/cartonReturn/index'),
name: 'cartonReturn',
meta: { title: 'cartonReturn', icon: 'cartonReturn' }
},
{
path: 'InventoryDish',
component: () => import('@/views/inventory/carton/InventoryDish/index'),
name: 'InventoryDish',
meta: { title: 'InventoryDish', icon: 'InventoryDish' }
}
]
},
{
path: 'vehicle',
component: () => import('@/views/inventory/vehicle/index'),
name: 'vehicle',
meta: { title: 'vehicle' },
redirect: '/inventory/vehicle',
children: [
{
path: 'deliveryVehicle',
component: () => import('@/views/inventory/vehicle/deliveryVehicle/index'),
name: 'deliveryVehicle',
meta: { title: 'deliveryVehicle', icon: 'deliveryVehicle' }
},
{
path: 'deliveryRoute',
component: () => import('@/views/inventory/vehicle/deliveryRoute/index'),
name: 'deliveryRoute',
meta: { title: 'deliveryRoute', icon: 'deliveryRoute' }
},
{
path: 'seeCar',
component: () => import('@/views/inventory/vehicle/seeCar/index'),
name: 'seeCar',
meta: { title: 'seeCar', icon: 'seeCar' }
}
]
}
]
},
// 财务管理
{
path: '/financial',
component: Layout,
redirect: '/financial/payable',
name: 'FinancialManage',
meta: {
title: 'FinancialManage',
icon: 'financial'
},
children: [
{
path: 'payable',
component: () => import('@/views/financial/payable/index'),
name: 'payableManage',
meta: { title: 'payableManage' },
redirect: '/financial/payable',
children: [
{
path: 'payableStatement',
component: () => import('@/views/financial/payable/payableStatement/index'),
name: 'payableStatement',
meta: { title: 'payableStatement', icon: 'payableStatement' }
},
{
path: 'orderPay',
component: () => import('@/views/financial/payable/orderPay/index'),
name: 'orderPay',
meta: { title: 'orderPay', icon: 'orderPay' }
},
{
path: 'otherPay',
component: () => import('@/views/financial/payable/otherPay/index'),
name: 'otherPay',
meta: { title: 'otherPay', icon: 'otherPay' }
}
]
},
{
path: 'receivable',
component: () => import('@/views/financial/receivable/index'),
name: 'receivableManage',
meta: { title: 'receivableManage' },
redirect: '/financial/receivable',
children: [
{
path: 'receivableStatement',
component: () => import('@/views/financial/receivable/receivableStatement/index'),
name: 'receivableStatement',
meta: { title: 'receivableStatement', icon: 'receivableStatement' }
},
{
path: 'orderReceive',
component: () => import('@/views/financial/receivable/orderReceive/index'),
name: 'orderReceive',
meta: { title: 'orderReceive', icon: 'orderReceive' }
},
{
path: 'otherReceive',
component: () => import('@/views/financial/receivable/otherReceive/index'),
name: 'otherReceive',
meta: { title: 'otherReceive', icon: 'otherReceive' }
}
]
}
]
},
// 系统设置
{
path: '/systemSetting',
component: Layout,
redirect: '/systemSetting/basicSetting',
name: 'systemSetting',
meta: {
title: 'systemSetting',
icon: 'setting'
},
children: [
{
path: 'basicSetting',
component: () => import('@/views/systemSetting/basicSetting/index'),
name: 'basicSetting',
meta: { title: 'basicSetting' },
redirect: '/systemSetting/basicSetting',
children: [
{
path: '',
component: () => import('@/views/systemSetting/basicSetting/index'),
name: 'basicSetting',
meta: { title: 'basicSetting', icon: 'basicSetting' }
}
]
},
{
path: 'organSetting',
component: () => import('@/views/systemSetting/organSetting/index'),
name: 'organSetting',
meta: { title: 'organSetting' },
redirect: '/systemSetting/organSetting',
children: [
{
path: '',
component: () => import('@/views/systemSetting/organSetting/index'),
name: 'organSetting',
meta: { title: 'organSetting', icon: 'organSetting' }
}
]
},
{
path: 'roleSetting',
component: () => import('@/views/systemSetting/roleSetting/index'),
name: 'roleSetting',
meta: { title: 'roleSetting' },
redirect: '/systemSetting/roleSetting',
children: [
{
path: '',
component: () => import('@/views/systemSetting/roleSetting/index'),
name: 'roleSetting',
meta: { title: 'roleSetting', icon: 'roleSetting' }
}
]
},
{
path: 'permissionSetting',
component: () => import('@/views/systemSetting/permissionSetting/index'),
name: 'permissionSetting',
meta: { title: 'permissionSetting' },
redirect: '/systemSetting/permissionSetting',
children: [
{
path: '',
component: () => import('@/views/systemSetting/permissionSetting/index'),
name: 'permissionSetting',
meta: { title: 'permissionSetting', icon: 'permissionSetting' }
}
]
},
{
path: 'operationRecord',
component: () => import('@/views/systemSetting/operationRecord/index'),
name: 'operationRecord',
meta: { title: 'operationRecord' },
redirect: '/systemSetting/operationRecord',
children: [
{
path: '',
component: () => import('@/views/systemSetting/operationRecord/index'),
name: 'operationRecord',
meta: { title: 'operationRecord', icon: 'operationRecord' }
}
]
},
{
path: 'InternetManagement',
component: () => import('@/views/systemSetting/InternetManagement/index'),
name: 'InternetManagement',
meta: { title: 'InternetManagement' },
redirect: '/systemSetting/InternetManagement',
children: [
{
path: '',
component: () => import('@/views/systemSetting/InternetManagement/index'),
name: 'InternetManagement',
meta: { title: 'InternetManagement', icon: 'InternetManagement' }
}
]
},
{
path: 'NoticeManagement',
component: () => import('@/views/systemSetting/NoticeManagement/index'),
name: 'NoticeManagement',
meta: { title: 'NoticeManagement' },
redirect: '/systemSetting/NoticeManagement',
children: [
{
path: '',
component: () => import('@/views/systemSetting/NoticeManagement/index'),
name: 'NoticeManagement',
meta: { title: 'NoticeManagement', icon: 'NoticeManagement' }
}
]
},
{
path: 'payOrderManage',
component: () => import('@/views/systemSetting/payOrderManage/index'),
name: 'payOrderManage',
meta: { title: 'payOrderManage' },
redirect: '/systemSetting/payOrderManage',
children: [
{
path: '',
component: () => import('@/views/systemSetting/payOrderManage/index'),
name: 'payOrderManage',
meta: { title: 'payOrderManage', icon: 'payOrderManage' }
}
]
}
]
}
]
const createRouter = () =>
new Router({
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
const router = createRouter()
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher
}
export default router