@ -0,0 +1 @@
|
||||
node_modules
|
||||
@ -0,0 +1,24 @@
|
||||
# vue-project
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ['@vue/cli-plugin-babel/preset']
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "vue-project",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"core-js": "^3.6.5",
|
||||
"echarts": "^4.8.0",
|
||||
"element-china-area-data": "^5.0.2",
|
||||
"element-ui": "^2.13.2",
|
||||
"file-saver": "^2.0.2",
|
||||
"jquery-form": "^4.3.0",
|
||||
"js-cookie": "^2.2.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"normalize.css": "^8.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^6.1.0",
|
||||
"sass": "^1.26.5",
|
||||
"sass-loader": "^8.0.2",
|
||||
"sortablejs": "^1.12.0",
|
||||
"svg-sprite-loader": "^5.0.0",
|
||||
"v-distpicker": "^1.2.7",
|
||||
"vue": "^2.6.11",
|
||||
"vue-echarts": "^5.0.0-beta.0",
|
||||
"vue-quill-editor": "^3.0.6",
|
||||
"vue-router": "^3.2.0",
|
||||
"vuedraggable": "^2.24.3",
|
||||
"vuex": "^3.4.0",
|
||||
"xlsx": "^0.16.8",
|
||||
"zx-player": "^0.9.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.4.0",
|
||||
"@vue/cli-plugin-eslint": "~4.4.0",
|
||||
"@vue/cli-plugin-router": "~4.4.0",
|
||||
"@vue/cli-plugin-vuex": "~4.4.0",
|
||||
"@vue/cli-service": "~4.4.0",
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"fs": "0.0.1-security",
|
||||
"prettier": "^1.19.1",
|
||||
"script-loader": "^0.7.2",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<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">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,5 @@
|
||||
# just a flag
|
||||
ENV = 'development'
|
||||
|
||||
# base api
|
||||
VUE_APP_BASE_API = '/dev-api'
|
||||
@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
min-width: 1200px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,72 @@
|
||||
import {
|
||||
HTTP_URL, UPLOADAVATARIMG
|
||||
} from './api-type.js'
|
||||
|
||||
const $api = {
|
||||
URL: HTTP_URL + '/body',
|
||||
getArea: HTTP_URL + '/body/getArea', // 获取省市县
|
||||
login: HTTP_URL + '/body/login', // 登录接口
|
||||
getGoodsList: HTTP_URL + '/body/getGoodsList', // 获取商品列表
|
||||
getGoodsClassification: HTTP_URL + '/body/getGoodsClassification', // 获取商品分类
|
||||
addComboGoods: HTTP_URL + '/body/addComboGoods', // 新增商品套餐
|
||||
addGoods: HTTP_URL + '/body/addGoods', // 新增商品
|
||||
getComboList: HTTP_URL + '/body/getComboList', // 获取商品套餐列表
|
||||
editComboGoods: HTTP_URL + '/body/editComboGoods', // 编辑商品套餐
|
||||
delComboGoods: HTTP_URL + '/body/delComboGoods', // 删除商品套餐
|
||||
getOrders: HTTP_URL + '/body/getOrders', // 订单列表
|
||||
addMerchants: HTTP_URL + '/body/addMerchants', // 新增供应商/店铺 注册
|
||||
// uploadAvatar: UPLOADAVATARIMG + '/uploadAvatar', // 上传图片和视频
|
||||
// 新的上传接口
|
||||
uploadFile: UPLOADAVATARIMG + '/uploadFile', // 上传图片和视频
|
||||
getOrderDetails: HTTP_URL + '/body/getOrderDetails', // 获取订单详情
|
||||
changeState: HTTP_URL + '/body/getOrderDetails', // 修改订单状态
|
||||
updateState: HTTP_URL + '/body/updateState', // 更改商品状态
|
||||
getGoodsDetails: HTTP_URL + '/body/getGoodsDetails', // 获取商品详情
|
||||
modiPassword: HTTP_URL + '/body/modiPassword', // 修改管理员密码
|
||||
valiUserName: HTTP_URL + '/body/valiUserName', // 用户名唯一校验
|
||||
valiMerchantsName: HTTP_URL + '/body/valiMerchantsName', // 供应商名称唯一校验
|
||||
goodsSubmit: HTTP_URL + '/body/goodsSubmit', // 商品提交审核
|
||||
editGoods: HTTP_URL + '/body/editGoods', // 修改商品
|
||||
getMerchantsIndex: HTTP_URL + '/body/getMerchantsIndex', // 获取店铺首页信息
|
||||
editMerchantsIndex: HTTP_URL + '/body/editMerchantsIndex', // 修改店铺首页
|
||||
getGoodsByClassification: HTTP_URL + '/body/getGoodsByClassification', // 根据分类获取商品列表
|
||||
editMerchants: HTTP_URL + '/body/editMerchants', // 编辑供应商/店铺
|
||||
getMerchGoodsClassification: HTTP_URL + '/body/getMerchGoodsClassification', // 根据商户Id 获取商品分类
|
||||
getGoodsMerchClassification: HTTP_URL + '/body/getGoodsMerchClassification', // 根据商户Id 获取已经商品
|
||||
addCourierInfo: HTTP_URL + '/body/addCourierInfo', // 填写快递信息
|
||||
addRefundInfo: HTTP_URL + '/body/addRefundInfo', // 商家退款
|
||||
modiOrderState: HTTP_URL + '/body/modiOrderState', // 修改订单状态
|
||||
addRefuseRefundInfo: HTTP_URL + '/body/addRefuseRefundInfo', // 商家拒绝退款
|
||||
valiMerchantsNameAndID: HTTP_URL + '/body/valiMerchantsNameAndID',//带供应商id的校验供应商名字唯一校验
|
||||
getMerchantsState: HTTP_URL + '/body/getMerchantsState',//获取供应商状态
|
||||
exportOrdersExcel: HTTP_URL + '/body/exportOrdersExcel',//商户订单导出Excel表
|
||||
getGraphicData: HTTP_URL + '/body/getGraphicData',//获取图示数据
|
||||
getRealTimeData: HTTP_URL + '/body/getRealTimeData',//实时数据
|
||||
getOrderData: HTTP_URL + '/body/getOrderData',//获取订单数据(待办事项)
|
||||
getLogisticsInfo: HTTP_URL + '/body/getLogisticsInfo',//获取物流信息
|
||||
importOrderExcel: HTTP_URL + '/importOrderExcel',//导入订单物流信息
|
||||
exportErrorData: HTTP_URL + '/body/exportErrorData',//下载导入批次记录
|
||||
getLogisticsErrorMsg: HTTP_URL + '/body/getLogisticsErrorMsg',//快递单号无法识别
|
||||
getLogisticsImportErrorMsg: HTTP_URL + '/body/getLogisticsImportErrorMsg',//批量导入错误
|
||||
updateDataState: HTTP_URL + '/body/updateDataState',//更改批次状态
|
||||
getLogisticsCode: HTTP_URL + '/body/getLogisticsCode',//获取物流公司编码及名称
|
||||
updateOrderAddress: HTTP_URL + '/body/updateOrderAddress',//待发货状态订单操作栏增加修改收货地址
|
||||
|
||||
|
||||
// 三级套餐
|
||||
// 获取规格排序
|
||||
getSpecs: HTTP_URL + '/body/getSpecs',
|
||||
// 新增/编辑三级套餐
|
||||
addOrEditSpecMerchants: HTTP_URL + '/body/addOrEditSpecMerchants',
|
||||
// 回显三级套餐
|
||||
getSpecMerchants: HTTP_URL + '/body/getSpecMerchants',
|
||||
// 弹窗拖动排序
|
||||
editSpecsSort: HTTP_URL + '/body/editSpecsSort',
|
||||
// 回显拖动接口的值
|
||||
getSpecsSort: HTTP_URL + '/body/getSpecsSort',
|
||||
getActivityMenus: HTTP_URL + '/body/getActivityMenus', //获取活动列表
|
||||
addFullActivity: HTTP_URL + '/body/addFullActivity', //是否参加满额活动
|
||||
getGoodsFullActivityDetail: HTTP_URL + '/body/getGoodsFullActivityDetail', //回显满额活动
|
||||
}
|
||||
|
||||
export { $api }
|
||||
@ -0,0 +1,38 @@
|
||||
let httpUrl, uploadAvatarImg
|
||||
// 总后台
|
||||
// 设置环境 ,生产需要设置为 1
|
||||
// 0:test 1:produce
|
||||
// const _ENV = '1'
|
||||
const _ENV = '0'
|
||||
// 测试 账号:wanghao
|
||||
// 密码:111111
|
||||
|
||||
function setUrl() {
|
||||
if (_ENV === '0') {
|
||||
return 'test_url'
|
||||
} else if (_ENV === '1') {
|
||||
return 'pro_url'
|
||||
}
|
||||
}
|
||||
|
||||
switch (setUrl()) {
|
||||
case 'test_url':
|
||||
httpUrl = 'http://t.81ronggui.com:8082/ronghui/rh' // 测试环境
|
||||
// uploadAvatarImg = 'http://b.81ronggui.com:8445' //原来的上传
|
||||
uploadAvatarImg = 'https://www.rongui.cn/ronghui/admin' //现在的上传基础路径
|
||||
|
||||
// uploadAvatarImg = 'http://t.81ronggui.com:8082/ronghui/rh'
|
||||
// uploadAvatarImg = 'http://www.81ronggui.com:8082/ronggui/b'
|
||||
// uploadAvatarImg = 'http://b.81ronggui.com/ronggui/b'
|
||||
break
|
||||
case 'pro_url':
|
||||
httpUrl = 'https://www.rongui.cn/ronghui/rh' // 生产环 境
|
||||
// uploadAvatarImg = 'https://172.17.181.128:8445/ronggui/b'
|
||||
// uploadAvatarImg = 'https://b.81ronggui.com:8445/ronggui/b' //原来的上传
|
||||
uploadAvatarImg = 'https://www.rongui.cn/ronghui/admin' //现在的上传基础路径
|
||||
|
||||
// uploadAvatarImg = 'https://www.81ronggui.com:8445/ronggui/b'
|
||||
break
|
||||
}
|
||||
export const HTTP_URL = httpUrl
|
||||
export const UPLOADAVATARIMG = uploadAvatarImg
|
||||
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 732 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 430 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
|
||||
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
|
||||
<router-link :to="item.path" v-else>{{ item.meta.title }}</router-link>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import pathToRegexp from 'path-to-regexp'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
levelList: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.getBreadcrumb()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
methods: {
|
||||
getBreadcrumb() {
|
||||
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
|
||||
console.log(matched)
|
||||
const first = matched[0]
|
||||
|
||||
if (!this.isDashboard(first)) {
|
||||
matched = [{ path: '/home', meta: { title: '首页' }}].concat(matched)
|
||||
}
|
||||
|
||||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
||||
},
|
||||
isDashboard(route) {
|
||||
const name = route && route.name
|
||||
if (!name) {
|
||||
return false
|
||||
}
|
||||
return name.trim().toLocaleLowerCase() === 'home'.toLocaleLowerCase()
|
||||
},
|
||||
pathCompile(path) {
|
||||
// const { params } = this.$route
|
||||
// var toPath = pathToRegexp(path)
|
||||
// return toPath(params)
|
||||
},
|
||||
handleLink(item) {
|
||||
// console.log(item)
|
||||
const { redirect, path } = item
|
||||
if (redirect) {
|
||||
this.$router.push(redirect)
|
||||
return
|
||||
}
|
||||
this.$router.push(this.pathCompile(path))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-breadcrumb.el-breadcrumb {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
line-height: 50px;
|
||||
margin-left: 8px;
|
||||
|
||||
.no-redirect {
|
||||
color: #97a8be;
|
||||
cursor: text;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<el-select v-model="classificationid_code" placeholder="请选择分类" @change="choseGoodsType($event)">
|
||||
<el-option v-for="(item,index) in goodsType" :key="index" :value="item.goodsClassificationID" :label="item.goodsClassificationName" />
|
||||
</el-select>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
classificationid: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
goodsType: [],
|
||||
classificationid_code: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
classificationid: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.classificationid_code = val
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getgoodsType()
|
||||
},
|
||||
methods: {
|
||||
getgoodsType() {
|
||||
const params = {
|
||||
type: 'getGoodsClassification',
|
||||
data: {
|
||||
parentID: '0'
|
||||
}
|
||||
}
|
||||
|
||||
this.$http
|
||||
.post(this.$api.getGoodsClassification, params)
|
||||
.then((res) => {
|
||||
this.goodsType = res.goodsClassifications
|
||||
})
|
||||
},
|
||||
choseGoodsType(event) {
|
||||
let obj = {}
|
||||
obj = this.goodsType.find((item) => {
|
||||
return item.goodsClassificationID === event
|
||||
})
|
||||
this.$emit('choseGoodsType', obj)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div style="padding: 0 15px;" @click="toggleClick">
|
||||
<svg
|
||||
:class="{'is-active':isActive}"
|
||||
class="hamburger"
|
||||
viewBox="0 0 1024 1024"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="64"
|
||||
height="64"
|
||||
>
|
||||
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Hamburger',
|
||||
props: {
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleClick() {
|
||||
this.$emit('toggleClick')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hamburger {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.hamburger.is-active {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
|
||||
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
|
||||
<use :xlink:href="iconName" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isExternal } from '@/utils/validate'
|
||||
|
||||
export default {
|
||||
name: 'SvgIcon',
|
||||
props: {
|
||||
iconClass: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isExternal() {
|
||||
return isExternal(this.iconClass)
|
||||
},
|
||||
iconName() {
|
||||
return `#icon-${this.iconClass}`
|
||||
},
|
||||
svgClass() {
|
||||
if (this.className) {
|
||||
return 'svg-icon ' + this.className
|
||||
} else {
|
||||
return 'svg-icon'
|
||||
}
|
||||
},
|
||||
styleExternalIcon() {
|
||||
return {
|
||||
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
|
||||
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.svg-external-icon {
|
||||
background-color: currentColor;
|
||||
mask-size: cover!important;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 497 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 944 B |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 285 B |
|
After Width: | Height: | Size: 821 B |
|
After Width: | Height: | Size: 623 B |
|
After Width: | Height: | Size: 731 B |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 597 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 440 B |
@ -0,0 +1,22 @@
|
||||
# replace default config
|
||||
|
||||
# multipass: true
|
||||
# full: true
|
||||
|
||||
plugins:
|
||||
|
||||
# - name
|
||||
#
|
||||
# or:
|
||||
# - name: false
|
||||
# - name: true
|
||||
#
|
||||
# or:
|
||||
# - name:
|
||||
# param1: 1
|
||||
# param2: 2
|
||||
|
||||
- removeAttrs:
|
||||
attrs:
|
||||
- 'fill'
|
||||
- 'fill-rule'
|
||||
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class="vab-ad">
|
||||
<el-carousel
|
||||
v-if="adList"
|
||||
height="30px"
|
||||
direction="vertical"
|
||||
:autoplay="true"
|
||||
:interval="3000"
|
||||
indicator-position="none"
|
||||
>
|
||||
<el-carousel-item v-for="(item, index) in adList" :key="index">
|
||||
<el-tag type="warning" class="el-icon-warning" />
|
||||
<a target="_blank" :href="item.url">{{ item.title }}</a>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// import { getList } from '@/api/ad'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// nodeEnv: process.env.NODE_ENV,
|
||||
adList: [{
|
||||
title: '欢迎加入戎归星选电商平台,戎归星选电商平台致力于帮助农商商户、个体户打开销售渠道,只要你有优质货源,加入平台,将会找到更多客户!'
|
||||
// url: '#'
|
||||
}]
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// this.fetchData();
|
||||
},
|
||||
methods: {
|
||||
// async fetchData() {
|
||||
// const { data } = await getList();
|
||||
// this.adList = data;
|
||||
// },
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.vab-ad {
|
||||
height: 30px;
|
||||
padding-right: 20px;
|
||||
padding-left: 20px;
|
||||
line-height: 30px;
|
||||
cursor: pointer;
|
||||
background: #eef1f6;
|
||||
box-shadow: 0 -1px 2px rgba(0, 21, 41, 0.08) inset;
|
||||
margin-top: 50px;
|
||||
a {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<section class="app-main">
|
||||
<transition name="fade-transform" mode="out-in">
|
||||
<router-view :key="key" />
|
||||
</transition>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AppMain',
|
||||
computed: {
|
||||
key() {
|
||||
return this.$route.path
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fixed-header+.app-main {
|
||||
padding-top: 80px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div class="navbar">
|
||||
<hamburger
|
||||
:is-active="sidebar.opened"
|
||||
class="hamburger-container"
|
||||
@toggleClick="toggleSideBar"
|
||||
/>
|
||||
|
||||
<breadcrumb class="breadcrumb-container" />
|
||||
|
||||
<div class="right-menu">
|
||||
<el-dropdown class="avatar-container" trigger="click">
|
||||
<div class="avatar-wrapper">
|
||||
<!-- <img src="https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif?imageView2/1/w/80/h/80" class="user-avatar"> -->
|
||||
<span>{{ merchantsName }}</span>
|
||||
<i class="el-icon-caret-bottom" />
|
||||
</div>
|
||||
<el-dropdown-menu slot="dropdown" class="user-dropdown">
|
||||
<router-link to="/user/user">
|
||||
<el-dropdown-item>修改密码</el-dropdown-item>
|
||||
</router-link>
|
||||
<el-dropdown-item divided @click.native="logout">
|
||||
<span style="display:block;">退出系统</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import Breadcrumb from '@/components/Breadcrumb'
|
||||
import Hamburger from '@/components/Hamburger'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Breadcrumb,
|
||||
Hamburger
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['sidebar', 'merchantsName'])
|
||||
},
|
||||
methods: {
|
||||
toggleSideBar() {
|
||||
this.$store.dispatch('app/toggleSideBar')
|
||||
},
|
||||
async logout() {
|
||||
await this.$store.dispatch('user/logout')
|
||||
// this.$router.push(`/login?redirect=${this.$route.fullPath}`)
|
||||
// this.$router.push(`/login?redirect=/`)
|
||||
this.$router.push(`/login`)
|
||||
window.localStorage.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.navbar {
|
||||
height: 50px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||
|
||||
.hamburger-container {
|
||||
line-height: 46px;
|
||||
height: 100%;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.025);
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb-container {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.right-menu {
|
||||
float: right;
|
||||
height: 100%;
|
||||
line-height: 50px;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.right-menu-item {
|
||||
display: inline-block;
|
||||
padding: 0 8px;
|
||||
height: 100%;
|
||||
font-size: 18px;
|
||||
color: #5a5e66;
|
||||
vertical-align: text-bottom;
|
||||
|
||||
&.hover-effect {
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.025);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
margin-right: 30px;
|
||||
|
||||
.avatar-wrapper {
|
||||
margin-top: 5px;
|
||||
position: relative;
|
||||
|
||||
.user-avatar {
|
||||
cursor: pointer;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.el-icon-caret-bottom {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
top: 25px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,24 @@
|
||||
export default {
|
||||
computed: {
|
||||
device() {
|
||||
return this.$store.state.app.device
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fixBugIniOS()
|
||||
},
|
||||
methods: {
|
||||
fixBugIniOS() {
|
||||
const $subMenu = this.$refs.subMenu
|
||||
if ($subMenu) {
|
||||
const handleMouseleave = $subMenu.handleMouseleave
|
||||
$subMenu.handleMouseleave = (e) => {
|
||||
if (this.device === 'mobile') {
|
||||
return
|
||||
}
|
||||
handleMouseleave(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'MenuItem',
|
||||
functional: true,
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
render(h, context) {
|
||||
const { icon, title } = context.props
|
||||
const vnodes = []
|
||||
if (icon) {
|
||||
if (icon.includes('el-icon')) {
|
||||
vnodes.push(<i class={[icon, 'sub-el-icon']} />)
|
||||
} else {
|
||||
vnodes.push(<svg-icon icon-class={icon}/>)
|
||||
}
|
||||
}
|
||||
|
||||
if (title) {
|
||||
vnodes.push(<span slot='title'>{(title)}</span>)
|
||||
}
|
||||
return vnodes
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sub-el-icon {
|
||||
color: currentColor;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<component :is="type" v-bind="linkProps(to)">
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isExternal } from '@/utils/validate'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
to: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isExternal() {
|
||||
return isExternal(this.to)
|
||||
},
|
||||
type() {
|
||||
if (this.isExternal) {
|
||||
return 'a'
|
||||
}
|
||||
return 'router-link'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
linkProps(to) {
|
||||
if (this.isExternal) {
|
||||
return {
|
||||
href: to,
|
||||
target: '_blank',
|
||||
rel: 'noopener'
|
||||
}
|
||||
}
|
||||
return {
|
||||
to: to
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="sidebar-logo-container" :class="{'collapse':collapse}">
|
||||
<transition name="sidebarLogoFade">
|
||||
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
|
||||
<img v-if="logo" :src="logo" class="sidebar-logo">
|
||||
<h1 v-else class="sidebar-title">{{ title }} </h1>
|
||||
</router-link>
|
||||
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
|
||||
<img v-if="logo" :src="logo" class="sidebar-logo">
|
||||
<h1 class="sidebar-title">{{ title }} </h1>
|
||||
</router-link>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import logo from '../../../assets/images/ronggui.png'
|
||||
export default {
|
||||
name: 'SidebarLogo',
|
||||
props: {
|
||||
collapse: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: '后台管理系统',
|
||||
logo: logo
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.sidebarLogoFade-enter-active {
|
||||
transition: opacity 1.5s;
|
||||
}
|
||||
|
||||
.sidebarLogoFade-enter,
|
||||
.sidebarLogoFade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.sidebar-logo-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
background: #2b2f3a;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
|
||||
& .sidebar-logo-link {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
& .sidebar-logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
vertical-align: middle;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
& .sidebar-title {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
line-height: 50px;
|
||||
font-size: 14px;
|
||||
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
&.collapse {
|
||||
.sidebar-logo {
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div v-if="!item.hidden">
|
||||
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
|
||||
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
|
||||
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
|
||||
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
|
||||
</el-menu-item>
|
||||
</app-link>
|
||||
</template>
|
||||
|
||||
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
|
||||
<template slot="title">
|
||||
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
|
||||
</template>
|
||||
<sidebar-item
|
||||
v-for="child in item.children"
|
||||
:key="child.path"
|
||||
:is-nest="true"
|
||||
:item="child"
|
||||
:base-path="resolvePath(child.path)"
|
||||
class="nest-menu"
|
||||
/>
|
||||
</el-submenu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import path from 'path'
|
||||
import { isExternal } from '@/utils/validate'
|
||||
import Item from './Item'
|
||||
import AppLink from './Link'
|
||||
import FixiOSBug from './FixiOSBug'
|
||||
|
||||
export default {
|
||||
name: 'SidebarItem',
|
||||
components: { Item, AppLink },
|
||||
mixins: [FixiOSBug],
|
||||
props: {
|
||||
item: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
isNest: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
basePath: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
this.onlyOneChild = null
|
||||
return {}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
methods: {
|
||||
hasOneShowingChild(children = [], parent) {
|
||||
const showingChildren = children.filter(item => {
|
||||
if (item.hidden) {
|
||||
return false
|
||||
} else {
|
||||
this.onlyOneChild = item
|
||||
return true
|
||||
}
|
||||
})
|
||||
if (showingChildren.length === 1) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (showingChildren.length === 0) {
|
||||
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
},
|
||||
resolvePath(routePath) {
|
||||
if (isExternal(routePath)) {
|
||||
return routePath
|
||||
}
|
||||
if (isExternal(this.basePath)) {
|
||||
return this.basePath
|
||||
}
|
||||
return path.resolve(this.basePath, routePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div :class="{'has-logo':showLogo}">
|
||||
<logo :collapse="isCollapse" />
|
||||
<el-scrollbar wrap-class="scrollbar-wrapper">
|
||||
<el-menu
|
||||
:default-active="activeMenu"
|
||||
:collapse="isCollapse"
|
||||
:background-color="variables.menuBg"
|
||||
:text-color="variables.menuText"
|
||||
:unique-opened="false"
|
||||
:active-text-color="variables.menuActiveText"
|
||||
:collapse-transition="false"
|
||||
mode="vertical"
|
||||
>
|
||||
<sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" />
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import Logo from './Logo'
|
||||
import SidebarItem from './SidebarItem'
|
||||
import variables from '@/styles/variables.scss'
|
||||
|
||||
export default {
|
||||
components: { SidebarItem, Logo },
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'sidebar'
|
||||
]),
|
||||
routes() {
|
||||
return this.$router.options.routes
|
||||
},
|
||||
activeMenu() {
|
||||
const route = this.$route
|
||||
const { meta, path } = route
|
||||
if (meta.activeMenu) {
|
||||
return meta.activeMenu
|
||||
}
|
||||
return path
|
||||
},
|
||||
showLogo() {
|
||||
return this.$store.state.settings.sidebarLogo
|
||||
},
|
||||
variables() {
|
||||
return variables
|
||||
},
|
||||
isCollapse() {
|
||||
return !this.sidebar.opened
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,4 @@
|
||||
export { default as Navbar } from './Navbar'
|
||||
export { default as Sidebar } from './Sidebar'
|
||||
export { default as AppMain } from './AppMain'
|
||||
export { default as Ad } from './Ad'
|
||||
@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div :class="classObj" class="app-wrapper">
|
||||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
|
||||
<sidebar class="sidebar-container" />
|
||||
<div class="main-container">
|
||||
<div class="fixed-header">
|
||||
<navbar />
|
||||
<!-- <tags-view /> -->
|
||||
</div>
|
||||
<Ad />
|
||||
<app-main />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Navbar, Sidebar, AppMain, Ad } from './components'
|
||||
import ResizeMixin from './mixin/ResizeHandler'
|
||||
import { mapState } from 'vuex'
|
||||
export default {
|
||||
name: 'Layout',
|
||||
components: {
|
||||
Navbar,
|
||||
Sidebar,
|
||||
AppMain,
|
||||
Ad
|
||||
},
|
||||
mixins: [ResizeMixin],
|
||||
computed: {
|
||||
...mapState({
|
||||
needTagsView: state => state.settings.tagsView
|
||||
}),
|
||||
sidebar() {
|
||||
return this.$store.state.app.sidebar
|
||||
},
|
||||
device() {
|
||||
return this.$store.state.app.device
|
||||
},
|
||||
fixedHeader() {
|
||||
return this.$store.state.settings.fixedHeader
|
||||
},
|
||||
classObj() {
|
||||
return {
|
||||
hideSidebar: !this.sidebar.opened,
|
||||
openSidebar: this.sidebar.opened,
|
||||
withoutAnimation: this.sidebar.withoutAnimation,
|
||||
mobile: this.device === 'mobile'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClickOutside() {
|
||||
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~@/styles/mixin.scss";
|
||||
@import "~@/styles/variables.scss";
|
||||
|
||||
.app-wrapper {
|
||||
@include clearfix;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
&.mobile.openSidebar{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
.drawer-bg {
|
||||
background: #000;
|
||||
opacity: 0.3;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.fixed-header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 9;
|
||||
width: calc(100% - #{$sideBarWidth});
|
||||
transition: width 0.28s;
|
||||
}
|
||||
|
||||
.hideSidebar .fixed-header {
|
||||
width: calc(100% - 54px)
|
||||
}
|
||||
|
||||
.mobile .fixed-header {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,43 @@
|
||||
import store from '@/store'
|
||||
|
||||
const { body } = document
|
||||
const WIDTH = 992
|
||||
|
||||
export default {
|
||||
watch: {
|
||||
$route(route) {
|
||||
if (this.device === 'mobile' && this.sidebar.opened) {
|
||||
store.dispatch('app/closeSideBar', { withoutAnimation: false })
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
window.addEventListener('resize', this.$_resizeHandler)
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.$_resizeHandler)
|
||||
},
|
||||
mounted() {
|
||||
const isMobile = this.$_isMobile()
|
||||
if (isMobile) {
|
||||
store.dispatch('app/toggleDevice', 'mobile')
|
||||
store.dispatch('app/closeSideBar', { withoutAnimation: true })
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
$_isMobile() {
|
||||
const rect = body.getBoundingClientRect()
|
||||
return rect.width - 1 < WIDTH
|
||||
},
|
||||
$_resizeHandler() {
|
||||
if (!document.hidden) {
|
||||
const isMobile = this.$_isMobile()
|
||||
store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')
|
||||
|
||||
if (isMobile) {
|
||||
store.dispatch('app/closeSideBar', { withoutAnimation: true })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
// CSS重置的现代替代方法
|
||||
import 'normalize.css/normalize.css'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import '@/styles/index.scss' // 全局css
|
||||
// 第三方插件
|
||||
import ElementUI from 'element-ui'
|
||||
|
||||
import './icons' // icon
|
||||
import './utils/vab'
|
||||
import echarts from 'echarts' // 引入echarts
|
||||
import {
|
||||
$api
|
||||
} from './api/api-config' // 接口配置
|
||||
|
||||
//过滤器
|
||||
import filters from './utils/filters'
|
||||
for (const k in filters) {
|
||||
Vue.filter(k, filters[k]);
|
||||
}
|
||||
Vue.prototype.$api = $api
|
||||
import './permission' // 权限控制
|
||||
Vue.prototype.$echarts = echarts
|
||||
Vue.use(ElementUI)
|
||||
Vue.config.productionTip = false
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
@ -0,0 +1,34 @@
|
||||
import router from './router'
|
||||
import NProgress from 'nprogress' // 进度条
|
||||
import 'nprogress/nprogress.css' // 进度条样式
|
||||
import getPageTitle from '@/utils/get-page-title' // title设置
|
||||
import {
|
||||
routesWhiteList
|
||||
} from '@/config/settings'
|
||||
|
||||
NProgress.configure({ easing: 'ease', speed: 500, showSpinner: false })// 进度条配置
|
||||
router.beforeEach(async(to, from, next) => {
|
||||
NProgress.start() // 进度条开始
|
||||
document.title = getPageTitle(to.meta.title) // 设置页面标题
|
||||
const hasGetUserInfo = sessionStorage.getItem('userName') //获取登录标识
|
||||
if (hasGetUserInfo) { // 确定用户是否已登录
|
||||
if (to.path === '/login') {
|
||||
next({ path: '/' }) // 如果已登录,则重定向到主页
|
||||
NProgress.done() // 进度条结束
|
||||
} else {
|
||||
next()
|
||||
NProgress.done()
|
||||
}
|
||||
} else {
|
||||
if (routesWhiteList.indexOf(to.path) !== -1) { // 在免费登录白名单中,直接进入
|
||||
next()
|
||||
} else { // 其他没有访问权限的页面将被重定向到登录页面。
|
||||
next(`/login?redirect=${to.path}`)
|
||||
NProgress.done()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
router.afterEach(() => {
|
||||
NProgress.done() // 完成进度条
|
||||
})
|
||||
@ -0,0 +1,17 @@
|
||||
// // import 'echarts'
|
||||
// // import 'echarts/map/js/china'
|
||||
// // import 'echarts/map/js/world'
|
||||
|
||||
// // import 'echarts-wordcloud'
|
||||
|
||||
// // import VabChart from 'vue-echarts'
|
||||
// // import theme from './vab-echarts-theme.json'
|
||||
|
||||
// // VabChart.registerTheme('vab-echarts-theme', theme)
|
||||
// // export default VabChart
|
||||
// import vue from 'vue'
|
||||
// import ECharts from 'vue-echarts'
|
||||
// import 'echarts/lib/chart/bar'
|
||||
// import 'echarts/lib/component/tooltip'
|
||||
// import 'echarts'
|
||||
// vue.component('v-chart', ECharts)
|
||||
@ -0,0 +1,7 @@
|
||||
import { Custom, Flv, Hls, Mp4 } from 'zx-player'
|
||||
|
||||
const VabPlayerMp4 = Mp4
|
||||
const VabPlayerHls = Hls
|
||||
const VabPlayerFlv = Flv
|
||||
const VabPlayerCustom = Custom
|
||||
export { VabPlayerMp4, VabPlayerHls, VabPlayerFlv, VabPlayerCustom }
|
||||
@ -0,0 +1,5 @@
|
||||
import { quillEditor } from 'vue-quill-editor' // 调用编辑器
|
||||
import 'quill/dist/quill.core.css'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import 'quill/dist/quill.bubble.css'
|
||||
export { quillEditor }
|
||||
@ -0,0 +1,35 @@
|
||||
module.exports = {
|
||||
title: '戎归供应商管理系统',
|
||||
|
||||
/**
|
||||
* @type {boolean} true | false
|
||||
* @description Whether show the settings right-panel
|
||||
*/
|
||||
showSettings: true,
|
||||
|
||||
/**
|
||||
* @type {boolean} true | false
|
||||
* @description Whether need tagsView
|
||||
*/
|
||||
tagsView: true,
|
||||
|
||||
/**
|
||||
* @type {boolean} true | false
|
||||
* @description Whether fix the header
|
||||
*/
|
||||
fixedHeader: false,
|
||||
|
||||
/**
|
||||
* @type {boolean} true | false
|
||||
* @description Whether show the logo in sidebar
|
||||
*/
|
||||
sidebarLogo: false,
|
||||
|
||||
/**
|
||||
* @type {string | array} 'production' | ['production', 'development']
|
||||
* @description Need show err logs component.
|
||||
* The default is only used in the production env
|
||||
* If you want to also use it in dev, you can pass ['production', 'development']
|
||||
*/
|
||||
errorLog: 'production'
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
const getters = {
|
||||
sidebar: state => state.app.sidebar,
|
||||
// visitedViews: state => state.tagsView.visitedViews,
|
||||
device: state => state.app.device,
|
||||
token: state => state.user.token,
|
||||
merchantsName: state => state.user.merchantsName,
|
||||
merchantsAdminId: state => state.user.merchantsAdminId,
|
||||
detailsList: state => state.commoditydetails.detailsList,
|
||||
merchantsId: state => state.user.merchantsId,
|
||||
getstate: state => state.user.getstate,
|
||||
goodsID: state => state.goods.goodsID,
|
||||
goodstate: state => state.goods.goodstate,
|
||||
GoodsDetails: state => state.goods.GoodsDetails
|
||||
}
|
||||
export default getters
|
||||
@ -0,0 +1,28 @@
|
||||
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import getters from './getters'
|
||||
import settings from './modules/settings'
|
||||
import app from './modules/app'
|
||||
import user from './modules/user'
|
||||
import goods from './modules/goods'
|
||||
import province from './modules/province'
|
||||
import commoditydetails from './modules/commoditylistdetails'
|
||||
import Orderlist from './modules/Orderlist'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const store = new Vuex.Store({
|
||||
modules: {
|
||||
commoditydetails,
|
||||
app,
|
||||
user,
|
||||
goods,
|
||||
settings,
|
||||
Orderlist,
|
||||
province
|
||||
},
|
||||
getters
|
||||
})
|
||||
|
||||
export default store
|
||||
@ -0,0 +1,23 @@
|
||||
const getDefaultState = () => {
|
||||
return {
|
||||
code: ''
|
||||
}
|
||||
}
|
||||
const state = getDefaultState()
|
||||
|
||||
const mutations = {
|
||||
GET_CODE:(state,data)=>{ //省市县code码
|
||||
state.code = data
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
const state = {
|
||||
sidebar: {
|
||||
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
|
||||
withoutAnimation: false
|
||||
},
|
||||
device: 'desktop'
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
TOGGLE_SIDEBAR: state => {
|
||||
state.sidebar.opened = !state.sidebar.opened
|
||||
state.sidebar.withoutAnimation = false
|
||||
if (state.sidebar.opened) {
|
||||
Cookies.set('sidebarStatus', 1)
|
||||
} else {
|
||||
Cookies.set('sidebarStatus', 0)
|
||||
}
|
||||
},
|
||||
CLOSE_SIDEBAR: (state, withoutAnimation) => {
|
||||
Cookies.set('sidebarStatus', 0)
|
||||
state.sidebar.opened = false
|
||||
state.sidebar.withoutAnimation = withoutAnimation
|
||||
},
|
||||
TOGGLE_DEVICE: (state, device) => {
|
||||
state.device = device
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
toggleSideBar({ commit }) {
|
||||
commit('TOGGLE_SIDEBAR')
|
||||
},
|
||||
closeSideBar({ commit }, { withoutAnimation }) {
|
||||
commit('CLOSE_SIDEBAR', withoutAnimation)
|
||||
},
|
||||
toggleDevice({ commit }, device) {
|
||||
commit('TOGGLE_DEVICE', device)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
const state = {
|
||||
detailsList: []
|
||||
}
|
||||
const mutations = {
|
||||
DETAILS_LIST: (state, device) => {
|
||||
state.detailsList = device
|
||||
}
|
||||
}
|
||||
const actions = {
|
||||
details({ commit }, device) {
|
||||
console.log(device)
|
||||
commit('DETAILS_LIST', device)
|
||||
}
|
||||
}
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
import { $api } from '@/api/api-config' // 接口配置
|
||||
import request from '@/utils/request'
|
||||
import Cookies from 'js-cookie'
|
||||
const getDefaultState = () => {
|
||||
return {
|
||||
goodsID: Cookies.get('goodsID') ? Cookies.get('goodsID') : '',
|
||||
GoodsDetails: '',
|
||||
goodstate: Cookies.get('goodstate') ? Cookies.get('goodstate') : ''
|
||||
}
|
||||
}
|
||||
|
||||
const state = getDefaultState()
|
||||
|
||||
const mutations = {
|
||||
RESET_STATE: (state) => {
|
||||
Object.assign(state, getDefaultState())
|
||||
},
|
||||
SET_GOODSID: (state, goodsID) => {
|
||||
state.goodsID = goodsID
|
||||
},
|
||||
SET_GOODSDETAILS: (state, GoodsDetails) => {
|
||||
state.GoodsDetails = GoodsDetails
|
||||
},
|
||||
SET_GOODSTATE: (state, goodstate) => {
|
||||
state.goodstate = goodstate
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const actions = {
|
||||
// 获取商品id
|
||||
addGoods({ commit }, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post($api.addGoods, params).then(response => {
|
||||
commit('SET_GOODSID', response.goodsID)
|
||||
Cookies.set('goodsID', response.goodsID)
|
||||
resolve(response)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 编辑商品
|
||||
editGoods({ commit }, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post($api.editGoods, params).then(response => {
|
||||
resolve(response)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 商品列表获取goodid和商品state
|
||||
Editlist({ commit }, params) {
|
||||
commit('SET_GOODSID', params.goodsID)
|
||||
commit('SET_GOODSTATE', params.goodstate)
|
||||
Cookies.set('goodsID', params.goodsID)
|
||||
Cookies.set('goodstate', params.goodstate)
|
||||
},
|
||||
// 商品详情
|
||||
getGoodsDetails({ commit }, params) {
|
||||
commit('SET_GOODSDETAILS', params)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
const getDefaultState = () => {
|
||||
return {
|
||||
provinceid: '',
|
||||
cityid: '',
|
||||
countyid: ''
|
||||
}
|
||||
}
|
||||
|
||||
const state = getDefaultState()
|
||||
|
||||
const mutations = {
|
||||
RESET_STATE: (state) => {
|
||||
Object.assign(state, getDefaultState())
|
||||
},
|
||||
SET_PROVINCEID: (state, provinceid) => {
|
||||
alert(provinceid)
|
||||
state.provinceid = provinceid
|
||||
},
|
||||
SET_CITYID: (state, cityid) => {
|
||||
state.cityid = cityid
|
||||
},
|
||||
SET_COUNTYID: (state, countyid) => {
|
||||
state.countyid = countyid
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
// 获取省市县code
|
||||
getCode({ commit }, params) {
|
||||
commit('SET_PROVINCEID', params.provinceID)
|
||||
commit('SET_CITYID', params.cityID)
|
||||
commit('SET_COUNTYID', params.countyID)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
|
||||
@ -0,0 +1,160 @@
|
||||
const state = {
|
||||
visitedViews: [],
|
||||
cachedViews: []
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
ADD_VISITED_VIEW: (state, view) => {
|
||||
if (state.visitedViews.some(v => v.path === view.path)) return
|
||||
state.visitedViews.push(
|
||||
Object.assign({}, view, {
|
||||
title: view.meta.title || 'no-name'
|
||||
})
|
||||
)
|
||||
},
|
||||
ADD_CACHED_VIEW: (state, view) => {
|
||||
if (state.cachedViews.includes(view.name)) return
|
||||
if (!view.meta.noCache) {
|
||||
state.cachedViews.push(view.name)
|
||||
}
|
||||
},
|
||||
|
||||
DEL_VISITED_VIEW: (state, view) => {
|
||||
for (const [i, v] of state.visitedViews.entries()) {
|
||||
if (v.path === view.path) {
|
||||
state.visitedViews.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
DEL_CACHED_VIEW: (state, view) => {
|
||||
const index = state.cachedViews.indexOf(view.name)
|
||||
index > -1 && state.cachedViews.splice(index, 1)
|
||||
},
|
||||
|
||||
DEL_OTHERS_VISITED_VIEWS: (state, view) => {
|
||||
state.visitedViews = state.visitedViews.filter(v => {
|
||||
return v.meta.affix || v.path === view.path
|
||||
})
|
||||
},
|
||||
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
|
||||
const index = state.cachedViews.indexOf(view.name)
|
||||
if (index > -1) {
|
||||
state.cachedViews = state.cachedViews.slice(index, index + 1)
|
||||
} else {
|
||||
// if index = -1, there is no cached tags
|
||||
state.cachedViews = []
|
||||
}
|
||||
},
|
||||
|
||||
DEL_ALL_VISITED_VIEWS: state => {
|
||||
// keep affix tags
|
||||
const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
|
||||
state.visitedViews = affixTags
|
||||
},
|
||||
DEL_ALL_CACHED_VIEWS: state => {
|
||||
state.cachedViews = []
|
||||
},
|
||||
|
||||
UPDATE_VISITED_VIEW: (state, view) => {
|
||||
for (let v of state.visitedViews) {
|
||||
if (v.path === view.path) {
|
||||
v = Object.assign(v, view)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
addView({ dispatch }, view) {
|
||||
dispatch('addVisitedView', view)
|
||||
dispatch('addCachedView', view)
|
||||
},
|
||||
addVisitedView({ commit }, view) {
|
||||
commit('ADD_VISITED_VIEW', view)
|
||||
},
|
||||
addCachedView({ commit }, view) {
|
||||
commit('ADD_CACHED_VIEW', view)
|
||||
},
|
||||
|
||||
delView({ dispatch, state }, view) {
|
||||
return new Promise(resolve => {
|
||||
dispatch('delVisitedView', view)
|
||||
dispatch('delCachedView', view)
|
||||
resolve({
|
||||
visitedViews: [...state.visitedViews],
|
||||
cachedViews: [...state.cachedViews]
|
||||
})
|
||||
})
|
||||
},
|
||||
delVisitedView({ commit, state }, view) {
|
||||
return new Promise(resolve => {
|
||||
commit('DEL_VISITED_VIEW', view)
|
||||
resolve([...state.visitedViews])
|
||||
})
|
||||
},
|
||||
delCachedView({ commit, state }, view) {
|
||||
return new Promise(resolve => {
|
||||
commit('DEL_CACHED_VIEW', view)
|
||||
resolve([...state.cachedViews])
|
||||
})
|
||||
},
|
||||
|
||||
delOthersViews({ dispatch, state }, view) {
|
||||
return new Promise(resolve => {
|
||||
dispatch('delOthersVisitedViews', view)
|
||||
dispatch('delOthersCachedViews', view)
|
||||
resolve({
|
||||
visitedViews: [...state.visitedViews],
|
||||
cachedViews: [...state.cachedViews]
|
||||
})
|
||||
})
|
||||
},
|
||||
delOthersVisitedViews({ commit, state }, view) {
|
||||
return new Promise(resolve => {
|
||||
commit('DEL_OTHERS_VISITED_VIEWS', view)
|
||||
resolve([...state.visitedViews])
|
||||
})
|
||||
},
|
||||
delOthersCachedViews({ commit, state }, view) {
|
||||
return new Promise(resolve => {
|
||||
commit('DEL_OTHERS_CACHED_VIEWS', view)
|
||||
resolve([...state.cachedViews])
|
||||
})
|
||||
},
|
||||
|
||||
delAllViews({ dispatch, state }, view) {
|
||||
return new Promise(resolve => {
|
||||
dispatch('delAllVisitedViews', view)
|
||||
dispatch('delAllCachedViews', view)
|
||||
resolve({
|
||||
visitedViews: [...state.visitedViews],
|
||||
cachedViews: [...state.cachedViews]
|
||||
})
|
||||
})
|
||||
},
|
||||
delAllVisitedViews({ commit, state }) {
|
||||
return new Promise(resolve => {
|
||||
commit('DEL_ALL_VISITED_VIEWS')
|
||||
resolve([...state.visitedViews])
|
||||
})
|
||||
},
|
||||
delAllCachedViews({ commit, state }) {
|
||||
return new Promise(resolve => {
|
||||
commit('DEL_ALL_CACHED_VIEWS')
|
||||
resolve([...state.cachedViews])
|
||||
})
|
||||
},
|
||||
|
||||
updateVisitedView({ commit }, view) {
|
||||
commit('UPDATE_VISITED_VIEW', view)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
import { getToken, setToken, removeToken } from '@/utils/auth'
|
||||
import { $api } from '@/api/api-config' // 接口配置
|
||||
import request from '@/utils/request'
|
||||
import Cookies from 'js-cookie'
|
||||
const getDefaultState = () => {
|
||||
return {
|
||||
token: getToken(),
|
||||
merchantsId: Cookies.get('merchantsId') ? Cookies.get('merchantsId') : '',
|
||||
getstate: Cookies.get('state') ? Cookies.get('state') : '',
|
||||
merchantsName: Cookies.get('merchantsName') ? Cookies.get('merchantsName') : '',
|
||||
merchantsAdminId: Cookies.get('merchantsAdminId') ? Cookies.get('merchantsAdminId') : ''
|
||||
}
|
||||
}
|
||||
const state = getDefaultState()
|
||||
|
||||
const mutations = {
|
||||
RESET_STATE: (state) => {
|
||||
Object.assign(state, getDefaultState())
|
||||
},
|
||||
SET_TOKEN: (state, token) => {
|
||||
state.token = token
|
||||
setToken(token)
|
||||
},
|
||||
SET_MERCHANTSNAME: (state, merchantsName) => {
|
||||
state.merchantsName = merchantsName
|
||||
},
|
||||
SET_MERCHANTSADMINID: (state, id) => {
|
||||
state.merchantsAdminId = id
|
||||
},
|
||||
SET_STATE_CODE: (state, getstate) => {
|
||||
state.getstate = getstate
|
||||
},
|
||||
SET_MERCHANTSID: (state, merchantsid) => {
|
||||
state.merchantsId = merchantsid
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
// 用户登录
|
||||
login({ commit }, userInfo) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post($api.login, userInfo).then(response => {
|
||||
if (response.state === '1') {
|
||||
commit('SET_STATE_CODE', response.state)
|
||||
commit('SET_MERCHANTSADMINID', response.merchantsAdminId)
|
||||
commit('SET_MERCHANTSID', response.merchantsId)
|
||||
commit('SET_MERCHANTSNAME', response.merchantsName)
|
||||
Cookies.set('merchantsAdminId', response.merchantsAdminId)
|
||||
Cookies.set('merchantsId', response.merchantsId)
|
||||
Cookies.set('state', response.state)
|
||||
Cookies.set('merchantsName', response.merchantsName)
|
||||
resolve(response)
|
||||
} else {
|
||||
resolve(response)
|
||||
Cookies.remove('merchantsName')
|
||||
}
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 退出
|
||||
logout({ commit, state }) {
|
||||
return new Promise(resolve => {
|
||||
removeToken()
|
||||
Cookies.remove('merchantsName')
|
||||
sessionStorage.removeItem("userName") //退出,删除登录标识
|
||||
commit('RESET_STATE')
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
// 修改密码
|
||||
changepaw({ commit }, payload) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post($api.modiPassword, payload).then(response => {
|
||||
resolve(response)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 注册
|
||||
register({ commit }, payload) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post($api.addMerchants, payload).then(response => {
|
||||
commit('SET_STATE_CODE', response.state)
|
||||
Cookies.set('state', response.state)
|
||||
resolve(response)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 编辑供应商/店铺
|
||||
editMerchants({ commit }, payload) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post($api.editMerchants, payload).then(response => {
|
||||
commit('SET_STATE_CODE', response.state)
|
||||
Cookies.set('state', response.state)
|
||||
resolve(response)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
// cover some element-ui styles
|
||||
.el-breadcrumb__inner,
|
||||
.el-breadcrumb__inner a {
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
.el-upload {
|
||||
input[type="file"] {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-upload__input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
// to fixed https://github.com/ElemeFE/element/issues/2461
|
||||
.el-dialog {
|
||||
transform: none;
|
||||
left: 0;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
// refine element ui upload
|
||||
.upload-container {
|
||||
.el-upload {
|
||||
width: 100%;
|
||||
|
||||
.el-upload-dragger {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dropdown
|
||||
.el-dropdown-menu {
|
||||
a {
|
||||
display: block
|
||||
}
|
||||
}
|
||||
|
||||
// to fix el-date-picker css style
|
||||
.el-range-separator {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
@import './variables.scss';
|
||||
@import './mixin.scss';
|
||||
@import './transition.scss';
|
||||
@import './element-ui.scss';
|
||||
@import './sidebar.scss';
|
||||
@import './table.scss';
|
||||
body {
|
||||
height: 100%;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
|
||||
color: #2c3e50;
|
||||
background: #f6f8f9;
|
||||
font-size: 14px;
|
||||
}
|
||||
// 处理input type = number的上下箭头
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
input[type="number"]{
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
label {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
a:focus,
|
||||
a:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a,
|
||||
a:focus,
|
||||
a:hover {
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
&:after {
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: " ";
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// main-container global css
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.app-main {
|
||||
min-height: calc(100vh - 50px);
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding:20px;
|
||||
.app-main-height{
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
min-height: calc(100vh - 70px);
|
||||
}
|
||||
}
|
||||
ul,li{
|
||||
list-style: none;
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
@mixin clearfix {
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin scrollBar {
|
||||
&::-webkit-scrollbar-track-piece {
|
||||
background: #d3dce6;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #99a9bf;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin relative {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@mixin panel {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
@mixin base-scrollbar {
|
||||
&::-webkit-scrollbar {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
background-clip: padding-box;
|
||||
border: 3px solid transparent;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track:hover {
|
||||
background-color: #f8fafc;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,226 @@
|
||||
#app {
|
||||
|
||||
.main-container {
|
||||
min-height: 100%;
|
||||
transition: margin-left .28s;
|
||||
margin-left: $sideBarWidth;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
transition: width 0.28s;
|
||||
width: $sideBarWidth !important;
|
||||
background-color: $menuBg;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
font-size: 0px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1001;
|
||||
overflow: hidden;
|
||||
|
||||
// reset element-ui css
|
||||
.horizontal-collapse-transition {
|
||||
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
|
||||
}
|
||||
|
||||
.scrollbar-wrapper {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
.el-scrollbar__bar.is-vertical {
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.el-scrollbar {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&.has-logo {
|
||||
.el-scrollbar {
|
||||
height: calc(100% - 50px);
|
||||
}
|
||||
}
|
||||
|
||||
.is-horizontal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.sub-el-icon {
|
||||
margin-right: 12px;
|
||||
margin-left: -2px;
|
||||
}
|
||||
|
||||
.el-menu {
|
||||
border: none;
|
||||
height: 100%;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
// menu hover
|
||||
.submenu-title-noDropdown,
|
||||
.el-submenu__title {
|
||||
&:hover {
|
||||
background-color: $menuHover !important;
|
||||
}
|
||||
}
|
||||
|
||||
.is-active>.el-submenu__title {
|
||||
color: $subMenuActiveText !important;
|
||||
}
|
||||
|
||||
& .nest-menu .el-submenu>.el-submenu__title,
|
||||
& .el-submenu .el-menu-item {
|
||||
min-width: $sideBarWidth !important;
|
||||
background-color: $subMenuBg !important;
|
||||
|
||||
&:hover {
|
||||
background-color: $subMenuHover !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hideSidebar {
|
||||
.sidebar-container {
|
||||
width: 54px !important;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
margin-left: 54px;
|
||||
}
|
||||
|
||||
.submenu-title-noDropdown {
|
||||
padding: 0 !important;
|
||||
position: relative;
|
||||
|
||||
.el-tooltip {
|
||||
padding: 0 !important;
|
||||
|
||||
.svg-icon {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.sub-el-icon {
|
||||
margin-left: 19px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-submenu {
|
||||
overflow: hidden;
|
||||
|
||||
&>.el-submenu__title {
|
||||
padding: 0 !important;
|
||||
|
||||
.svg-icon {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.sub-el-icon {
|
||||
margin-left: 19px;
|
||||
}
|
||||
|
||||
.el-submenu__icon-arrow {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-menu--collapse {
|
||||
.el-submenu {
|
||||
&>.el-submenu__title {
|
||||
&>span {
|
||||
height: 0;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-menu--collapse .el-menu .el-submenu {
|
||||
min-width: $sideBarWidth !important;
|
||||
}
|
||||
|
||||
// mobile responsive
|
||||
.mobile {
|
||||
.main-container {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
transition: transform .28s;
|
||||
width: $sideBarWidth !important;
|
||||
}
|
||||
|
||||
&.hideSidebar {
|
||||
.sidebar-container {
|
||||
pointer-events: none;
|
||||
transition-duration: 0.3s;
|
||||
transform: translate3d(-$sideBarWidth, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.withoutAnimation {
|
||||
|
||||
.main-container,
|
||||
.sidebar-container {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// when menu collapsed
|
||||
.el-menu--vertical {
|
||||
&>.el-menu {
|
||||
.svg-icon {
|
||||
margin-right: 16px;
|
||||
}
|
||||
.sub-el-icon {
|
||||
margin-right: 12px;
|
||||
margin-left: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
.nest-menu .el-submenu>.el-submenu__title,
|
||||
.el-menu-item {
|
||||
&:hover {
|
||||
// you can use $subMenuHover
|
||||
background-color: $menuHover !important;
|
||||
}
|
||||
}
|
||||
|
||||
// the scroll bar appears when the subMenu is too long
|
||||
>.el-menu--popup {
|
||||
max-height: 100vh;
|
||||
overflow-y: auto;
|
||||
|
||||
&::-webkit-scrollbar-track-piece {
|
||||
background: #d3dce6;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #99a9bf;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
.left-panel{
|
||||
@include panel;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.right-panel{
|
||||
@include panel;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
/* 表格开始 */
|
||||
.el-table {
|
||||
.el-table__body-wrapper {
|
||||
@include base-scrollbar;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
padding: 7.5px 0;
|
||||
|
||||
.cell {
|
||||
font-size: $base-font-size-default;
|
||||
font-weight: normal;
|
||||
color: #606266;
|
||||
|
||||
.el-image {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: $base-border-radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 表格结束 */
|
||||
/* 分页开始 */
|
||||
.el-pagination {
|
||||
padding: 2px 5px;
|
||||
margin: 15px 0 0 0;
|
||||
font-weight: normal;
|
||||
color: $base-color-black;
|
||||
text-align: center;
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
// global transition css
|
||||
|
||||
/* fade */
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.28s;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-active {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* fade-transform */
|
||||
.fade-transform-leave-active,
|
||||
.fade-transform-enter-active {
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.fade-transform-enter {
|
||||
opacity: 0;
|
||||
transform: translateX(-30px);
|
||||
}
|
||||
|
||||
.fade-transform-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateX(30px);
|
||||
}
|
||||
|
||||
/* breadcrumb transition */
|
||||
.breadcrumb-enter-active,
|
||||
.breadcrumb-leave-active {
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.breadcrumb-enter,
|
||||
.breadcrumb-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
.breadcrumb-move {
|
||||
transition: all .5s;
|
||||
}
|
||||
|
||||
.breadcrumb-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
// sidebar
|
||||
$menuText:#bfcbd9;
|
||||
$menuActiveText:#409EFF;
|
||||
$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
|
||||
|
||||
$menuBg:#304156;
|
||||
$menuHover:#263445;
|
||||
|
||||
$subMenuBg:#1f2d3d;
|
||||
$subMenuHover:#001528;
|
||||
|
||||
$sideBarWidth: 210px;
|
||||
//字体大小配置
|
||||
$base-font-size-default: 14px;
|
||||
$base-border-radius: 2px;
|
||||
$base-color-black: #000;
|
||||
//默认层级
|
||||
$base-z-index: 999;
|
||||
//默认paddiing
|
||||
$base-padding: 20px;
|
||||
:export {
|
||||
menuText: $menuText;
|
||||
menuActiveText: $menuActiveText;
|
||||
subMenuActiveText: $subMenuActiveText;
|
||||
menuBg: $menuBg;
|
||||
menuHover: $menuHover;
|
||||
subMenuBg: $subMenuBg;
|
||||
subMenuHover: $subMenuHover;
|
||||
sideBarWidth: $sideBarWidth;
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
import { storage, tokenTableName } from '@/config/settings'
|
||||
import cookie from 'js-cookie'
|
||||
|
||||
/**
|
||||
* @copyright
|
||||
* @description 获取accessToken
|
||||
* @returns {string|ActiveX.IXMLDOMNode|Promise<any>|any|IDBRequest<any>|MediaKeyStatus|FormDataEntryValue|Function|Promise<Credential | null>}
|
||||
*/
|
||||
export function getAccessToken() {
|
||||
if (storage) {
|
||||
if (storage === 'localStorage') {
|
||||
return localStorage.getItem(tokenTableName)
|
||||
} else if (storage === 'sessionStorage') {
|
||||
return sessionStorage.getItem(tokenTableName)
|
||||
} else if (storage === 'cookie') {
|
||||
return cookie.get(tokenTableName)
|
||||
} else {
|
||||
return localStorage.getItem(tokenTableName)
|
||||
}
|
||||
} else {
|
||||
return localStorage.getItem(tokenTableName)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @copyright
|
||||
* @description 存储accessToken
|
||||
* @param accessToken
|
||||
* @returns {void|*}
|
||||
*/
|
||||
export function setAccessToken(accessToken) {
|
||||
if (storage) {
|
||||
if (storage === 'localStorage') {
|
||||
return localStorage.setItem(tokenTableName, accessToken)
|
||||
} else if (storage === 'sessionStorage') {
|
||||
return sessionStorage.setItem(tokenTableName, accessToken)
|
||||
} else if (storage === 'cookie') {
|
||||
return cookie.set(tokenTableName, accessToken)
|
||||
} else {
|
||||
return localStorage.setItem(tokenTableName, accessToken)
|
||||
}
|
||||
} else {
|
||||
return localStorage.setItem(tokenTableName, accessToken)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @copyright chuzhixin 1204505056@qq.com
|
||||
* @description 移除accessToken
|
||||
* @returns {void|Promise<void>}
|
||||
*/
|
||||
export function removeAccessToken() {
|
||||
if (storage) {
|
||||
if (storage === 'localStorage') {
|
||||
return localStorage.removeItem(tokenTableName)
|
||||
} else if (storage === 'sessionStorage') {
|
||||
return sessionStorage.clear()
|
||||
} else if (storage === 'cookie') {
|
||||
return cookie.remove(tokenTableName)
|
||||
} else {
|
||||
return localStorage.removeItem(tokenTableName)
|
||||
}
|
||||
} else {
|
||||
return localStorage.removeItem(tokenTableName)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
import Cookies from 'js-cookie'
|
||||
const TokenKey = 'ronggui'
|
||||
export function getToken() {
|
||||
return Cookies.get(TokenKey)
|
||||
}
|
||||
|
||||
export function setToken(token) {
|
||||
return Cookies.set(TokenKey, token)
|
||||
}
|
||||
|
||||
export function removeToken() {
|
||||
return Cookies.remove(TokenKey)
|
||||
}
|
||||