Unverified Commit 324c8da3 authored by linlinjava's avatar linlinjava Committed by GitHub
Browse files

Merge branch 'master' into dev

parents 693cf5cd 4c46da9b
......@@ -43,3 +43,10 @@ export function replyComment(data) {
data
})
}
export function listChannel(id) {
return request({
url: '/order/channel',
method: 'get'
})
}
......@@ -40,5 +40,5 @@ export function deleteStorage(data) {
})
}
const uploadPath = process.env.BASE_API + '/storage/create'
const uploadPath = process.env.VUE_APP_BASE_API + '/storage/create'
export { uploadPath }
......@@ -16,11 +16,11 @@ export function createTopic(data) {
})
}
export function readTopic(data) {
export function readTopic(query) {
return request({
url: '/topic/read',
method: 'get',
data
params: query
})
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
<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 v-else :to="item.redirect||item.path">{{ item.meta.title }}</router-link>
<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>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
......@@ -19,7 +19,11 @@ export default {
}
},
watch: {
$route() {
$route(route) {
// if you go to the redirect page, do not update the breadcrumbs
if (route.path.startsWith('/redirect/')) {
return
}
this.getBreadcrumb()
}
},
......@@ -28,27 +32,46 @@ export default {
},
methods: {
getBreadcrumb() {
const { params } = this.$route
let matched = this.$route.matched.filter(item => {
if (item.name) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
var toPath = pathToRegexp.compile(item.path)
item.path = toPath(params)
return true
}
})
// only show routes with meta.title
let matched = this.$route.matched.filter(
item => item.meta && item.meta.title
)
const first = matched[0]
if (first && first.name.trim().toLocaleLowerCase() !== 'Dashboard'.toLocaleLowerCase()) {
if (!this.isDashboard(first)) {
matched = [{ path: '/dashboard', meta: { title: '首页' }}].concat(matched)
}
this.levelList = 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() === 'Dashboard'.toLocaleLowerCase())
},
pathCompile(path) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
},
handleLink(item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
......@@ -57,5 +80,5 @@ export default {
color: #97a8be;
cursor: text;
}
}
}
</style>
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName"/>
<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>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
......@@ -18,6 +21,9 @@ export default {
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
......@@ -27,6 +33,12 @@ export default {
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
......@@ -40,4 +52,9 @@ export default {
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>
// set function parseTime,formatTime to filter
// import parseTime, formatTime and set to filter
export { parseTime, formatTime } from '@/utils'
/**
* Show plural label if time is plural number
* @param {number} time
* @param {string} label
* @return {string}
*/
function pluralize(time, label) {
if (time === 1) {
return time + label
......@@ -8,6 +14,9 @@ function pluralize(time, label) {
return time + label + 's'
}
/**
* @param {number} time
*/
export function timeAgo(time) {
const between = Date.now() / 1000 - Number(time)
if (between < 3600) {
......@@ -19,7 +28,12 @@ export function timeAgo(time) {
}
}
/* 数字 格式化*/
/**
* Number formatting
* like 10000 => 10k
* @param {number} num
* @param {number} digits
*/
export function numberFormatter(num, digits) {
const si = [
{ value: 1E18, symbol: 'E' },
......@@ -31,12 +45,24 @@ export function numberFormatter(num, digits) {
]
for (let i = 0; i < si.length; i++) {
if (num >= si[i].value) {
return (num / si[i].value + 0.1).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
return (num / si[i].value).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
}
}
return num.toString()
}
/**
* 10000 => "10,000"
* @param {number} num
*/
export function toThousandFilter(num) {
return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
}
/**
* Upper case first char
* @param {String} string
*/
export function uppercaseFirst(string) {
return string.charAt(0).toUpperCase() + string.slice(1)
}
......@@ -5,13 +5,13 @@ import Cookies from 'js-cookie'
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import './styles/element-variables.scss'
import '@/styles/index.scss' // global css
import App from './App'
import router from './router'
import store from './store'
import router from './router'
import './icons' // icon
import './permission' // permission control
......@@ -20,6 +20,10 @@ import * as filters from './filters' // global filters
import permission from '@/directive/permission/index.js' // 权限判断指令
import Print from '@/utils/print' // 打印
Vue.use(Print)
Vue.use(Element, {
size: Cookies.get('size') || 'medium' // set element-ui default size
})
......
......@@ -65,7 +65,7 @@ export const constantRouterMap = [
path: 'dashboard',
component: () => import('@/views/dashboard/index'),
name: 'Dashboard',
meta: { title: '首页', icon: 'dashboard', noCache: true }
meta: { title: '首页', icon: 'dashboard', affix: true }
}
]
}
......@@ -331,6 +331,28 @@ export const asyncRouterMap = [
noCache: true
}
},
{
path: 'topic-create',
component: () => import('@/views/promotion/topicCreate'),
name: 'topicCreate',
meta: {
perms: ['POST /admin/topic/create'],
title: '专题创建',
noCache: true
},
hidden: true
},
{
path: 'topic-edit',
component: () => import('@/views/promotion/topicEdit'),
name: 'topicEdit',
meta: {
perms: ['GET /admin/topic/read', 'POST /admin/topic/update'],
title: '专题编辑',
noCache: true
},
hidden: true
},
{
path: 'groupon-rule',
component: () => import('@/views/promotion/grouponRule'),
......@@ -380,7 +402,7 @@ export const asyncRouterMap = [
component: () => import('@/views/sys/log'),
name: 'log',
meta: {
perms: ['GET /admin/admin/log'],
perms: ['GET /admin/log/list'],
title: '操作日志',
noCache: true
}
......@@ -400,7 +422,7 @@ export const asyncRouterMap = [
component: () => import('@/views/sys/os'),
name: 'os',
meta: {
perms: ['GET /admin/os/list', 'POST /admin/os/create', 'POST /admin/os/update', 'POST /admin/os/delete'],
perms: ['GET /admin/storage/list', 'POST /admin/storage/create', 'POST /admin/storage/update', 'POST /admin/storage/delete'],
title: '对象存储',
noCache: true
}
......
const tagsView = {
state: {
const state = {
visitedViews: [],
cachedViews: []
},
mutations: {
}
const mutations = {
ADD_VISITED_VIEW: (state, view) => {
if (state.visitedViews.some(v => v.path === view.path)) return
state.visitedViews.push(
......@@ -28,35 +28,29 @@ const tagsView = {
}
},
DEL_CACHED_VIEW: (state, view) => {
for (const i of state.cachedViews) {
if (i === view.name) {
const index = state.cachedViews.indexOf(i)
state.cachedViews.splice(index, 1)
break
}
}
const index = state.cachedViews.indexOf(view.name)
index > -1 && state.cachedViews.splice(index, 1)
},
DEL_OTHERS_VISITED_VIEWS: (state, view) => {
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
state.visitedViews = state.visitedViews.slice(i, i + 1)
break
}
}
state.visitedViews = state.visitedViews.filter(v => {
return v.meta.affix || v.path === view.path
})
},
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
for (const i of state.cachedViews) {
if (i === view.name) {
const index = state.cachedViews.indexOf(i)
const index = state.cachedViews.indexOf(view.name)
if (index > -1) {
state.cachedViews = state.cachedViews.slice(index, index + 1)
break
}
} else {
// if index = -1, there is no cached tags
state.cachedViews = []
}
},
DEL_ALL_VISITED_VIEWS: state => {
state.visitedViews = []
// keep affix tags
const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
state.visitedViews = affixTags
},
DEL_ALL_CACHED_VIEWS: state => {
state.cachedViews = []
......@@ -70,9 +64,9 @@ const tagsView = {
}
}
}
}
},
actions: {
const actions = {
addView({ dispatch }, view) {
dispatch('addVisitedView', view)
dispatch('addCachedView', view)
......@@ -156,7 +150,11 @@ const tagsView = {
updateVisitedView({ commit }, view) {
commit('UPDATE_VISITED_VIEW', view)
}
}
}
export default tagsView
export default {
namespaced: true,
state,
mutations,
actions
}
......@@ -53,7 +53,7 @@ const user = {
const username = userInfo.username.trim()
return new Promise((resolve, reject) => {
loginByUsername(username, userInfo.password).then(response => {
const token = response.data.data
const token = response.data.data.token
commit('SET_TOKEN', token)
setToken(token)
resolve()
......
......@@ -2,8 +2,10 @@
@mixin colorBtn($color) {
background: $color;
&:hover {
color: $color;
&:before,
&:after {
background: $color;
......@@ -49,14 +51,17 @@
transition: 600ms ease all;
position: relative;
display: inline-block;
&:hover {
background: #fff;
&:before,
&:after {
width: 100%;
transition: 600ms ease all;
}
}
&:before,
&:after {
content: '';
......@@ -67,6 +72,7 @@
width: 0;
transition: 400ms ease all;
}
&::after {
right: inherit;
top: inherit;
......@@ -91,4 +97,3 @@
font-size: 14px;
border-radius: 4px;
}
//覆盖一些element-ui样式
// cover some element-ui styles
.el-breadcrumb__inner, .el-breadcrumb__inner a{
font-weight: 400!important;
.el-breadcrumb__inner,
.el-breadcrumb__inner a {
font-weight: 400 !important;
}
.el-upload {
.el-upload {
input[type="file"] {
display: none !important;
}
}
}
.el-upload__input {
.el-upload__input {
display: none;
}
}
.cell {
.cell {
.el-tag {
margin-right: 0px;
}
}
}
.small-padding {
.small-padding {
.cell {
padding-left: 5px;
padding-right: 5px;
}
}
}
.fixed-width{
.el-button--mini{
.fixed-width {
.el-button--mini {
padding: 7px 10px;
width: 60px;
}
}
}
.status-col {
.status-col {
.cell {
padding: 0 10px;
text-align: center;
.el-tag {
margin-right: 0px;
}
}
}
}
//暂时性解决dialog 问题 https://github.com/ElemeFE/element/issues/2461
.el-dialog {
// to fixed https://github.com/ElemeFE/element/issues/2461
.el-dialog {
transform: none;
left: 0;
position: relative;
margin: 0 auto;
}
//文章页textarea修改样式
.article-textarea {
textarea {
padding-right: 40px;
resize: none;
border: none;
border-radius: 0px;
border-bottom: 1px solid #bfcbd9;
}
}
}
//element ui upload
.upload-container {
// refine element ui upload
.upload-container {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
height: 200px;
}
}
}
}
//dropdown
.el-dropdown-menu{
a{
// dropdown
.el-dropdown-menu {
a {
display: block
}
}
// fix date-picker ui bug in filter-item
.el-range-editor.el-input__inner {
display: inline-flex !important;
}
// to fix el-date-picker css style
.el-range-separator {
box-sizing: content-box;
}
/**
* I think element-ui's default theme color is too light for long-term use.
* So I modified the default color and you can modify it to your liking.
**/
/* theme color */
$--color-primary: #1890ff;
$--color-success: #13ce66;
$--color-warning: #FFBA00;
$--color-danger: #ff4949;
// $--color-info: #1E1E1E;
$--button-font-weight: 400;
// $--color-text-regular: #1f2d3d;
$--border-color-light: #dfe4ed;
$--border-color-lighter: #e6ebf5;
$--table-border:1px solid#dfe6ec;
/* icon font path, required */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
theme: $--color-primary;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment