Commit 6f0ebe3e authored by Junling Bu's avatar Junling Bu
Browse files

chore[litemall-admin]: 管理后台基于的vue-element-admin框架更新至3.9.3

parent cffdc561
<template> <template>
<div class="app-container calendar-list-container"> <div class="app-container">
<!-- 查询和其他操作 --> <!-- 查询和其他操作 -->
<div class="filter-container"> <div class="filter-container">
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入商品编号" v-model="listQuery.goodsSn"> <el-input v-model="listQuery.goodsSn" clearable class="filter-item" style="width: 200px;" placeholder="请输入商品编号"/>
</el-input> <el-input v-model="listQuery.name" clearable class="filter-item" style="width: 200px;" placeholder="请输入商品名称"/>
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入商品名称" v-model="listQuery.name">
</el-input>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button> <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-button class="filter-item" type="primary" @click="handleCreate" icon="el-icon-edit">添加</el-button> <el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">添加</el-button>
<el-button class="filter-item" type="primary" :loading="downloadLoading" icon="el-icon-download" @click="handleDownload">导出</el-button> <el-button :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">导出</el-button>
</div> </div>
<!-- 查询结果 --> <!-- 查询结果 -->
<el-table size="small" :data="list" v-loading="listLoading" element-loading-text="正在查询中。。。" border fit highlight-current-row> <el-table v-loading="listLoading" :data="list" size="small" element-loading-text="正在查询中。。。" border fit highlight-current-row>
<el-table-column type="expand"> <el-table-column type="expand">
<template slot-scope="props"> <template slot-scope="props">
<el-form label-position="left" class="table-expand"> <el-form label-position="left" class="table-expand">
<el-form-item label="宣传画廊"> <el-form-item label="宣传画廊">
<img class="gallery" v-for="pic in props.row.gallery" :key="pic" :src="pic"/> <img v-for="pic in props.row.gallery" :key="pic" :src="pic" class="gallery">
</el-form-item> </el-form-item>
<el-form-item label="商品介绍"> <el-form-item label="商品介绍">
<span>{{ props.row.brief }}</span> <span>{{ props.row.brief }}</span>
...@@ -40,74 +38,65 @@ ...@@ -40,74 +38,65 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="商品编号" prop="goodsSn"> <el-table-column align="center" label="商品编号" prop="goodsSn"/>
</el-table-column>
<el-table-column align="center" min-width="100" label="名称" prop="name"> <el-table-column align="center" min-width="100" label="名称" prop="name"/>
</el-table-column>
<el-table-column align="center" property="iconUrl" label="图片"> <el-table-column align="center" property="iconUrl" label="图片">
<template slot-scope="scope"> <template slot-scope="scope">
<img :src="scope.row.picUrl" width="40"/> <img :src="scope.row.picUrl" width="40">
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" property="iconUrl" label="分享图"> <el-table-column align="center" property="iconUrl" label="分享图">
<template slot-scope="scope"> <template slot-scope="scope">
<img :src="scope.row.shareUrl" width="40"/> <img :src="scope.row.shareUrl" width="40">
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="详情" prop="detail"> <el-table-column align="center" label="详情" prop="detail">
<template slot-scope="scope"> <template slot-scope="scope">
<el-dialog title="商品详情" :visible.sync="detailDialogVisible"> <el-dialog :visible.sync="detailDialogVisible" title="商品详情">
<div v-html="goodsDetail"></div> <div v-html="goodsDetail"/>
</el-dialog> </el-dialog>
<el-button type="primary" size="mini" @click="showDetail(scope.row.detail)">查看</el-button> <el-button type="primary" size="mini" @click="showDetail(scope.row.detail)">查看</el-button>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="专柜价格" prop="counterPrice"> <el-table-column align="center" label="专柜价格" prop="counterPrice"/>
</el-table-column>
<el-table-column align="center" label="当前价格" prop="retailPrice"> <el-table-column align="center" label="当前价格" prop="retailPrice"/>
</el-table-column>
<el-table-column align="center" label="是否新品" prop="isNew"> <el-table-column align="center" label="是否新品" prop="isNew">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.isNew ? 'success' : 'error' ">{{scope.row.isNew ? '新品' : '非新品'}}</el-tag> <el-tag :type="scope.row.isNew ? 'success' : 'error' ">{{ scope.row.isNew ? '新品' : '非新品' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="是否热品" prop="isHot"> <el-table-column align="center" label="是否热品" prop="isHot">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.isHot ? 'success' : 'error' ">{{scope.row.isHot ? '热品' : '非热品'}}</el-tag> <el-tag :type="scope.row.isHot ? 'success' : 'error' ">{{ scope.row.isHot ? '热品' : '非热品' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="是否在售" prop="isOnSale"> <el-table-column align="center" label="是否在售" prop="isOnSale">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.isOnSale ? 'success' : 'error' ">{{scope.row.isOnSale ? '在售' : '未售'}}</el-tag> <el-tag :type="scope.row.isOnSale ? 'success' : 'error' ">{{ scope.row.isOnSale ? '在售' : '未售' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="操作" width="200" class-name="small-padding fixed-width"> <el-table-column align="center" label="操作" width="200" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button> <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button> <el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页 --> <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
<div class="pagination-container">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page"
:page-sizes="[10,20,30,50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<el-tooltip placement="top" content="返回顶部"> <el-tooltip placement="top" content="返回顶部">
<back-to-top :visibilityHeight="100" ></back-to-top> <back-to-top :visibility-height="100" />
</el-tooltip> </el-tooltip>
</div> </div>
...@@ -134,10 +123,11 @@ ...@@ -134,10 +123,11 @@
<script> <script>
import { listGoods, deleteGoods } from '@/api/goods' import { listGoods, deleteGoods } from '@/api/goods'
import BackToTop from '@/components/BackToTop' import BackToTop from '@/components/BackToTop'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
export default { export default {
name: 'GoodsList', name: 'GoodsList',
components: { BackToTop }, components: { BackToTop, Pagination },
data() { data() {
return { return {
list: [], list: [],
...@@ -176,14 +166,6 @@ export default { ...@@ -176,14 +166,6 @@ export default {
this.listQuery.page = 1 this.listQuery.page = 1
this.getList() this.getList()
}, },
handleSizeChange(val) {
this.listQuery.limit = val
this.getList()
},
handleCurrentChange(val) {
this.listQuery.page = val
this.getList()
},
handleCreate() { handleCreate() {
this.$router.push({ path: '/goods/create' }) this.$router.push({ path: '/goods/create' })
}, },
......
<template> <template>
<div class="app-wrapper" :class="{hideSidebar:!sidebar.opened}"> <div :class="classObj" class="app-wrapper">
<sidebar class="sidebar-container"></sidebar> <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
<div class="main-container"> <sidebar class="sidebar-container"/>
<navbar></navbar> <div class="main-container">
<tags-view></tags-view> <navbar/>
<app-main></app-main> <tags-view/>
</div> <app-main/>
</div> </div>
</div>
</template> </template>
<script> <script>
import { Navbar, Sidebar, AppMain, TagsView } from './components' import { Navbar, Sidebar, AppMain, TagsView } from './components'
import ResizeMixin from './mixin/ResizeHandler'
export default { export default {
name: 'layout', name: 'Layout',
components: { components: {
Navbar, Navbar,
Sidebar, Sidebar,
AppMain, AppMain,
TagsView TagsView
}, },
mixins: [ResizeMixin],
computed: { computed: {
sidebar() { sidebar() {
return this.$store.state.app.sidebar return this.$store.state.app.sidebar
},
device() {
return this.$store.state.app.device
},
classObj() {
return {
hideSidebar: !this.sidebar.opened,
openSidebar: this.sidebar.opened,
withoutAnimation: this.sidebar.withoutAnimation,
mobile: this.device === 'mobile'
}
}
},
methods: {
handleClickOutside() {
this.$store.dispatch('closeSideBar', { withoutAnimation: false })
} }
} }
} }
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
@import "src/styles/mixin.scss"; @import "src/styles/mixin.scss";
.app-wrapper { .app-wrapper {
@include clearfix; @include clearfix;
position: relative; position: relative;
height: 100%; height: 100%;
width: 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;
}
</style> </style>
<template> <template>
<section class="app-main" style="min-height: 100%"> <section class="app-main">
<transition name="fade" mode="out-in"> <transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews"> <keep-alive :include="cachedViews">
<router-view></router-view> <router-view :key="key"/>
</keep-alive> </keep-alive>
</transition> </transition>
</section> </section>
...@@ -14,10 +14,21 @@ export default { ...@@ -14,10 +14,21 @@ export default {
computed: { computed: {
cachedViews() { cachedViews() {
return this.$store.state.tagsView.cachedViews return this.$store.state.tagsView.cachedViews
},
key() {
return this.$route.fullPath
} }
// key() {
// return this.$route.name !== undefined ? this.$route.name + +new Date() : this.$route + +new Date()
// }
} }
} }
</script> </script>
<style scoped>
.app-main {
/*84 = navbar + tags-view = 50 +34 */
min-height: calc(100vh - 84px);
width: 100%;
position: relative;
overflow: hidden;
}
</style>
<template> <template>
<el-menu class="navbar" mode="horizontal"> <div class="navbar">
<hamburger class="hamburger-container" :toggleClick="toggleSideBar" :isActive="sidebar.opened"></hamburger> <hamburger :toggle-click="toggleSideBar" :is-active="sidebar.opened" class="hamburger-container"/>
<breadcrumb class="breadcrumb-container"></breadcrumb> <breadcrumb class="breadcrumb-container"/>
<div class="right-menu"> <div class="right-menu">
<template v-if="device!=='mobile'">
<el-tooltip effect="dark" content="全屏" placement="bottom"> <el-tooltip :content="$t('navbar.screenfull')" effect="dark" placement="bottom">
<screenfull class="screenfull right-menu-item"></screenfull> <screenfull class="screenfull right-menu-item"/>
</el-tooltip> </el-tooltip>
<el-tooltip :content="$t('navbar.size')" effect="dark" placement="bottom">
<size-select class="international right-menu-item"/>
</el-tooltip>
<lang-select class="international right-menu-item"/>
<el-tooltip :content="$t('navbar.theme')" effect="dark" placement="bottom">
<theme-picker class="theme-switch right-menu-item"/>
</el-tooltip>
</template>
<el-dropdown class="avatar-container right-menu-item" trigger="click"> <el-dropdown class="avatar-container right-menu-item" trigger="click">
<div class="avatar-wrapper"> <div class="avatar-wrapper">
<img class="user-avatar" :src="avatar+'?imageView2/1/w/80/h/80'"> <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
<i class="el-icon-caret-bottom"></i> <i class="el-icon-caret-bottom"/>
</div> </div>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item> <router-link to="/">
<router-link to="/"> <el-dropdown-item>
主页 {{ $t('navbar.dashboard') }}
</router-link> </el-dropdown-item>
</el-dropdown-item> </router-link>
<el-dropdown-item divided> <el-dropdown-item divided>
<a target='_blank' href="https://github.com/linlinjava/litemall"> <a target="_blank" href="https://github.com/linlinjava/litemall">
GitHub GitHub
</a> </a>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item> <el-dropdown-item>
<a target='_blank' href="https://gitee.com/linlinjava/litemall"> <a target="_blank" href="https://gitee.com/linlinjava/litemall">
码云 码云
</a> </a>
</el-dropdown-item> </el-dropdown-item>
...@@ -37,12 +49,12 @@ ...@@ -37,12 +49,12 @@
</router-link> </router-link>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item divided> <el-dropdown-item divided>
<span @click="logout" style="display:block;">退出登录</span> <span style="display:block;" @click="logout">{{ $t('navbar.logOut') }}</span>
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</div> </div>
</el-menu> </div>
</template> </template>
<script> <script>
...@@ -50,18 +62,25 @@ import { mapGetters } from 'vuex' ...@@ -50,18 +62,25 @@ import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb' import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger' import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull' import Screenfull from '@/components/Screenfull'
import SizeSelect from '@/components/SizeSelect'
import LangSelect from '@/components/LangSelect'
import ThemePicker from '@/components/ThemePicker'
export default { export default {
components: { components: {
Breadcrumb, Breadcrumb,
Hamburger, Hamburger,
Screenfull Screenfull,
SizeSelect,
LangSelect,
ThemePicker
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
'sidebar', 'sidebar',
'name', 'name',
'avatar' 'avatar',
'device'
]) ])
}, },
methods: { methods: {
...@@ -108,6 +127,12 @@ export default { ...@@ -108,6 +127,12 @@ export default {
.screenfull { .screenfull {
height: 20px; height: 20px;
} }
.international{
vertical-align: top;
}
.theme-switch {
vertical-align: 15px;
}
.avatar-container { .avatar-container {
height: 50px; height: 50px;
margin-right: 30px; margin-right: 30px;
......
export default {
computed: {
device() {
return this.$store.state.app.device
}
},
mounted() {
// In order to fix the click on menu on the ios device will trigger the mouseeleave bug
// https://github.com/PanJiaChen/vue-element-admin/issues/1135
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)
}
}
}
}
}
<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) {
vnodes.push(<svg-icon icon-class={icon}/>)
}
if (title) {
vnodes.push(<span slot='title'>{(title)}</span>)
}
return vnodes
}
}
</script>
<template>
<!-- eslint-disable vue/require-component-is-->
<component v-bind="linkProps(to)">
<slot/>
</component>
</template>
<script>
import { isExternal } from '@/utils'
export default {
props: {
to: {
type: String,
required: true
}
},
methods: {
isExternalLink(routePath) {
return isExternal(routePath)
},
linkProps(url) {
if (this.isExternalLink(url)) {
return {
is: 'a',
href: url,
target: '_blank',
rel: 'noopener'
}
}
return {
is: 'router-link',
to: url
}
}
}
}
</script>
<template> <template>
<div class="menu-wrapper"> <div v-if="!item.hidden&&item.children" class="menu-wrapper">
<template v-for="item in routes" v-if="!item.hidden&&item.children">
<router-link v-if="item.children.length===1 && !item.children[0].children&&!item.alwaysShow" :to="item.path+'/'+item.children[0].path" :key="item.children[0].name"> <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<el-menu-item :index="item.path+'/'+item.children[0].path" :class="{'submenu-title-noDropdown':!isNest}"> <app-link :to="resolvePath(onlyOneChild.path)">
<svg-icon v-if="item.children[0].meta&&item.children[0].meta.icon" :icon-class="item.children[0].meta.icon"></svg-icon> <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<span v-if="item.children[0].meta&&item.children[0].meta.title">{{item.children[0].meta.title}}</span> <item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon||item.meta.icon" :title="generateTitle(onlyOneChild.meta.title)" />
</el-menu-item> </el-menu-item>
</router-link> </app-link>
<el-submenu v-else :index="item.name||item.path" :key="item.name">
<template slot="title">
<svg-icon v-if="item.meta&&item.meta.icon" :icon-class="item.meta.icon"></svg-icon>
<span v-if="item.meta&&item.meta.title">{{item.meta.title}}</span>
</template>
<template v-for="child in item.children" v-if="!child.hidden">
<sidebar-item :is-nest="true" class="nest-menu" v-if="child.children&&child.children.length>0" :routes="[child]" :key="child.path"></sidebar-item>
<router-link v-else :to="item.path+'/'+child.path" :key="child.name">
<el-menu-item :index="item.path+'/'+child.path">
<svg-icon v-if="child.meta&&child.meta.icon" :icon-class="child.meta.icon"></svg-icon>
<span v-if="child.meta&&child.meta.title">{{child.meta.title}}</span>
</el-menu-item>
</router-link>
</template>
</el-submenu>
</template> </template>
<el-submenu v-else ref="submenu" :index="resolvePath(item.path)">
<template slot="title">
<item v-if="item.meta" :icon="item.meta.icon" :title="generateTitle(item.meta.title)" />
</template>
<template v-for="child in item.children" v-if="!child.hidden">
<sidebar-item
v-if="child.children&&child.children.length>0"
:is-nest="true"
:item="child"
:key="child.path"
:base-path="resolvePath(child.path)"
class="nest-menu" />
<app-link v-else :to="resolvePath(child.path)" :key="child.name">
<el-menu-item :index="resolvePath(child.path)">
<item v-if="child.meta" :icon="child.meta.icon" :title="generateTitle(child.meta.title)" />
</el-menu-item>
</app-link>
</template>
</el-submenu>
</div> </div>
</template> </template>
<script> <script>
import path from 'path'
import { generateTitle } from '@/utils/i18n'
import { isExternal } from '@/utils'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'
export default { export default {
name: 'SidebarItem', name: 'SidebarItem',
components: { Item, AppLink },
mixins: [FixiOSBug],
props: { props: {
routes: { // route object
type: Array item: {
type: Object,
required: true
}, },
isNest: { isNest: {
type: Boolean, type: Boolean,
default: false default: false
},
basePath: {
type: String,
default: ''
}
},
data() {
return {
onlyOneChild: null
} }
},
methods: {
hasOneShowingChild(children, parent) {
const showingChildren = children.filter(item => {
if (item.hidden) {
return false
} else {
// Temp set(will be used if only has one showing child)
this.onlyOneChild = item
return true
}
})
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) {
return true
}
// Show parent if there are no child router to display
if (showingChildren.length === 0) {
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
return true
}
return false
},
resolvePath(routePath) {
if (this.isExternalLink(routePath)) {
return routePath
}
return path.resolve(this.basePath, routePath)
},
isExternalLink(routePath) {
return isExternal(routePath)
},
generateTitle
} }
} }
</script> </script>
<template> <template>
<scroll-bar> <el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu mode="vertical" :default-active="$route.path" :collapse="isCollapse" background-color="#304156" text-color="#bfcbd9" active-text-color="#409EFF"> <el-menu
<sidebar-item :routes="permission_routers"></sidebar-item> :show-timeout="200"
:default-active="$route.path"
:collapse="isCollapse"
mode="vertical"
background-color="#304156"
text-color="#bfcbd9"
active-text-color="#409EFF"
>
<sidebar-item v-for="route in permission_routers" :key="route.path" :item="route" :base-path="route.path"/>
</el-menu> </el-menu>
</scroll-bar> </el-scrollbar>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
import ScrollBar from '@/components/ScrollBar'
export default { export default {
components: { SidebarItem, ScrollBar }, components: { SidebarItem },
computed: { computed: {
...mapGetters([ ...mapGetters([
'permission_routers', 'permission_routers',
......
<template> <template>
<div class="tags-view-container"> <div class="tags-view-container">
<scroll-pane class='tags-view-wrapper' ref='scrollPane'> <scroll-pane ref="scrollPane" class="tags-view-wrapper">
<router-link ref='tag' class="tags-view-item" :class="isActive(tag)?'active':''" v-for="tag in Array.from(visitedViews)" <router-link
:to="tag.path" :key="tag.path" @contextmenu.prevent.native="openMenu(tag,$event)"> v-for="tag in visitedViews"
{{tag.title}} ref="tag"
<span class='el-icon-close' @click.prevent.stop='closeSelectedTag(tag)'></span> :class="isActive(tag)?'active':''"
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
:key="tag.path"
tag="span"
class="tags-view-item"
@click.middle.native="closeSelectedTag(tag)"
@contextmenu.prevent.native="openMenu(tag,$event)">
{{ generateTitle(tag.title) }}
<span class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
</router-link> </router-link>
</scroll-pane> </scroll-pane>
<ul class='contextmenu' v-show="visible" :style="{left:left+'px',top:top+'px'}"> <ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
<li @click="closeSelectedTag(selectedTag)">关闭</li> <li @click="refreshSelectedTag(selectedTag)">{{ $t('tagsView.refresh') }}</li>
<li @click="closeOthersTags">关闭其它</li> <li @click="closeSelectedTag(selectedTag)">{{ $t('tagsView.close') }}</li>
<li @click="closeAllTags">关闭所有</li> <li @click="closeOthersTags">{{ $t('tagsView.closeOthers') }}</li>
<li @click="closeAllTags">{{ $t('tagsView.closeAll') }}</li>
</ul> </ul>
</div> </div>
</template> </template>
<script> <script>
import ScrollPane from '@/components/ScrollPane' import ScrollPane from '@/components/ScrollPane'
import { generateTitle } from '@/utils/i18n'
export default { export default {
components: { ScrollPane }, components: { ScrollPane },
...@@ -50,39 +60,50 @@ export default { ...@@ -50,39 +60,50 @@ export default {
this.addViewTags() this.addViewTags()
}, },
methods: { methods: {
generateRoute() { generateTitle, // generateTitle by vue-i18n
if (this.$route.name) {
return this.$route
}
return false
},
isActive(route) { isActive(route) {
return route.path === this.$route.path || route.name === this.$route.name return route.path === this.$route.path
}, },
addViewTags() { addViewTags() {
const route = this.generateRoute() const { name } = this.$route
if (!route) { if (name) {
return false this.$store.dispatch('addView', this.$route)
} }
this.$store.dispatch('addVisitedViews', route) return false
}, },
moveToCurrentTag() { moveToCurrentTag() {
const tags = this.$refs.tag const tags = this.$refs.tag
this.$nextTick(() => { this.$nextTick(() => {
for (const tag of tags) { for (const tag of tags) {
if (tag.to === this.$route.path) { if (tag.to.path === this.$route.path) {
this.$refs.scrollPane.moveToTarget(tag.$el) this.$refs.scrollPane.moveToTarget(tag)
// when query is different then update
if (tag.to.fullPath !== this.$route.fullPath) {
this.$store.dispatch('updateVisitedView', this.$route)
}
break break
} }
} }
}) })
}, },
refreshSelectedTag(view) {
this.$store.dispatch('delCachedView', view).then(() => {
const { fullPath } = view
this.$nextTick(() => {
this.$router.replace({
path: '/redirect' + fullPath
})
})
})
},
closeSelectedTag(view) { closeSelectedTag(view) {
this.$store.dispatch('delVisitedViews', view).then((views) => { this.$store.dispatch('delView', view).then(({ visitedViews }) => {
if (this.isActive(view)) { if (this.isActive(view)) {
const latestView = views.slice(-1)[0] const latestView = visitedViews.slice(-1)[0]
if (latestView) { if (latestView) {
this.$router.push(latestView.path) this.$router.push(latestView)
} else { } else {
this.$router.push('/') this.$router.push('/')
} }
...@@ -90,7 +111,7 @@ export default { ...@@ -90,7 +111,7 @@ export default {
}) })
}, },
closeOthersTags() { closeOthersTags() {
this.$router.push(this.selectedTag.path) this.$router.push(this.selectedTag)
this.$store.dispatch('delOthersViews', this.selectedTag).then(() => { this.$store.dispatch('delOthersViews', this.selectedTag).then(() => {
this.moveToCurrentTag() this.moveToCurrentTag()
}) })
...@@ -100,10 +121,21 @@ export default { ...@@ -100,10 +121,21 @@ export default {
this.$router.push('/') this.$router.push('/')
}, },
openMenu(tag, e) { openMenu(tag, e) {
const menuMinWidth = 105
const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
const offsetWidth = this.$el.offsetWidth // container width
const maxLeft = offsetWidth - menuMinWidth // left boundary
const left = e.clientX - offsetLeft + 15 // 15: margin right
if (left > maxLeft) {
this.left = maxLeft
} else {
this.left = left
}
this.top = e.clientY
this.visible = true this.visible = true
this.selectedTag = tag this.selectedTag = tag
this.left = e.clientX
this.top = e.clientY
}, },
closeMenu() { closeMenu() {
this.visible = false this.visible = false
...@@ -114,14 +146,16 @@ export default { ...@@ -114,14 +146,16 @@ export default {
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.tags-view-container { .tags-view-container {
height: 34px;
width: 100%;
background: #fff;
border-bottom: 1px solid #d8dce5;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
.tags-view-wrapper { .tags-view-wrapper {
background: #fff;
height: 34px;
border-bottom: 1px solid #d8dce5;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
.tags-view-item { .tags-view-item {
display: inline-block; display: inline-block;
position: relative; position: relative;
cursor: pointer;
height: 26px; height: 26px;
line-height: 26px; line-height: 26px;
border: 1px solid #d8dce5; border: 1px solid #d8dce5;
...@@ -134,6 +168,9 @@ export default { ...@@ -134,6 +168,9 @@ export default {
&:first-of-type { &:first-of-type {
margin-left: 15px; margin-left: 15px;
} }
&:last-of-type {
margin-right: 15px;
}
&.active { &.active {
background-color: #42b983; background-color: #42b983;
color: #fff; color: #fff;
...@@ -154,7 +191,7 @@ export default { ...@@ -154,7 +191,7 @@ export default {
.contextmenu { .contextmenu {
margin: 0; margin: 0;
background: #fff; background: #fff;
z-index: 2; z-index: 100;
position: absolute; position: absolute;
list-style-type: none; list-style-type: none;
padding: 5px 0; padding: 5px 0;
......
import store from '@/store'
const { body } = document
const WIDTH = 1024
const RATIO = 3
export default {
watch: {
$route(route) {
if (this.device === 'mobile' && this.sidebar.opened) {
store.dispatch('closeSideBar', { withoutAnimation: false })
}
}
},
beforeMount() {
window.addEventListener('resize', this.resizeHandler)
},
mounted() {
const isMobile = this.isMobile()
if (isMobile) {
store.dispatch('toggleDevice', 'mobile')
store.dispatch('closeSideBar', { withoutAnimation: true })
}
},
methods: {
isMobile() {
const rect = body.getBoundingClientRect()
return rect.width - RATIO < WIDTH
},
resizeHandler() {
if (!document.hidden) {
const isMobile = this.isMobile()
store.dispatch('toggleDevice', isMobile ? 'mobile' : 'desktop')
if (isMobile) {
store.dispatch('closeSideBar', { withoutAnimation: true })
}
}
}
}
}
<script>
export default {
name: 'AuthRedirect',
created() {
const hash = window.location.search.slice(1)
window.opener.location.href = window.location.origin + '/login#' + hash
window.close()
}
}
</script>
<template> <template>
<div class="login-container"> <div class="login-container">
<el-form class="login-form" autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left"> <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
<div class="title-container"> <div class="title-container">
<h3 class="title">管理员登录</h3> <h3 class="title">管理员登录</h3>
</div> </div>
...@@ -8,20 +8,20 @@ ...@@ -8,20 +8,20 @@
<span class="svg-container svg-container_login"> <span class="svg-container svg-container_login">
<svg-icon icon-class="user" /> <svg-icon icon-class="user" />
</span> </span>
<el-input name="username" type="text" v-model="loginForm.username" autoComplete="on" placeholder="username" /> <el-input v-model="loginForm.username" name="username" type="text" auto-complete="on" placeholder="username" />
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<span class="svg-container"> <span class="svg-container">
<svg-icon icon-class="password" /> <svg-icon icon-class="password" />
</span> </span>
<el-input name="password" :type="passwordType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autoComplete="on" placeholder="password" /> <el-input :type="passwordType" v-model="loginForm.password" name="password" auto-complete="on" placeholder="password" @keyup.enter.native="handleLogin" />
<span class="show-pwd" @click="showPwd"> <span class="show-pwd" @click="showPwd">
<svg-icon icon-class="eye" /> <svg-icon icon-class="eye" />
</span> </span>
</el-form-item> </el-form-item>
<el-button type="primary" style="width:100%;margin-bottom:30px;" :loading="loading" @click.native.prevent="handleLogin">登录</el-button> <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登录</el-button>
</el-form> </el-form>
</div> </div>
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
<script> <script>
export default { export default {
name: 'login', name: 'Login',
data() { data() {
const validateUsername = (rule, value, callback) => { const validateUsername = (rule, value, callback) => {
if (validateUsername == null) { if (validateUsername == null) {
...@@ -47,8 +47,8 @@ export default { ...@@ -47,8 +47,8 @@ export default {
} }
return { return {
loginForm: { loginForm: {
username: '', username: 'admin123',
password: '' password: 'admin123'
}, },
loginRules: { loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }], username: [{ required: true, trigger: 'blur', validator: validateUsername }],
...@@ -58,6 +58,21 @@ export default { ...@@ -58,6 +58,21 @@ export default {
loading: false loading: false
} }
}, },
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true
}
},
created() {
// window.addEventListener('hashchange', this.afterQRScan)
},
destroyed() {
// window.removeEventListener('hashchange', this.afterQRScan)
},
methods: { methods: {
showPwd() { showPwd() {
if (this.passwordType === 'password') { if (this.passwordType === 'password') {
...@@ -72,7 +87,7 @@ export default { ...@@ -72,7 +87,7 @@ export default {
this.loading = true this.loading = true
this.$store.dispatch('LoginByUsername', this.loginForm).then(() => { this.$store.dispatch('LoginByUsername', this.loginForm).then(() => {
this.loading = false this.loading = false
this.$router.push({ path: '/' }) this.$router.push({ path: this.redirect || '/' })
}).catch(response => { }).catch(response => {
this.$notify.error({ this.$notify.error({
title: '失败', title: '失败',
......
<template> <template>
<div class="app-container calendar-list-container"> <div class="app-container">
<!-- 查询和其他操作 --> <!-- 查询和其他操作 -->
<div class="filter-container"> <div class="filter-container">
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入品牌商ID" v-model="listQuery.id"> <el-input v-model="listQuery.id" clearable class="filter-item" style="width: 200px;" placeholder="请输入品牌商ID"/>
</el-input> <el-input v-model="listQuery.name" clearable class="filter-item" style="width: 200px;" placeholder="请输入品牌商名称"/>
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入品牌商名称" v-model="listQuery.name">
</el-input>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button> <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">添加</el-button> <el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">添加</el-button>
<el-button class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload" :loading="downloadLoading">导出</el-button> <el-button :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">导出</el-button>
</div> </div>
<!-- 查询结果 --> <!-- 查询结果 -->
<el-table size="small" :data="list" v-loading="listLoading" element-loading-text="正在查询中。。。" border fit highlight-current-row> <el-table v-loading="listLoading" :data="list" size="small" element-loading-text="正在查询中。。。" border fit highlight-current-row>
<el-table-column align="center" label="品牌商ID" prop="id"> <el-table-column align="center" label="品牌商ID" prop="id"/>
</el-table-column>
<el-table-column align="center" label="品牌商名称" prop="name"> <el-table-column align="center" label="品牌商名称" prop="name"/>
</el-table-column>
<el-table-column align="center" property="picUrl" label="品牌商图片"> <el-table-column align="center" property="picUrl" label="品牌商图片">
<template slot-scope="scope"> <template slot-scope="scope">
<img :src="scope.row.picUrl" width="80" v-if="scope.row.picUrl"/> <img v-if="scope.row.picUrl" :src="scope.row.picUrl" width="80">
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" min-width="400px" label="介绍" prop="desc"> <el-table-column align="center" min-width="400px" label="介绍" prop="desc"/>
</el-table-column>
<el-table-column align="center" label="底价" prop="floorPrice"> <el-table-column align="center" label="底价" prop="floorPrice"/>
</el-table-column>
<el-table-column align="center" label="操作" width="200" class-name="small-padding fixed-width"> <el-table-column align="center" label="操作" width="200" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button> <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button> <el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页 --> <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
<div class="pagination-container">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page"
:page-sizes="[10,20,30,50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<!-- 添加或修改对话框 --> <!-- 添加或修改对话框 -->
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form :rules="rules" ref="dataForm" :model="dataForm" status-icon label-position="left" label-width="100px" style='width: 400px; margin-left:50px;'> <el-form ref="dataForm" :rules="rules" :model="dataForm" status-icon label-position="left" label-width="100px" style="width: 400px; margin-left:50px;">
<el-form-item label="品牌商名称" prop="name"> <el-form-item label="品牌商名称" prop="name">
<el-input v-model="dataForm.name"></el-input> <el-input v-model="dataForm.name"/>
</el-form-item> </el-form-item>
<el-form-item label="介绍" prop="simpleDesc"> <el-form-item label="介绍" prop="simpleDesc">
<el-input v-model="dataForm.desc"></el-input> <el-input v-model="dataForm.desc"/>
</el-form-item> </el-form-item>
<el-form-item label="品牌商图片" prop="picUrl"> <el-form-item label="品牌商图片" prop="picUrl">
<el-upload class="avatar-uploader" :headers="headers" :action='uploadPath' list-type="picture-card" :show-file-list="false" accept=".jpg,.jpeg,.png,.gif" :on-success="uploadPicUrl"> <el-upload :headers="headers" :action="uploadPath" :show-file-list="false" :on-success="uploadPicUrl" class="avatar-uploader" list-type="picture-card" accept=".jpg,.jpeg,.png,.gif">
<img v-if="dataForm.picUrl" :src="dataForm.picUrl" class="avatar"> <img v-if="dataForm.picUrl" :src="dataForm.picUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i> <i v-else class="el-icon-plus avatar-uploader-icon"/>
</el-upload> </el-upload>
</el-form-item> </el-form-item>
<el-form-item label="底价" prop="floorPrice"> <el-form-item label="底价" prop="floorPrice">
<el-input v-model="dataForm.floorPrice"></el-input> <el-input v-model="dataForm.floorPrice"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
...@@ -78,45 +67,40 @@ ...@@ -78,45 +67,40 @@
</template> </template>
<style> <style>
.avatar-uploader .el-upload { .avatar-uploader .el-upload {
border: 1px dashed #d9d9d9; border: 1px dashed #d9d9d9;
border-radius: 6px; border-radius: 6px;
cursor: pointer; cursor: pointer;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
} }
.avatar-uploader .el-upload:hover { .avatar-uploader .el-upload:hover {
border-color: #20a0ff; border-color: #20a0ff;
} }
.avatar-uploader-icon { .avatar-uploader-icon {
font-size: 28px; font-size: 28px;
color: #8c939d; color: #8c939d;
width: 120px; width: 120px;
height: 120px; height: 120px;
line-height: 120px; line-height: 120px;
text-align: center; text-align: center;
} }
.avatar { .avatar {
width: 120px; width: 120px;
height: 120px; height: 120px;
display: block; display: block;
} }
</style> </style>
<script> <script>
import { listBrand, createBrand, updateBrand, deleteBrand } from '@/api/brand' import { listBrand, createBrand, updateBrand, deleteBrand } from '@/api/brand'
import { uploadPath } from '@/api/storage' import { uploadPath } from '@/api/storage'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
export default { export default {
name: 'Brand', name: 'Brand',
computed: { components: { Pagination },
headers() {
return {
'Admin-Token': getToken()
}
}
},
data() { data() {
return { return {
uploadPath, uploadPath,
...@@ -145,39 +129,42 @@ export default { ...@@ -145,39 +129,42 @@ export default {
create: '创建' create: '创建'
}, },
rules: { rules: {
name: [{ required: true, message: '品牌商名称不能为空', trigger: 'blur' }] name: [
{ required: true, message: '品牌商名称不能为空', trigger: 'blur' }
]
}, },
downloadLoading: false downloadLoading: false
} }
}, },
computed: {
headers() {
return {
'Admin-Token': getToken()
}
}
},
created() { created() {
this.getList() this.getList()
}, },
methods: { methods: {
getList() { getList() {
this.listLoading = true this.listLoading = true
listBrand(this.listQuery).then(response => { listBrand(this.listQuery)
this.list = response.data.data.items .then(response => {
this.total = response.data.data.total this.list = response.data.data.items
this.listLoading = false this.total = response.data.data.total
}).catch(() => { this.listLoading = false
this.list = [] })
this.total = 0 .catch(() => {
this.listLoading = false this.list = []
}) this.total = 0
this.listLoading = false
})
}, },
handleFilter() { handleFilter() {
this.listQuery.page = 1 this.listQuery.page = 1
this.getList() this.getList()
}, },
handleSizeChange(val) {
this.listQuery.limit = val
this.getList()
},
handleCurrentChange(val) {
this.listQuery.page = val
this.getList()
},
resetForm() { resetForm() {
this.dataForm = { this.dataForm = {
id: undefined, id: undefined,
...@@ -199,21 +186,23 @@ export default { ...@@ -199,21 +186,23 @@ export default {
this.dataForm.picUrl = response.data.url this.dataForm.picUrl = response.data.url
}, },
createData() { createData() {
this.$refs['dataForm'].validate((valid) => { this.$refs['dataForm'].validate(valid => {
if (valid) { if (valid) {
createBrand(this.dataForm).then(response => { createBrand(this.dataForm)
this.list.unshift(response.data.data) .then(response => {
this.dialogFormVisible = false this.list.unshift(response.data.data)
this.$notify.success({ this.dialogFormVisible = false
title: '成功', this.$notify.success({
message: '创建成功' title: '成功',
message: '创建成功'
})
}) })
}).catch(response => { .catch(response => {
this.$notify.error({ this.$notify.error({
title: '失败', title: '失败',
message: response.data.errmsg message: response.data.errmsg
})
}) })
})
} }
}) })
}, },
...@@ -226,51 +215,66 @@ export default { ...@@ -226,51 +215,66 @@ export default {
}) })
}, },
updateData() { updateData() {
this.$refs['dataForm'].validate((valid) => { this.$refs['dataForm'].validate(valid => {
if (valid) { if (valid) {
updateBrand(this.dataForm).then(() => { updateBrand(this.dataForm)
for (const v of this.list) { .then(() => {
if (v.id === this.dataForm.id) { for (const v of this.list) {
const index = this.list.indexOf(v) if (v.id === this.dataForm.id) {
this.list.splice(index, 1, this.dataForm) const index = this.list.indexOf(v)
break this.list.splice(index, 1, this.dataForm)
break
}
} }
} this.dialogFormVisible = false
this.dialogFormVisible = false this.$notify.success({
this.$notify.success({ title: '成功',
title: '成功', message: '更新成功'
message: '更新成功' })
}) })
}).catch(response => { .catch(response => {
this.$notify.error({ this.$notify.error({
title: '失败', title: '失败',
message: response.data.errmsg message: response.data.errmsg
})
}) })
})
} }
}) })
}, },
handleDelete(row) { handleDelete(row) {
deleteBrand(row).then(response => { deleteBrand(row)
this.$notify.success({ .then(response => {
title: '成功', this.$notify.success({
message: '删除成功' title: '成功',
message: '删除成功'
})
const index = this.list.indexOf(row)
this.list.splice(index, 1)
}) })
const index = this.list.indexOf(row) .catch(response => {
this.list.splice(index, 1) this.$notify.error({
}).catch(response => { title: '失败',
this.$notify.error({ message: response.data.errmsg
title: '失败', })
message: response.data.errmsg
}) })
})
}, },
handleDownload() { handleDownload() {
this.downloadLoading = true this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => { import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['品牌商ID', '品牌商名称', '介绍', '低价', '品牌商图片'] const tHeader = [
'品牌商ID',
'品牌商名称',
'介绍',
'低价',
'品牌商图片'
]
const filterVal = ['id', 'name', 'desc', 'floorPrice', 'picUrl'] const filterVal = ['id', 'name', 'desc', 'floorPrice', 'picUrl']
excel.export_json_to_excel2(tHeader, this.list, filterVal, '品牌商信息') excel.export_json_to_excel2(
tHeader,
this.list,
filterVal,
'品牌商信息'
)
this.downloadLoading = false this.downloadLoading = false
}) })
} }
......
<template> <template>
<div class="app-container calendar-list-container"> <div class="app-container">
<!-- 查询和其他操作 --> <!-- 查询和其他操作 -->
<div class="filter-container"> <div class="filter-container">
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入类目ID" v-model="listQuery.id"> <el-input v-model="listQuery.id" clearable class="filter-item" style="width: 200px;" placeholder="请输入类目ID"/>
</el-input> <el-input v-model="listQuery.name" clearable class="filter-item" style="width: 200px;" placeholder="请输入类目名称"/>
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入类目名称" v-model="listQuery.name">
</el-input>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button> <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-button class="filter-item" type="primary" @click="handleCreate" icon="el-icon-edit">添加</el-button> <el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">添加</el-button>
<el-button class="filter-item" type="primary" :loading="downloadLoading" icon="el-icon-download" @click="handleDownload">导出</el-button> <el-button :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">导出</el-button>
</div> </div>
<!-- 查询结果 --> <!-- 查询结果 -->
<el-table size="small" :data="list" v-loading="listLoading" element-loading-text="正在查询中。。。" border fit highlight-current-row> <el-table v-loading="listLoading" :data="list" size="small" element-loading-text="正在查询中。。。" border fit highlight-current-row>
<el-table-column align="center" label="类目ID" prop="id"> <el-table-column align="center" label="类目ID" prop="id"/>
</el-table-column>
<el-table-column align="center" label="类目名" prop="name"> <el-table-column align="center" label="类目名" prop="name"/>
</el-table-column>
<el-table-column align="center" property="iconUrl" label="类目图标"> <el-table-column align="center" property="iconUrl" label="类目图标">
<template slot-scope="scope"> <template slot-scope="scope">
<img :src="scope.row.iconUrl" width="40" v-if="scope.row.iconUrl"/> <img v-if="scope.row.iconUrl" :src="scope.row.iconUrl" width="40">
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" property="picUrl" label="类目图片"> <el-table-column align="center" property="picUrl" label="类目图片">
<template slot-scope="scope"> <template slot-scope="scope">
<img :src="scope.row.picUrl" width="80" v-if="scope.row.picUrl"/> <img v-if="scope.row.picUrl" :src="scope.row.picUrl" width="80">
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="关键字" prop="keywords"> <el-table-column align="center" label="关键字" prop="keywords"/>
</el-table-column>
<el-table-column align="center" min-width="100" label="简介" prop="desc"> <el-table-column align="center" min-width="100" label="简介" prop="desc"/>
</el-table-column>
<el-table-column align="center" label="级别" prop="level" <el-table-column
:filters="[{ text: '一级类目', value: 'L1' }, { text: '二级类目', value: 'L2' }]" :filter-method="filterLevel"> :filters="[{ text: '一级类目', value: 'L1' }, { text: '二级类目', value: 'L2' }]"
:filter-method="filterLevel"
align="center"
label="级别"
prop="level">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.level === 'L1' ? 'primary' : 'info' ">{{scope.row.level === 'L1' ? '一级类目' : '二级类目'}}</el-tag> <el-tag :type="scope.row.level === 'L1' ? 'primary' : 'info' ">{{ scope.row.level === 'L1' ? '一级类目' : '二级类目' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="父类目ID" prop="pid"> <el-table-column align="center" label="父类目ID" prop="pid"/>
</el-table-column>
<el-table-column align="center" label="操作" width="200" class-name="small-padding fixed-width"> <el-table-column align="center" label="操作" width="200" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button> <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button> <el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页 --> <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
<div class="pagination-container">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page"
:page-sizes="[10,20,30,50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<!-- 添加或修改对话框 --> <!-- 添加或修改对话框 -->
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form :rules="rules" ref="dataForm" :model="dataForm" status-icon label-position="left" label-width="100px" style='width: 400px; margin-left:50px;'> <el-form ref="dataForm" :rules="rules" :model="dataForm" status-icon label-position="left" label-width="100px" style="width: 400px; margin-left:50px;">
<el-form-item label="类目名称" prop="name"> <el-form-item label="类目名称" prop="name">
<el-input v-model="dataForm.name"></el-input> <el-input v-model="dataForm.name"/>
</el-form-item> </el-form-item>
<el-form-item label="关键字" prop="keywords"> <el-form-item label="关键字" prop="keywords">
<el-input v-model="dataForm.keywords"></el-input> <el-input v-model="dataForm.keywords"/>
</el-form-item> </el-form-item>
<el-form-item label="级别" prop="level"> <el-form-item label="级别" prop="level">
<el-select v-model="dataForm.level" @change="onLevelChange"> <el-select v-model="dataForm.level" @change="onLevelChange">
<el-option label="一级类目" value="L1"> <el-option label="一级类目" value="L1"/>
</el-option> <el-option label="二级类目" value="L2"/>
<el-option label="二级类目" value="L2">
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="父类目" prop="pid" v-if="dataForm.level === 'L2'"> <el-form-item v-if="dataForm.level === 'L2'" label="父类目" prop="pid">
<el-select v-model="dataForm.pid"> <el-select v-model="dataForm.pid">
<el-option v-for="item in catL1" :key="item.value" :label="item.label" :value="item.value"> <el-option v-for="item in catL1" :key="item.value" :label="item.label" :value="item.value"/>
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="类目图标" prop="iconUrl"> <el-form-item label="类目图标" prop="iconUrl">
<el-upload class="avatar-uploader" :headers="headers" :action='uploadPath' list-type="picture-card" :show-file-list="false" accept=".jpg,.jpeg,.png,.gif" :on-success="uploadIconUrl"> <el-upload :headers="headers" :action="uploadPath" :show-file-list="false" :on-success="uploadIconUrl" class="avatar-uploader" list-type="picture-card" accept=".jpg,.jpeg,.png,.gif">
<img v-if="dataForm.iconUrl" :src="dataForm.iconUrl" class="avatar"> <img v-if="dataForm.iconUrl" :src="dataForm.iconUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i> <i v-else class="el-icon-plus avatar-uploader-icon"/>
</el-upload> </el-upload>
</el-form-item> </el-form-item>
<el-form-item label="类目图片" prop="picUrl"> <el-form-item label="类目图片" prop="picUrl">
<el-upload class="avatar-uploader" :headers="headers" :action='uploadPath' list-type="picture-card" :show-file-list="false" accept=".jpg,.jpeg,.png,.gif" :on-success="uploadPicUrl"> <el-upload :headers="headers" :action="uploadPath" :show-file-list="false" :on-success="uploadPicUrl" class="avatar-uploader" list-type="picture-card" accept=".jpg,.jpeg,.png,.gif">
<img v-if="dataForm.picUrl" :src="dataForm.picUrl" class="avatar"> <img v-if="dataForm.picUrl" :src="dataForm.picUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i> <i v-else class="el-icon-plus avatar-uploader-icon"/>
</el-upload> </el-upload>
</el-form-item> </el-form-item>
<el-form-item label="类目简介" prop="desc"> <el-form-item label="类目简介" prop="desc">
<el-input v-model="dataForm.desc"></el-input> <el-input v-model="dataForm.desc"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
...@@ -114,45 +103,40 @@ ...@@ -114,45 +103,40 @@
</template> </template>
<style> <style>
.avatar-uploader .el-upload { .avatar-uploader .el-upload {
border: 1px dashed #d9d9d9; border: 1px dashed #d9d9d9;
border-radius: 6px; border-radius: 6px;
cursor: pointer; cursor: pointer;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
} }
.avatar-uploader .el-upload:hover { .avatar-uploader .el-upload:hover {
border-color: #20a0ff; border-color: #20a0ff;
} }
.avatar-uploader-icon { .avatar-uploader-icon {
font-size: 28px; font-size: 28px;
color: #8c939d; color: #8c939d;
width: 120px; width: 120px;
height: 120px; height: 120px;
line-height: 120px; line-height: 120px;
text-align: center; text-align: center;
} }
.avatar { .avatar {
width: 120px; width: 120px;
height: 120px; height: 120px;
display: block; display: block;
} }
</style> </style>
<script> <script>
import { listCategory, listCatL1, createCategory, updateCategory, deleteCategory } from '@/api/category' import { listCategory, listCatL1, createCategory, updateCategory, deleteCategory } from '@/api/category'
import { uploadPath } from '@/api/storage' import { uploadPath } from '@/api/storage'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
export default { export default {
name: 'Category', name: 'Category',
computed: { components: { Pagination },
headers() {
return {
'Admin-Token': getToken()
}
}
},
data() { data() {
return { return {
uploadPath, uploadPath,
...@@ -190,6 +174,13 @@ export default { ...@@ -190,6 +174,13 @@ export default {
downloadLoading: false downloadLoading: false
} }
}, },
computed: {
headers() {
return {
'Admin-Token': getToken()
}
}
},
created() { created() {
this.getList() this.getList()
this.getCatL1() this.getCatL1()
...@@ -197,15 +188,17 @@ export default { ...@@ -197,15 +188,17 @@ export default {
methods: { methods: {
getList() { getList() {
this.listLoading = true this.listLoading = true
listCategory(this.listQuery).then(response => { listCategory(this.listQuery)
this.list = response.data.data.items .then(response => {
this.total = response.data.data.total this.list = response.data.data.items
this.listLoading = false this.total = response.data.data.total
}).catch(() => { this.listLoading = false
this.list = [] })
this.total = 0 .catch(() => {
this.listLoading = false this.list = []
}) this.total = 0
this.listLoading = false
})
}, },
getCatL1() { getCatL1() {
listCatL1().then(response => { listCatL1().then(response => {
...@@ -216,14 +209,6 @@ export default { ...@@ -216,14 +209,6 @@ export default {
this.listQuery.page = 1 this.listQuery.page = 1
this.getList() this.getList()
}, },
handleSizeChange(val) {
this.listQuery.limit = val
this.getList()
},
handleCurrentChange(val) {
this.listQuery.page = val
this.getList()
},
resetForm() { resetForm() {
this.dataForm = { this.dataForm = {
id: undefined, id: undefined,
...@@ -259,23 +244,25 @@ export default { ...@@ -259,23 +244,25 @@ export default {
this.dataForm.picUrl = response.data.url this.dataForm.picUrl = response.data.url
}, },
createData() { createData() {
this.$refs['dataForm'].validate((valid) => { this.$refs['dataForm'].validate(valid => {
if (valid) { if (valid) {
createCategory(this.dataForm).then(response => { createCategory(this.dataForm)
this.list.unshift(response.data.data) .then(response => {
// 更新L1目录 this.list.unshift(response.data.data)
this.getCatL1() // 更新L1目录
this.dialogFormVisible = false this.getCatL1()
this.$notify.success({ this.dialogFormVisible = false
title: '成功', this.$notify.success({
message: '创建成功' title: '成功',
message: '创建成功'
})
}) })
}).catch(response => { .catch(response => {
this.$notify.error({ this.$notify.error({
title: '失败', title: '失败',
message: response.data.errmsg message: response.data.errmsg
})
}) })
})
} }
}) })
}, },
...@@ -288,55 +275,82 @@ export default { ...@@ -288,55 +275,82 @@ export default {
}) })
}, },
updateData() { updateData() {
this.$refs['dataForm'].validate((valid) => { this.$refs['dataForm'].validate(valid => {
if (valid) { if (valid) {
updateCategory(this.dataForm).then(() => { updateCategory(this.dataForm)
for (const v of this.list) { .then(() => {
if (v.id === this.dataForm.id) { for (const v of this.list) {
const index = this.list.indexOf(v) if (v.id === this.dataForm.id) {
this.list.splice(index, 1, this.dataForm) const index = this.list.indexOf(v)
break this.list.splice(index, 1, this.dataForm)
break
}
} }
} // 更新L1目录
// 更新L1目录 this.getCatL1()
this.getCatL1() this.dialogFormVisible = false
this.dialogFormVisible = false this.$notify.success({
this.$notify.success({ title: '成功',
title: '成功', message: '更新成功'
message: '更新成功' })
}) })
}).catch(response => { .catch(response => {
this.$notify.error({ this.$notify.error({
title: '失败', title: '失败',
message: response.data.errmsg message: response.data.errmsg
})
}) })
})
} }
}) })
}, },
handleDelete(row) { handleDelete(row) {
deleteCategory(row).then(response => { deleteCategory(row)
// 更新L1目录 .then(response => {
this.getCatL1() // 更新L1目录
this.$notify.success({ this.getCatL1()
title: '成功', this.$notify.success({
message: '删除成功' title: '成功',
message: '删除成功'
})
const index = this.list.indexOf(row)
this.list.splice(index, 1)
}) })
const index = this.list.indexOf(row) .catch(response => {
this.list.splice(index, 1) this.$notify.error({
}).catch(response => { title: '失败',
this.$notify.error({ message: response.data.errmsg
title: '失败', })
message: response.data.errmsg
}) })
})
}, },
handleDownload() { handleDownload() {
this.downloadLoading = true this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => { import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['类目ID', '名称', '关键字', '级别', '父类目ID', '类目图标', '类目图片', '简介'] const tHeader = [
const filterVal = ['id', 'name', 'keywords', 'level', 'pid', 'iconUrl', 'picUrl', 'desc'] '类目ID',
excel.export_json_to_excel2(tHeader, this.list, filterVal, '商品类目信息') '名称',
'关键字',
'级别',
'父类目ID',
'类目图标',
'类目图片',
'简介'
]
const filterVal = [
'id',
'name',
'keywords',
'level',
'pid',
'iconUrl',
'picUrl',
'desc'
]
excel.export_json_to_excel2(
tHeader,
this.list,
filterVal,
'商品类目信息'
)
this.downloadLoading = false this.downloadLoading = false
}) })
} }
......
<template> <template>
<div class="app-container calendar-list-container"> <div class="app-container">
<!-- 查询和其他操作 --> <!-- 查询和其他操作 -->
<div class="filter-container"> <div class="filter-container">
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入问题" v-model="listQuery.question"> <el-input v-model="listQuery.question" clearable class="filter-item" style="width: 200px;" placeholder="请输入问题"/>
</el-input>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button> <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-button class="filter-item" type="primary" @click="handleCreate" icon="el-icon-edit">添加</el-button> <el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">添加</el-button>
<el-button class="filter-item" type="primary" :loading="downloadLoading" icon="el-icon-download" @click="handleDownload">导出</el-button> <el-button :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">导出</el-button>
</div> </div>
<!-- 查询结果 --> <!-- 查询结果 -->
<el-table size="small" :data="list" v-loading="listLoading" element-loading-text="正在查询中。。。" border fit highlight-current-row> <el-table v-loading="listLoading" :data="list" size="small" element-loading-text="正在查询中。。。" border fit highlight-current-row>
<el-table-column align="center" width="100px" label="问题ID" prop="id" sortable> <el-table-column align="center" width="100px" label="问题ID" prop="id" sortable/>
</el-table-column>
<el-table-column align="center" min-width="200px" label="问题内容" prop="question"> <el-table-column align="center" min-width="200px" label="问题内容" prop="question"/>
</el-table-column>
<el-table-column align="center" min-width="400px" label="问题回复" prop="answer"> <el-table-column align="center" min-width="400px" label="问题回复" prop="answer"/>
</el-table-column>
<el-table-column align="center" label="操作" width="250" class-name="small-padding fixed-width"> <el-table-column align="center" label="操作" width="250" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button> <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button> <el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页 --> <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
<div class="pagination-container">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page"
:page-sizes="[10,20,30,50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<!-- 添加或修改对话框 --> <!-- 添加或修改对话框 -->
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form :rules="rules" ref="dataForm" :model="dataForm" status-icon label-position="left" label-width="100px" style='width: 400px; margin-left:50px;'> <el-form ref="dataForm" :rules="rules" :model="dataForm" status-icon label-position="left" label-width="100px" style="width: 400px; margin-left:50px;">
<el-form-item label="问题" prop="question"> <el-form-item label="问题" prop="question">
<el-input v-model="dataForm.question"></el-input> <el-input v-model="dataForm.question"/>
</el-form-item> </el-form-item>
<el-form-item label="回复" prop="answer"> <el-form-item label="回复" prop="answer">
<el-input v-model="dataForm.answer" type="textarea" :rows="8" placeholder="请输入内容"></el-input> <el-input v-model="dataForm.answer" :rows="8" type="textarea" placeholder="请输入内容"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
...@@ -58,9 +49,11 @@ ...@@ -58,9 +49,11 @@
<script> <script>
import { listIssue, createIssue, updateIssue, deleteIssue } from '@/api/issue' import { listIssue, createIssue, updateIssue, deleteIssue } from '@/api/issue'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
export default { export default {
name: 'Issue', name: 'Issue',
components: { Pagination },
data() { data() {
return { return {
list: null, list: null,
...@@ -111,14 +104,6 @@ export default { ...@@ -111,14 +104,6 @@ export default {
this.listQuery.page = 1 this.listQuery.page = 1
this.getList() this.getList()
}, },
handleSizeChange(val) {
this.listQuery.limit = val
this.getList()
},
handleCurrentChange(val) {
this.listQuery.page = val
this.getList()
},
resetForm() { resetForm() {
this.dataForm = { this.dataForm = {
id: undefined, id: undefined,
......
<template> <template>
<div class="app-container calendar-list-container"> <div class="app-container">
<!-- 查询和其他操作 --> <!-- 查询和其他操作 -->
<div class="filter-container"> <div class="filter-container">
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入关键字" v-model="listQuery.keyword"> <el-input v-model="listQuery.keyword" clearable class="filter-item" style="width: 200px;" placeholder="请输入关键字"/>
</el-input> <el-input v-model="listQuery.url" clearable class="filter-item" style="width: 200px;" placeholder="请输入跳转链接"/>
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入跳转链接" v-model="listQuery.url">
</el-input>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button> <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">添加</el-button> <el-button class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">添加</el-button>
<el-button class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload" :loading="downloadLoading">导出</el-button> <el-button :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">导出</el-button>
</div> </div>
<!-- 查询结果 --> <!-- 查询结果 -->
<el-table size="small" :data="list" v-loading="listLoading" element-loading-text="正在查询中。。。" border fit highlight-current-row> <el-table v-loading="listLoading" :data="list" size="small" element-loading-text="正在查询中。。。" border fit highlight-current-row>
<el-table-column align="center" width="150px" label="关键词ID" prop="id" sortable> <el-table-column align="center" width="150px" label="关键词ID" prop="id" sortable/>
</el-table-column>
<el-table-column align="center" min-width="100px" label="关键词" prop="keyword"> <el-table-column align="center" min-width="100px" label="关键词" prop="keyword"/>
</el-table-column>
<el-table-column align="center" min-width="300px" label="跳转链接" prop="url"> <el-table-column align="center" min-width="300px" label="跳转链接" prop="url"/>
</el-table-column>
<el-table-column align="center" min-width="100px" label="是否推荐" prop="isHot"> <el-table-column align="center" min-width="100px" label="是否推荐" prop="isHot">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.isHot ? 'success' : 'error' ">{{scope.row.isHot ? '' : ''}}</el-tag> <el-tag :type="scope.row.isHot ? 'success' : 'error' ">{{ scope.row.isHot ? '' : '' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" min-width="100px" label="是否默认" prop="isDefault"> <el-table-column align="center" min-width="100px" label="是否默认" prop="isDefault">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.isDefault ? 'success' : 'error' ">{{scope.row.isDefault ? '' : ''}}</el-tag> <el-tag :type="scope.row.isDefault ? 'success' : 'error' ">{{ scope.row.isDefault ? '' : '' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="操作" width="250" class-name="small-padding fixed-width"> <el-table-column align="center" label="操作" width="250" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button> <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button> <el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页 --> <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
<div class="pagination-container">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page"
:page-sizes="[10,20,30,50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<!-- 添加或修改对话框 --> <!-- 添加或修改对话框 -->
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible"> <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form :rules="rules" ref="dataForm" :model="dataForm" status-icon label-position="left" label-width="100px" style='width: 400px; margin-left:50px;'> <el-form ref="dataForm" :rules="rules" :model="dataForm" status-icon label-position="left" label-width="100px" style="width: 400px; margin-left:50px;">
<el-form-item label="关键词" prop="keyword"> <el-form-item label="关键词" prop="keyword">
<el-input v-model="dataForm.keyword"></el-input> <el-input v-model="dataForm.keyword"/>
</el-form-item> </el-form-item>
<el-form-item label="跳转链接" prop="url"> <el-form-item label="跳转链接" prop="url">
<el-input v-model="dataForm.url"></el-input> <el-input v-model="dataForm.url"/>
</el-form-item> </el-form-item>
<el-form-item label="是否推荐" prop="isHot"> <el-form-item label="是否推荐" prop="isHot">
<el-select v-model="dataForm.isHot" placeholder="请选择"> <el-select v-model="dataForm.isHot" placeholder="请选择">
<el-option label="推荐" :value="true"> <el-option :value="true" label="推荐"/>
</el-option> <el-option :value="false" label="普通"/>
<el-option label="普通" :value="false">
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="是否默认" prop="isDefault"> <el-form-item label="是否默认" prop="isDefault">
<el-select v-model="dataForm.isDefault" placeholder="请选择"> <el-select v-model="dataForm.isDefault" placeholder="请选择">
<el-option label="默认" :value="true"> <el-option :value="true" label="默认"/>
</el-option> <el-option :value="false" label="非默认"/>
<el-option label="非默认" :value="false">
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button> <el-button @click="dialogFormVisible = false">取消</el-button>
...@@ -89,9 +75,11 @@ ...@@ -89,9 +75,11 @@
<script> <script>
import { listKeyword, createKeyword, updateKeyword, deleteKeyword } from '@/api/keyword' import { listKeyword, createKeyword, updateKeyword, deleteKeyword } from '@/api/keyword'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
export default { export default {
name: 'Keyword', name: 'Keyword',
components: { Pagination },
data() { data() {
return { return {
list: undefined, list: undefined,
...@@ -144,14 +132,6 @@ export default { ...@@ -144,14 +132,6 @@ export default {
this.listQuery.page = 1 this.listQuery.page = 1
this.getList() this.getList()
}, },
handleSizeChange(val) {
this.listQuery.limit = val
this.getList()
},
handleCurrentChange(val) {
this.listQuery.page = val
this.getList()
},
resetForm() { resetForm() {
this.dataForm = { this.dataForm = {
id: undefined, id: undefined,
...@@ -247,4 +227,4 @@ export default { ...@@ -247,4 +227,4 @@ export default {
} }
} }
} }
</script> </script>
\ No newline at end of file
<template> <template>
<div class="app-container calendar-list-container"> <div class="app-container">
<!-- 查询和其他操作 --> <!-- 查询和其他操作 -->
<div class="filter-container"> <div class="filter-container">
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入用户ID" v-model="listQuery.userId"> <el-input v-model="listQuery.userId" clearable class="filter-item" style="width: 200px;" placeholder="请输入用户ID"/>
</el-input> <el-input v-model="listQuery.orderSn" clearable class="filter-item" style="width: 200px;" placeholder="请输入订单编号"/>
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入订单编号" v-model="listQuery.orderSn"> <el-select v-model="listQuery.orderStatusArray" multiple style="width: 200px" class="filter-item" placeholder="请选择订单状态">
</el-input> <el-option v-for="(key, value) in statusMap" :key="key" :label="key" :value="value"/>
<el-select multiple style="width: 200px" class="filter-item" placeholder="请选择订单状态" v-model="listQuery.orderStatusArray"> </el-select>
<el-option v-for="(key, value) in statusMap" :key="key" :label="key" :value="value">
</el-option>
</el-select>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button> <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-button class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload" :loading="downloadLoading">导出</el-button> <el-button :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">导出</el-button>
</div> </div>
<!-- 查询结果 --> <!-- 查询结果 -->
<el-table size="small" :data="list" v-loading="listLoading" element-loading-text="正在查询中。。。" border fit highlight-current-row> <el-table v-loading="listLoading" :data="list" size="small" element-loading-text="正在查询中。。。" border fit highlight-current-row>
<el-table-column align="center" min-width="100" label="订单编号" prop="orderSn"> <el-table-column align="center" min-width="100" label="订单编号" prop="orderSn"/>
</el-table-column>
<el-table-column align="center" label="用户ID" prop="userId"> <el-table-column align="center" label="用户ID" prop="userId"/>
</el-table-column>
<el-table-column align="center" label="订单状态" prop="orderStatus"> <el-table-column align="center" label="订单状态" prop="orderStatus">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag>{{scope.row.orderStatus | orderStatusFilter}}</el-tag> <el-tag>{{ scope.row.orderStatus | orderStatusFilter }}</el-tag>
</template> </template>
</el-table-column>
<el-table-column align="center" label="订单金额" prop="orderPrice">
</el-table-column> </el-table-column>
<el-table-column align="center" label="支付金额" prop="actualPrice"> <el-table-column align="center" label="订单金额" prop="orderPrice"/>
</el-table-column>
<el-table-column align="center" label="支付时间" prop="payTime"> <el-table-column align="center" label="支付金额" prop="actualPrice"/>
</el-table-column>
<el-table-column align="center" label="物流单号" prop="shipSn"> <el-table-column align="center" label="支付时间" prop="payTime"/>
</el-table-column>
<el-table-column align="center" label="物流渠道" prop="shipChannel"> <el-table-column align="center" label="物流单号" prop="shipSn"/>
</el-table-column>
<el-table-column align="center" label="物流渠道" prop="shipChannel"/>
<el-table-column align="center" label="操作" width="200" class-name="small-padding fixed-width"> <el-table-column align="center" label="操作" width="200" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleDetail(scope.row)">详情</el-button> <el-button type="primary" size="mini" @click="handleDetail(scope.row)">详情</el-button>
<el-button type="primary" size="mini" @click="handleShip(scope.row)" v-if="scope.row.orderStatus==201">发货</el-button> <el-button v-if="scope.row.orderStatus==201" type="primary" size="mini" @click="handleShip(scope.row)">发货</el-button>
<el-button type="primary" size="mini" @click="handleRefund(scope.row)" v-if="scope.row.orderStatus==202">退款</el-button> <el-button v-if="scope.row.orderStatus==202" type="primary" size="mini" @click="handleRefund(scope.row)">退款</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页 --> <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
<div class="pagination-container">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page"
:page-sizes="[10,20,30,50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<!-- 订单详情对话框 --> <!-- 订单详情对话框 -->
<el-dialog title="订单详情" width="800" :visible.sync="orderDialogVisible"> <el-dialog :visible.sync="orderDialogVisible" title="订单详情" width="800">
<el-form :data="orderDetail" label-position="left"> <el-form :data="orderDetail" label-position="left">
<el-form-item label="订单编号"> <el-form-item label="订单编号">
<span>{{ orderDetail.order.orderSn }}</span> <span>{{ orderDetail.order.orderSn }}</span>
</el-form-item> </el-form-item>
<el-form-item label="订单状态"> <el-form-item label="订单状态">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag>{{orderDetail.order.orderStatus | orderStatusFilter}}</el-tag> <el-tag>{{ orderDetail.order.orderStatus | orderStatusFilter }}</el-tag>
</template> </template>
</el-form-item> </el-form-item>
<el-form-item label="订单用户"> <el-form-item label="订单用户">
<span>{{ orderDetail.user.nickname }}</span> <span>{{ orderDetail.user.nickname }}</span>
</el-form-item> </el-form-item>
<el-form-item label="用户留言"> <el-form-item label="用户留言">
<span>{{ orderDetail.order.message }}</span> <span>{{ orderDetail.order.message }}</span>
</el-form-item> </el-form-item>
<el-form-item label="收货信息"> <el-form-item label="收货信息">
<span>(收货人){{ orderDetail.order.consignee }}</span> <span>(收货人){{ orderDetail.order.consignee }}</span>
<span>(手机号){{ orderDetail.order.mobile }}</span> <span>(手机号){{ orderDetail.order.mobile }}</span>
<span>(地址){{ orderDetail.order.address }}</span> <span>(地址){{ orderDetail.order.address }}</span>
</el-form-item> </el-form-item>
<el-form-item label="商品信息"> <el-form-item label="商品信息">
<el-table size="small" :data="orderDetail.orderGoods" border fit highlight-current-row> <el-table :data="orderDetail.orderGoods" size="small" border fit highlight-current-row>
<el-table-column align="center" label="商品名称" prop="goodsName" /> <el-table-column align="center" label="商品名称" prop="goodsName" />
<el-table-column align="center" label="商品编号" prop="goodsSn" /> <el-table-column align="center" label="商品编号" prop="goodsSn" />
<el-table-column align="center" label="货品规格" prop="specifications" /> <el-table-column align="center" label="货品规格" prop="specifications" />
<el-table-column align="center" label="货品价格" prop="price" /> <el-table-column align="center" label="货品价格" prop="price" />
<el-table-column align="center" label="货品数量" prop="number" /> <el-table-column align="center" label="货品数量" prop="number" />
<el-table-column align="center" label="货品图片" prop="picUrl"> <el-table-column align="center" label="货品图片" prop="picUrl">
<template slot-scope="scope"> <template slot-scope="scope">
<img :src="scope.row.picUrl" width="40"/> <img :src="scope.row.picUrl" width="40">
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-form-item> </el-form-item>
<el-form-item label="费用信息"> <el-form-item label="费用信息">
<span> <span>
(实际费用){{ orderDetail.order.actualPrice }}元 = (实际费用){{ orderDetail.order.actualPrice }}元 =
(商品总价){{ orderDetail.order.goodsPrice }}元 + (商品总价){{ orderDetail.order.goodsPrice }}元 +
(快递费用){{ orderDetail.order.freightPrice }}元 - (快递费用){{ orderDetail.order.freightPrice }}元 -
(优惠减免){{ orderDetail.order.couponPrice }}元 - (优惠减免){{ orderDetail.order.couponPrice }}元 -
(积分减免){{ orderDetail.order.integralPrice }}元 (积分减免){{ orderDetail.order.integralPrice }}元
</span> </span>
</el-form-item> </el-form-item>
<el-form-item label="支付信息"> <el-form-item label="支付信息">
<span>(支付渠道)微信支付</span> <span>(支付渠道)微信支付</span>
<span>(支付时间){{ orderDetail.order.payTime }}</span> <span>(支付时间){{ orderDetail.order.payTime }}</span>
</el-form-item> </el-form-item>
<el-form-item label="快递信息"> <el-form-item label="快递信息">
<span>(快递公司){{ orderDetail.order.shipChannel }}</span> <span>(快递公司){{ orderDetail.order.shipChannel }}</span>
<span>(快递单号){{ orderDetail.order.shipSn }}</span> <span>(快递单号){{ orderDetail.order.shipSn }}</span>
<span>(发货时间){{ orderDetail.order.shipTime }}</span> <span>(发货时间){{ orderDetail.order.shipTime }}</span>
</el-form-item> </el-form-item>
<el-form-item label="收货信息"> <el-form-item label="收货信息">
<span>(确认收货时间){{ orderDetail.order.confirmTime }}</span> <span>(确认收货时间){{ orderDetail.order.confirmTime }}</span>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-dialog> </el-dialog>
<!-- 发货对话框 --> <!-- 发货对话框 -->
<el-dialog title="发货" :visible.sync="shipDialogVisible"> <el-dialog :visible.sync="shipDialogVisible" title="发货">
<el-form ref="shipForm" :model="shipForm" status-icon label-position="left" label-width="100px" style='width: 400px; margin-left:50px;'> <el-form ref="shipForm" :model="shipForm" status-icon label-position="left" label-width="100px" style="width: 400px; margin-left:50px;">
<el-form-item label="快递公司" prop="shipChannel"> <el-form-item label="快递公司" prop="shipChannel">
<el-input v-model="shipForm.shipChannel"></el-input> <el-input v-model="shipForm.shipChannel"/>
</el-form-item> </el-form-item>
<el-form-item label="快递编号" prop="shipSn"> <el-form-item label="快递编号" prop="shipSn">
<el-input v-model="shipForm.shipSn"></el-input> <el-input v-model="shipForm.shipSn"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
...@@ -140,10 +124,10 @@ ...@@ -140,10 +124,10 @@
</el-dialog> </el-dialog>
<!-- 退款对话框 --> <!-- 退款对话框 -->
<el-dialog title="退款" :visible.sync="refundDialogVisible"> <el-dialog :visible.sync="refundDialogVisible" title="退款">
<el-form ref="refundForm" :model="refundForm" status-icon label-position="left" label-width="100px" style='width: 400px; margin-left:50px;'> <el-form ref="refundForm" :model="refundForm" status-icon label-position="left" label-width="100px" style="width: 400px; margin-left:50px;">
<el-form-item label="退款金额" prop="refundMoney"> <el-form-item label="退款金额" prop="refundMoney">
<el-input v-model="refundForm.refundMoney" :disabled="true"></el-input> <el-input v-model="refundForm.refundMoney" :disabled="true"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
...@@ -161,6 +145,7 @@ ...@@ -161,6 +145,7 @@
<script> <script>
import { listOrder, shipOrder, refundOrder, detailOrder } from '@/api/order' import { listOrder, shipOrder, refundOrder, detailOrder } from '@/api/order'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
const statusMap = { const statusMap = {
101: '未付款', 101: '未付款',
...@@ -176,6 +161,12 @@ const statusMap = { ...@@ -176,6 +161,12 @@ const statusMap = {
export default { export default {
name: 'Order', name: 'Order',
components: { Pagination },
filters: {
orderStatusFilter(status) {
return statusMap[status]
}
},
data() { data() {
return { return {
list: undefined, list: undefined,
...@@ -211,11 +202,6 @@ export default { ...@@ -211,11 +202,6 @@ export default {
downloadLoading: false downloadLoading: false
} }
}, },
filters: {
orderStatusFilter(status) {
return statusMap[status]
}
},
created() { created() {
this.getList() this.getList()
}, },
...@@ -236,14 +222,6 @@ export default { ...@@ -236,14 +222,6 @@ export default {
this.listQuery.page = 1 this.listQuery.page = 1
this.getList() this.getList()
}, },
handleSizeChange(val) {
this.listQuery.limit = val
this.getList()
},
handleCurrentChange(val) {
this.listQuery.page = val
this.getList()
},
handleDetail(row) { handleDetail(row) {
detailOrder(row.id).then(response => { detailOrder(row.id).then(response => {
this.orderDetail = response.data.data this.orderDetail = response.data.data
......
<template> <template>
<div class="app-container calendar-list-container"> <div class="app-container">
<!-- 查询和其他操作 --> <!-- 查询和其他操作 -->
<div class="filter-container"> <div class="filter-container">
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入行政区域名称" v-model="listQuery.name"> <el-input v-model="listQuery.name" clearable class="filter-item" style="width: 200px;" placeholder="请输入行政区域名称"/>
</el-input> <el-input v-model="listQuery.code" clearable class="filter-item" style="width: 200px;" placeholder="请输入行政区域编码"/>
<el-input clearable class="filter-item" style="width: 200px;" placeholder="请输入行政区域编码" v-model="listQuery.code">
</el-input>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button> <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-button class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload" :loading="downloadLoading">导出</el-button> <el-button :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">导出</el-button>
</div> </div>
<!-- 查询结果 --> <!-- 查询结果 -->
<el-table :data="list" v-loading="listLoading" element-loading-text="正在查询中。。。" border fit highlight-current-row> <el-table v-loading="listLoading" :data="list" element-loading-text="正在查询中。。。" border fit highlight-current-row>
<el-table-column align="center" width="100px" label="区域ID" prop="id" sortable> <el-table-column align="center" width="100px" label="区域ID" prop="id" sortable/>
</el-table-column>
<el-table-column align="center" min-width="100px" label="区域父ID" prop="pid"> <el-table-column align="center" min-width="100px" label="区域父ID" prop="pid"/>
</el-table-column>
<el-table-column align="center" min-width="200px" label="区域名称" prop="name"> <el-table-column align="center" min-width="200px" label="区域名称" prop="name"/>
</el-table-column>
<el-table-column align="center" min-width="100px" label="区域类型" prop="type"> <el-table-column align="center" min-width="100px" label="区域类型" prop="type">
<template slot-scope="scope"> <template slot-scope="scope">
{{scope.row.type | typeFilter }} {{ scope.row.type | typeFilter }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" min-width="100px" label="区域编码" prop="code"> <el-table-column align="center" min-width="100px" label="区域编码" prop="code"/>
</el-table-column>
</el-table> </el-table>
<!-- 分页 --> <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
<div class="pagination-container">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="listQuery.page"
:page-sizes="[10,20,30,50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
</div> </div>
</template> </template>
<script> <script>
import { listRegion } from '@/api/region' import { listRegion } from '@/api/region'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
export default { export default {
name: 'Region', name: 'Region',
components: { Pagination },
filters: {
typeFilter(status) {
const typeMap = {
'1': '',
'2': '',
'3': ''
}
return typeMap[status]
}
},
data() { data() {
return { return {
list: undefined, list: undefined,
...@@ -63,16 +64,6 @@ export default { ...@@ -63,16 +64,6 @@ export default {
downloadLoading: false downloadLoading: false
} }
}, },
filters: {
typeFilter(status) {
const typeMap = {
'1': '',
'2': '',
'3': ''
}
return typeMap[status]
}
},
created() { created() {
this.getList() this.getList()
}, },
...@@ -93,14 +84,6 @@ export default { ...@@ -93,14 +84,6 @@ export default {
this.listQuery.page = 1 this.listQuery.page = 1
this.getList() this.getList()
}, },
handleSizeChange(val) {
this.listQuery.limit = val
this.getList()
},
handleCurrentChange(val) {
this.listQuery.page = val
this.getList()
},
handleDownload() { handleDownload() {
this.downloadLoading = true this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => { import('@/vendor/Export2Excel').then(excel => {
...@@ -112,4 +95,4 @@ export default { ...@@ -112,4 +95,4 @@ export default {
} }
} }
} }
</script> </script>
\ No newline at end of file
<template> <template>
<div class="app-container calendar-list-container"> <div class="app-container">
<el-form :rules="rules" ref="dataForm" :model="dataForm" status-icon label-position="left" label-width="100px" style='width: 400px; margin-left:50px;'> <el-form ref="dataForm" :rules="rules" :model="dataForm" status-icon label-position="left" label-width="100px" style="width: 400px; margin-left:50px;">
<el-form-item label="原密码" prop="oldPassword"> <el-form-item label="原密码" prop="oldPassword">
<el-input type="password" v-model="dataForm.oldPassword"></el-input> <el-input v-model="dataForm.oldPassword" type="password"/>
</el-form-item> </el-form-item>
<el-form-item label="新密码" prop="newPassword"> <el-form-item label="新密码" prop="newPassword">
<el-input type="password" v-model="dataForm.newPassword" auto-complete="off"></el-input> <el-input v-model="dataForm.newPassword" type="password" auto-complete="off"/>
</el-form-item> </el-form-item>
<el-form-item label="确认密码" prop="newPassword2"> <el-form-item label="确认密码" prop="newPassword2">
<el-input type="password" v-model="dataForm.newPassword2" auto-complete="off"></el-input> <el-input v-model="dataForm.newPassword2" type="password" auto-complete="off"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div style='margin-left:100px;'> <div style="margin-left:100px;">
<el-button @click="cancel">取消</el-button> <el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="change">确定</el-button> <el-button type="primary" @click="change">确定</el-button>
</div> </div>
</div> </div>
</template> </template>
......
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