@ -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,54 @@
|
||||
{
|
||||
"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.24.0",
|
||||
"clipboard": "^2.0.8",
|
||||
"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.5",
|
||||
"js-cookie": "^2.2.1",
|
||||
"normalize.css": "^8.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^6.1.0",
|
||||
"sass": "^1.26.5",
|
||||
"sortablejs": "^1.14.0",
|
||||
"svg-sprite-loader": "^5.0.0",
|
||||
"uuid": "^8.3.2",
|
||||
"uuidjs": "^4.2.9",
|
||||
"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",
|
||||
"vuex": "^3.4.0",
|
||||
"wangeditor": "^4.0.3",
|
||||
"xlsx": "^0.17.4",
|
||||
"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",
|
||||
"node-sass": "^6.0.1",
|
||||
"prettier": "^1.19.1",
|
||||
"sass-loader": "^10.2.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,10 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
#app {
|
||||
min-width: 1200px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,47 @@
|
||||
let httpUrl, uploadAvatarImg, pick
|
||||
// 商户后台
|
||||
// 设置环境 ,生产需要设置为 1
|
||||
// 0:test 1:produce
|
||||
/**
|
||||
* 总后台测试环境的 账号:wanghao111 密码:123456
|
||||
*/
|
||||
// 生产环境
|
||||
// const _ENV = '1'
|
||||
// 测试环境
|
||||
const _ENV = '0'
|
||||
|
||||
|
||||
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/admin' // 测试环境
|
||||
// uploadAvatarImg = 'http://t.81ronggui.com:8082/ronghui/rh' // 原来的测试环境
|
||||
uploadAvatarImg = 'https://www.rongui.cn/ronghui/admin' // 现在的上传基础地址
|
||||
// 省市区请求
|
||||
pick = 'http://t.81ronggui.com:8082/ronghui/rh'
|
||||
|
||||
// uploadAvatarImg = 'http:/tb.81ronggui.com/ronghui/rh'
|
||||
// uploadAvatarImg = 'http://b.81ronggui.com/ronggui/b'
|
||||
break
|
||||
case 'pro_url':
|
||||
httpUrl = 'https://www.rongui.cn/ronghui/admin' // 生产环境
|
||||
// uploadAvatarImg = 'https://b.81ronggui.com:8445/ronggui/b' // 域名
|
||||
uploadAvatarImg = 'https://www.rongui.cn/ronghui/admin' // 测试环境上传基础地址
|
||||
// 省市区请求
|
||||
pick = 'https://www.rongui.cn/ronghui/rh'
|
||||
// uploadAvatarImg = 'https://172.17.181.128:8445/ronggui/b'
|
||||
// pick = 'http://t.81ronggui.com:8082/ronghui/rh'
|
||||
break
|
||||
}
|
||||
export const HTTP_URL = httpUrl
|
||||
export const UPLOADAVATARIMG = uploadAvatarImg
|
||||
export const pick_Url = pick
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 160 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 761 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: 3.8 KiB |
|
After Width: | Height: | Size: 2.6 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)
|
||||
|
||||
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>
|
||||
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<el-cascader
|
||||
v-model="selectedOptions"
|
||||
size="large"
|
||||
:options="options"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</template>
|
||||
<script>
|
||||
import { regionData, CodeToText, TextToCode } from 'element-china-area-data'
|
||||
import { data } from './regions'
|
||||
import { mapState } from 'vuex'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
options: regionData,
|
||||
selectedOptions: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
code: state => state.Orderlist.code
|
||||
})
|
||||
},
|
||||
created() {
|
||||
// console.log(regionData)
|
||||
// console.log(data)
|
||||
// this.selectedOptions=[TextToCode[this.code[0]].code,TextToCode[this.code[0]][this.code[1]].code,TextToCode[this.code[0]][this.code[1]][this.code[2]].code]
|
||||
},
|
||||
methods: {
|
||||
handleChange(value) {
|
||||
const address = `${CodeToText[value[0]]}${CodeToText[value[1]]}${CodeToText[value[2]]}`
|
||||
const data = {
|
||||
selectedOptions: this.selectedOptions,
|
||||
address: address
|
||||
}
|
||||
// this.$store.commit("Orderlist/GET_CODE",[CodeToText[value[0]],CodeToText[value[1]],CodeToText[value[0]]])
|
||||
// this.$emit('handleChange',data)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
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: 1.4 KiB |
|
After Width: | Height: | Size: 285 B |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 821 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
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: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.4 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,132 @@
|
||||
<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">
|
||||
<span>{{ userName }}</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', 'userName'])
|
||||
},
|
||||
methods: {
|
||||
toggleSideBar() {
|
||||
this.$store.dispatch('app/toggleSideBar')
|
||||
},
|
||||
async logout() {
|
||||
this.$store.dispatch('user/logout')
|
||||
this.$router.push(`/login`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</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,87 @@
|
||||
<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,88 @@
|
||||
<template>
|
||||
<div v-if="!item.hidden">
|
||||
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
|
||||
<app-link v-if="onlyOneChild.menu_name" :to="resolvePath(onlyOneChild.path)">
|
||||
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
|
||||
<item :title="onlyOneChild.menu_name" />
|
||||
</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.menu_name" :title="item.menu_name" />
|
||||
</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,115 @@
|
||||
<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
|
||||
let strArry = sessionStorage.getItem("menuList");
|
||||
let objArry = JSON.parse(strArry);
|
||||
// console.log(objArry, "777777777777777");
|
||||
let arr1 = [];
|
||||
let arr2 = [];
|
||||
for (let i = 0; i < objArry.length; i++) {
|
||||
if (objArry[i].parent_id == 0) {
|
||||
arr1.push(objArry[i]);
|
||||
arr2.push(objArry[i].menu_id); //手动添加一级菜单
|
||||
}
|
||||
// console.log(arr1, "00000000000000");
|
||||
}
|
||||
for (let k = 0; k < arr1.length; k++) {
|
||||
let children = [];
|
||||
|
||||
// console.log(arr1[k])
|
||||
|
||||
for (let j = 0; j < objArry.length; j++) {
|
||||
if (objArry[j].parent_id == arr1[k].menu_id) {
|
||||
children.push(objArry[j]);
|
||||
// console.log(arr1, "111111111");
|
||||
} else {
|
||||
}
|
||||
}
|
||||
arr1[k].children = children;
|
||||
}
|
||||
for (let x = 0; x < objArry.length; x++) {
|
||||
if (
|
||||
objArry[x].parent_id != 0 &&
|
||||
arr2.indexOf(objArry[x].parent_id) == -1
|
||||
) {
|
||||
// console.log(objArry[x])
|
||||
arr1.push(objArry[x]);
|
||||
}
|
||||
}
|
||||
return arr1;
|
||||
// for(let j=0; j<objArry.length;j++){
|
||||
// for()
|
||||
// if(objArry[j].parent_id==){
|
||||
// arr1.push(objArry[i])
|
||||
// console.log(arr1,"00000000000000")
|
||||
// }
|
||||
|
||||
// };
|
||||
// for(let i in objArry){
|
||||
// //var o={};
|
||||
// //o[i]=jsonObj[i];
|
||||
// arr1.push(objArry[i]);
|
||||
// }
|
||||
// console.log(arr1)
|
||||
return objArry;
|
||||
},
|
||||
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;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
// console.log(this.$router.options.routes);
|
||||
// console.log(typeof(this.$router.options.routes))
|
||||
// console.log(typeof(sessionStorage.getItem("menuList"),"111111111"))
|
||||
},
|
||||
};
|
||||
</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,34 @@
|
||||
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' // 接口配置
|
||||
Vue.prototype.$api = $api
|
||||
import './permission' // 权限控制
|
||||
// 过滤器
|
||||
import filters from './utils/filters'
|
||||
// 日期时间格式化
|
||||
import './utils/date.js'
|
||||
|
||||
for (const k in filters) {
|
||||
Vue.filter(k, filters[k])
|
||||
}
|
||||
Vue.prototype.$echarts = echarts
|
||||
Vue.use(ElementUI)
|
||||
Vue.config.productionTip = false
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
@ -0,0 +1,32 @@
|
||||
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('adminName') // 获取登录标识
|
||||
next()
|
||||
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,13 @@
|
||||
const getters = {
|
||||
sidebar: state => state.app.sidebar,
|
||||
device: state => state.app.device,
|
||||
userID: state => state.user.userID,
|
||||
adminName: state => state.user.adminName,
|
||||
userName:state=>state.user.userName,
|
||||
detailsList: state => state.commoditydetails.detailsList,
|
||||
goodsID: state => state.goods.goodsID,
|
||||
goodstate: state => state.goods.goodstate,
|
||||
GoodsDetails: state => state.goods.GoodsDetails
|
||||
|
||||
}
|
||||
export default getters
|
||||
@ -0,0 +1,30 @@
|
||||
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import getters from './getters'
|
||||
import app from './modules/app'
|
||||
import settings from './modules/settings'
|
||||
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'
|
||||
import partner from './modules/partner'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const store = new Vuex.Store({
|
||||
modules: {
|
||||
commoditydetails,
|
||||
app,
|
||||
settings,
|
||||
user,
|
||||
goods,
|
||||
Orderlist,
|
||||
province,
|
||||
partner
|
||||
},
|
||||
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,80 @@
|
||||
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()
|
||||
}).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) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post($api.getGoodsDetails, params).then(response => {
|
||||
// console.log(response)
|
||||
// commit('SET_GOODSDETAILS', response)
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
import { $api } from '@/api/api-config' // 接口配置
|
||||
import request from '@/utils/request'
|
||||
// import Cookies from 'js-cookie'
|
||||
const getDefaultState = () => {
|
||||
return {
|
||||
provinceDetails: []
|
||||
}
|
||||
}
|
||||
|
||||
const state = getDefaultState()
|
||||
|
||||
const mutations = {
|
||||
|
||||
}
|
||||
|
||||
const actions = {
|
||||
// 新增渠道商
|
||||
addPartner({ commit }, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.post($api.addPartner, params).then(response => {
|
||||
// console.log('渠道商')
|
||||
// console.log(response)
|
||||
resolve(response)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
Details({ commit }, params) {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// request.post($api.addPartner, params).then(response => {
|
||||
// console.log("渠道商")
|
||||
// console.log(response)
|
||||
// resolve(response)
|
||||
// }).catch(error => {
|
||||
// reject(error)
|
||||
// })
|
||||
// })
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
|
||||