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

Merge branch 'master' into dev

parents 693cf5cd 4c46da9b
<template>
<div v-if="!item.hidden&&item.children" class="menu-wrapper">
<div v-if="!item.hidden" class="menu-wrapper">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link :to="resolvePath(onlyOneChild.path)">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon||item.meta.icon" :title="onlyOneChild.meta.title" />
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
</el-menu-item>
</app-link>
</template>
<el-submenu v-else ref="submenu" :index="resolvePath(item.path)">
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title">
<item v-if="item.meta" :icon="item.meta.icon" :title="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="child.meta.title" />
</el-menu-item>
</app-link>
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
class="nest-menu"
/>
</el-submenu>
</div>
</template>
<script>
import path from 'path'
import { isExternal } from '@/utils'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'
......@@ -61,12 +50,13 @@ export default {
}
},
data() {
return {
onlyOneChild: null
}
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
// TODO: refactor with render function
this.onlyOneChild = null
return {}
},
methods: {
hasOneShowingChild(children, parent) {
hasOneShowingChild(children = [], parent) {
const showingChildren = children.filter(item => {
if (item.hidden) {
return false
......@@ -91,13 +81,13 @@ export default {
return false
},
resolvePath(routePath) {
if (this.isExternalLink(routePath)) {
if (isExternal(routePath)) {
return routePath
}
if (isExternal(this.basePath)) {
return this.basePath
}
return path.resolve(this.basePath, routePath)
},
isExternalLink(routePath) {
return isExternal(routePath)
}
}
}
......
<template>
<div class="tags-view-container">
<div id="tags-view-container" class="tags-view-container">
<scroll-pane ref="scrollPane" class="tags-view-wrapper">
<router-link
v-for="tag in visitedViews"
ref="tag"
:key="tag.path"
: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)">
@click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"
@contextmenu.prevent.native="openMenu(tag,$event)"
>
{{ tag.title }}
<span class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
<span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
</router-link>
</scroll-pane>
<ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
<li @click="refreshSelectedTag(selectedTag)">刷新</li>
<li @click="closeSelectedTag(selectedTag)">关闭</li>
<li @click="closeOthersTags">关闭其</li>
<li @click="closeAllTags">关闭所有</li>
<li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">关闭</li>
<li @click="closeOthersTags">关闭其</li>
<li @click="closeAllTags(selectedTag)">关闭所有</li>
</ul>
</div>
</template>
<script>
import ScrollPane from '@/components/ScrollPane'
import ScrollPane from './ScrollPane'
import path from 'path'
export default {
components: { ScrollPane },
......@@ -34,17 +36,21 @@ export default {
visible: false,
top: 0,
left: 0,
selectedTag: {}
selectedTag: {},
affixTags: []
}
},
computed: {
visitedViews() {
return this.$store.state.tagsView.visitedViews
},
routes() {
return this.$store.state.permission.routers
}
},
watch: {
$route() {
this.addViewTags()
this.addTags()
this.moveToCurrentTag()
},
visible(value) {
......@@ -56,16 +62,50 @@ export default {
}
},
mounted() {
this.addViewTags()
this.initTags()
this.addTags()
},
methods: {
isActive(route) {
return route.path === this.$route.path
},
addViewTags() {
isAffix(tag) {
return tag.meta && tag.meta.affix
},
filterAffixTags(routes, basePath = '/') {
let tags = []
routes.forEach(route => {
if (route.meta && route.meta.affix) {
const tagPath = path.resolve(basePath, route.path)
tags.push({
fullPath: tagPath,
path: tagPath,
name: route.name,
meta: { ...route.meta }
})
}
if (route.children) {
const tempTags = this.filterAffixTags(route.children, route.path)
if (tempTags.length >= 1) {
tags = [...tags, ...tempTags]
}
}
})
return tags
},
initTags() {
const affixTags = this.affixTags = this.filterAffixTags(this.routes)
for (const tag of affixTags) {
// Must have tag name
if (tag.name) {
this.$store.dispatch('tagsView/addVisitedView', tag)
}
}
},
addTags() {
const { name } = this.$route
if (name) {
this.$store.dispatch('addView', this.$route)
this.$store.dispatch('tagsView/addView', this.$route)
}
return false
},
......@@ -75,19 +115,17 @@ export default {
for (const tag of tags) {
if (tag.to.path === this.$route.path) {
this.$refs.scrollPane.moveToTarget(tag)
// when query is different then update
if (tag.to.fullPath !== this.$route.fullPath) {
this.$store.dispatch('updateVisitedView', this.$route)
this.$store.dispatch('tagsView/updateVisitedView', this.$route)
}
break
}
}
})
},
refreshSelectedTag(view) {
this.$store.dispatch('delCachedView', view).then(() => {
this.$store.dispatch('tagsView/delCachedView', view).then(() => {
const { fullPath } = view
this.$nextTick(() => {
this.$router.replace({
......@@ -97,26 +135,40 @@ export default {
})
},
closeSelectedTag(view) {
this.$store.dispatch('delView', view).then(({ visitedViews }) => {
this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
if (this.isActive(view)) {
const latestView = visitedViews.slice(-1)[0]
if (latestView) {
this.$router.push(latestView)
} else {
this.$router.push('/')
}
this.toLastView(visitedViews, view)
}
})
},
closeOthersTags() {
this.$router.push(this.selectedTag)
this.$store.dispatch('delOthersViews', this.selectedTag).then(() => {
this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
this.moveToCurrentTag()
})
},
closeAllTags() {
this.$store.dispatch('delAllViews')
this.$router.push('/')
closeAllTags(view) {
this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
if (this.affixTags.some(tag => tag.path === view.path)) {
return
}
this.toLastView(visitedViews, view)
})
},
toLastView(visitedViews, view) {
const latestView = visitedViews.slice(-1)[0]
if (latestView) {
this.$router.push(latestView.fullPath)
} else {
// now the default is to redirect to the home page if there is no tags-view,
// you can adjust it according to your needs.
if (view.name === 'Dashboard') {
// to reload home page
this.$router.replace({ path: '/redirect' + view.fullPath })
} else {
this.$router.push('/')
}
}
},
openMenu(tag, e) {
const menuMinWidth = 105
......@@ -130,8 +182,8 @@ export default {
} else {
this.left = left
}
this.top = e.clientY
this.top = e.clientY
this.visible = true
this.selectedTag = tag
},
......@@ -142,7 +194,7 @@ export default {
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
<style lang="scss" scoped>
.tags-view-container {
height: 34px;
width: 100%;
......@@ -189,7 +241,7 @@ export default {
.contextmenu {
margin: 0;
background: #fff;
z-index: 100;
z-index: 3000;
position: absolute;
list-style-type: none;
padding: 5px 0;
......@@ -210,7 +262,7 @@ export default {
}
</style>
<style rel="stylesheet/scss" lang="scss">
<style lang="scss">
//reset element css of el-icon-close
.tags-view-wrapper {
.tags-view-item {
......
......@@ -5,20 +5,17 @@
<h3 class="title">管理员登录</h3>
</div>
<el-form-item prop="username">
<span class="svg-container svg-container_login">
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<el-input v-model="loginForm.username" name="username" type="text" auto-complete="on" placeholder="username" />
<el-input v-model="loginForm.username" name="username" type="text" tabindex="1" auto-complete="on" placeholder="管理员账户" />
</el-form-item>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<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">
<svg-icon icon-class="eye" />
</span>
<el-input v-model="loginForm.password" :type="passwordType" name="password" auto-complete="on" tabindex="2" show-password placeholder="管理员密码" @keyup.enter.native="handleLogin" />
</el-form-item>
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登录</el-button>
......@@ -46,13 +43,6 @@
export default {
name: 'Login',
data() {
const validateUsername = (rule, value, callback) => {
if (validateUsername == null) {
callback(new Error('请输入正确的管理员用户名'))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (value.length < 6) {
callback(new Error('管理员密码长度应大于6'))
......@@ -66,8 +56,11 @@ export default {
password: 'admin123'
},
loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
password: [{ required: true, trigger: 'blur', validator: validatePassword }]
username: [{ required: true, message: '管理员账户不允许为空', trigger: 'blur' }],
password: [
{ required: true, message: '管理员密码不允许为空', trigger: 'blur' },
{ validator: validatePassword, trigger: 'blur' }
]
},
passwordType: 'password',
loading: false
......@@ -89,13 +82,6 @@ export default {
// window.removeEventListener('hashchange', this.afterQRScan)
},
methods: {
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
},
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid && !this.loading) {
......@@ -119,9 +105,19 @@ export default {
}
</script>
<style rel="stylesheet/scss" lang="scss">
$bg:#2d3a4b;
$light_gray:#eee;
<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
$bg:#283443;
$light_gray:#fff;
$cursor: #fff;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input {
color: $cursor;
}
}
/* reset element-ui css */
.login-container {
......@@ -129,6 +125,7 @@ $light_gray:#eee;
display: inline-block;
height: 47px;
width: 85%;
input {
background: transparent;
border: 0px;
......@@ -137,13 +134,15 @@ $light_gray:#eee;
padding: 12px 5px 12px 15px;
color: $light_gray;
height: 47px;
caret-color: $cursor;
&:-webkit-autofill {
box-shadow: 0 0 0px 1000px $bg inset !important;
-webkit-box-shadow: 0 0 0px 1000px $bg inset !important;
-webkit-text-fill-color: #fff !important;
-webkit-text-fill-color: $cursor !important;
}
}
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
......@@ -153,63 +152,57 @@ $light_gray:#eee;
}
</style>
<style rel="stylesheet/scss" lang="scss" scoped>
<style lang="scss" scoped>
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee;
.login-container {
position: fixed;
height: 100%;
min-height: 100%;
width: 100%;
background-color: $bg;
overflow: hidden;
.login-form {
position: absolute;
left: 0;
right: 0;
position: relative;
width: 520px;
padding: 35px 35px 15px 35px;
margin: 120px auto;
max-width: 100%;
padding: 160px 35px 0;
margin: 0 auto;
overflow: hidden;
}
.tips {
font-size: 14px;
color: #fff;
margin-bottom: 10px;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
&_login {
font-size: 20px;
}
}
.title-container {
position: relative;
.title {
font-size: 26px;
font-weight: 400;
color: $light_gray;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
</style>
......@@ -110,7 +110,7 @@ export default {
data() {
return {
uploadPath,
list: undefined,
list: [],
total: 0,
listLoading: true,
listQuery: {
......@@ -157,7 +157,7 @@ export default {
this.listLoading = true
listBrand(this.listQuery)
.then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
})
......
......@@ -180,7 +180,7 @@ export default {
this.listLoading = true
listCategory()
.then(response => {
this.list = response.data.data
this.list = response.data.data.list
this.listLoading = false
})
.catch(() => {
......@@ -190,7 +190,7 @@ export default {
},
getCatL1() {
listCatL1().then(response => {
this.catL1 = response.data.data
this.catL1 = response.data.data.list
})
},
resetForm() {
......
......@@ -91,7 +91,7 @@ export default {
getList() {
this.listLoading = true
listIssue(this.listQuery).then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
}).catch(() => {
......
......@@ -82,7 +82,7 @@ export default {
components: { Pagination },
data() {
return {
list: undefined,
list: [],
total: 0,
listLoading: true,
listQuery: {
......@@ -119,7 +119,7 @@ export default {
getList() {
this.listLoading = true
listKeyword(this.listQuery).then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
}).catch(() => {
......
......@@ -3,10 +3,10 @@
<!-- 查询和其他操作 -->
<div class="filter-container">
<el-input v-model="listQuery.userId" clearable class="filter-item" style="width: 200px;" placeholder="请输入用户ID"/>
<el-input v-model="listQuery.orderSn" clearable class="filter-item" style="width: 200px;" placeholder="请输入订单编号"/>
<el-input v-model="listQuery.userId" clearable class="filter-item" style="width: 200px;" placeholder="请输入用户ID" />
<el-input v-model="listQuery.orderSn" clearable class="filter-item" style="width: 200px;" placeholder="请输入订单编号" />
<el-select v-model="listQuery.orderStatusArray" multiple style="width: 200px" class="filter-item" placeholder="请选择订单状态">
<el-option v-for="(key, value) in statusMap" :key="key" :label="key" :value="value"/>
<el-option v-for="(key, value) in statusMap" :key="key" :label="key" :value="value" />
</el-select>
<el-button v-permission="['GET /admin/order/list']" class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-button :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">导出</el-button>
......@@ -15,9 +15,9 @@
<!-- 查询结果 -->
<el-table v-loading="listLoading" :data="list" 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 align="center" label="用户ID" prop="userId"/>
<el-table-column align="center" label="用户ID" prop="userId" />
<el-table-column align="center" label="订单状态" prop="orderStatus">
<template slot-scope="scope">
......@@ -25,21 +25,21 @@
</template>
</el-table-column>
<el-table-column align="center" label="订单金额" prop="orderPrice"/>
<el-table-column align="center" label="订单金额" prop="orderPrice" />
<el-table-column align="center" label="支付金额" prop="actualPrice"/>
<el-table-column align="center" label="支付金额" prop="actualPrice" />
<el-table-column align="center" label="支付时间" prop="payTime"/>
<el-table-column align="center" label="支付时间" prop="payTime" />
<el-table-column align="center" label="物流单号" prop="shipSn"/>
<el-table-column align="center" label="物流单号" prop="shipSn" />
<el-table-column align="center" label="物流渠道" prop="shipChannel"/>
<el-table-column align="center" label="物流渠道" prop="shipChannel" />
<el-table-column align="center" label="操作" width="200" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button v-permission="['GET /admin/order/detail']" type="primary" size="mini" @click="handleDetail(scope.row)">详情</el-button>
<el-button v-permission="['POST /admin/order/ship']" v-if="scope.row.orderStatus==201" type="primary" size="mini" @click="handleShip(scope.row)">发货</el-button>
<el-button v-permission="['POST /admin/order/refund']" v-if="scope.row.orderStatus==202" type="primary" size="mini" @click="handleRefund(scope.row)">退款</el-button>
<el-button v-if="scope.row.orderStatus==201" v-permission="['POST /admin/order/ship']" type="primary" size="mini" @click="handleShip(scope.row)">发货</el-button>
<el-button v-if="scope.row.orderStatus==202||scope.row.orderStatus==204" v-permission="['POST /admin/order/refund']" type="primary" size="mini" @click="handleRefund(scope.row)">退款</el-button>
</template>
</el-table-column>
</el-table>
......@@ -48,71 +48,84 @@
<!-- 订单详情对话框 -->
<el-dialog :visible.sync="orderDialogVisible" title="订单详情" width="800">
<el-form :data="orderDetail" label-position="left">
<el-form-item label="订单编号">
<span>{{ orderDetail.order.orderSn }}</span>
</el-form-item>
<el-form-item label="订单状态">
<el-tag>{{ orderDetail.order.orderStatus | orderStatusFilter }}</el-tag>
</el-form-item>
<el-form-item label="订单用户">
<span>{{ orderDetail.user.nickname }}</span>
</el-form-item>
<el-form-item label="用户留言">
<span>{{ orderDetail.order.message }}</span>
</el-form-item>
<el-form-item label="收货信息">
<span>(收货人){{ orderDetail.order.consignee }}</span>
<span>(手机号){{ orderDetail.order.mobile }}</span>
<span>(地址){{ orderDetail.order.address }}</span>
</el-form-item>
<el-form-item label="商品信息">
<el-table :data="orderDetail.orderGoods" border fit highlight-current-row>
<el-table-column align="center" label="商品名称" prop="goodsName" />
<el-table-column align="center" label="商品编号" prop="goodsSn" />
<el-table-column align="center" label="货品规格" prop="specifications" />
<el-table-column align="center" label="货品价格" prop="price" />
<el-table-column align="center" label="货品数量" prop="number" />
<el-table-column align="center" label="货品图片" prop="picUrl">
<template slot-scope="scope">
<img :src="scope.row.picUrl" width="40">
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item label="费用信息">
<span>
(实际费用){{ orderDetail.order.actualPrice }}元 =
(商品总价){{ orderDetail.order.goodsPrice }}元 +
(快递费用){{ orderDetail.order.freightPrice }}元 -
(优惠减免){{ orderDetail.order.couponPrice }}元 -
(积分减免){{ orderDetail.order.integralPrice }}元
</span>
</el-form-item>
<el-form-item label="支付信息">
<span>(支付渠道)微信支付</span>
<span>(支付时间){{ orderDetail.order.payTime }}</span>
</el-form-item>
<el-form-item label="快递信息">
<span>(快递公司){{ orderDetail.order.shipChannel }}</span>
<span>(快递单号){{ orderDetail.order.shipSn }}</span>
<span>(发货时间){{ orderDetail.order.shipTime }}</span>
</el-form-item>
<el-form-item label="收货信息">
<span>(确认收货时间){{ orderDetail.order.confirmTime }}</span>
</el-form-item>
</el-form>
<section ref="print">
<el-form :data="orderDetail" label-position="left">
<el-form-item label="订单编号">
<span>{{ orderDetail.order.orderSn }}</span>
</el-form-item>
<el-form-item label="订单状态">
<el-tag>{{ orderDetail.order.orderStatus | orderStatusFilter }}</el-tag>
</el-form-item>
<el-form-item label="订单用户">
<span>{{ orderDetail.user.nickname }}</span>
</el-form-item>
<el-form-item label="用户留言">
<span>{{ orderDetail.order.message }}</span>
</el-form-item>
<el-form-item label="收货信息">
<span>(收货人){{ orderDetail.order.consignee }}</span>
<span>(手机号){{ orderDetail.order.mobile }}</span>
<span>(地址){{ orderDetail.order.address }}</span>
</el-form-item>
<el-form-item label="商品信息">
<el-table :data="orderDetail.orderGoods" border fit highlight-current-row>
<el-table-column align="center" label="商品名称" prop="goodsName" />
<el-table-column align="center" label="商品编号" prop="goodsSn" />
<el-table-column align="center" label="货品规格" prop="specifications" />
<el-table-column align="center" label="货品价格" prop="price" />
<el-table-column align="center" label="货品数量" prop="number" />
<el-table-column align="center" label="货品图片" prop="picUrl">
<template slot-scope="scope">
<img :src="scope.row.picUrl" width="40">
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item label="费用信息">
<span>
(实际费用){{ orderDetail.order.actualPrice }}元 =
(商品总价){{ orderDetail.order.goodsPrice }}元 +
(快递费用){{ orderDetail.order.freightPrice }}元 -
(优惠减免){{ orderDetail.order.couponPrice }}元 -
(积分减免){{ orderDetail.order.integralPrice }}元
</span>
</el-form-item>
<el-form-item label="支付信息">
<span>(支付渠道)微信支付</span>
<span>(支付时间){{ orderDetail.order.payTime }}</span>
</el-form-item>
<el-form-item label="快递信息">
<span>(快递公司){{ orderDetail.order.shipChannel }}</span>
<span>(快递单号){{ orderDetail.order.shipSn }}</span>
<span>(发货时间){{ orderDetail.order.shipTime }}</span>
</el-form-item>
<el-form-item label="退款信息">
<span>(退款金额){{ orderDetail.order.refundAmount }}元</span>
<span>(退款类型){{ orderDetail.order.refundType }}</span>
<span>(退款备注){{ orderDetail.order.refundContent }}</span>
<span>(退款时间){{ orderDetail.order.refundTime }}</span>
</el-form-item>
<el-form-item label="收货信息">
<span>(确认收货时间){{ orderDetail.order.confirmTime }}</span>
</el-form-item>
</el-form>
</section>
<span slot="footer" class="dialog-footer">
<el-button @click="orderDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="printOrder">打 印</el-button>
</span>
</el-dialog>
<!-- 发货对话框 -->
<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-item label="快递公司" prop="shipChannel">
<el-input v-model="shipForm.shipChannel"/>
<el-select v-model="shipForm.shipChannel" placeholder="请选择">
<el-option v-for="item in channels" :key="item.code" :label="item.name" :value="item.code" />
</el-select>
</el-form-item>
<el-form-item label="快递编号" prop="shipSn">
<el-input v-model="shipForm.shipSn"/>
<el-input v-model="shipForm.shipSn" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
......@@ -125,7 +138,7 @@
<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-item label="退款金额" prop="refundMoney">
<el-input v-model="refundForm.refundMoney" :disabled="true"/>
<el-input v-model="refundForm.refundMoney" :disabled="true" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
......@@ -137,12 +150,8 @@
</div>
</template>
<style>
</style>
<script>
import { listOrder, shipOrder, refundOrder, detailOrder } from '@/api/order'
import { detailOrder, listOrder, listChannel, refundOrder, shipOrder } from '@/api/order'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
import checkPermission from '@/utils/permission' // 权限判断函数
......@@ -150,9 +159,11 @@ const statusMap = {
101: '未付款',
102: '用户取消',
103: '系统取消',
200: '已付款团购',
201: '已付款',
202: '申请退款',
203: '已退款',
204: '已超时团购',
301: '已发货',
401: '用户收货',
402: '系统收货'
......@@ -168,7 +179,7 @@ export default {
},
data() {
return {
list: undefined,
list: [],
total: 0,
listLoading: true,
listQuery: {
......@@ -198,18 +209,20 @@ export default {
refundMoney: undefined
},
refundDialogVisible: false,
downloadLoading: false
downloadLoading: false,
channels: []
}
},
created() {
this.getList()
this.getChannel()
},
methods: {
checkPermission,
getList() {
this.listLoading = true
listOrder(this.listQuery).then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
}).catch(() => {
......@@ -218,6 +231,11 @@ export default {
this.listLoading = false
})
},
getChannel() {
listChannel().then(response => {
this.channels = response.data.data
})
},
handleFilter() {
this.listQuery.page = 1
this.getList()
......@@ -293,6 +311,10 @@ export default {
excel.export_json_to_excel2(tHeader, this.list, filterVal, '订单信息')
this.downloadLoading = false
})
},
printOrder() {
this.$print(this.$refs.print)
this.orderDialogVisible = false
}
}
}
......
......@@ -35,7 +35,7 @@ export default {
},
data() {
return {
list: undefined,
list: [],
listLoading: true,
downloadLoading: false
}
......@@ -47,7 +47,7 @@ export default {
getList() {
this.listLoading = true
listRegion().then(response => {
this.list = response.data.data
this.list = response.data.data.list
this.listLoading = false
}).catch(() => {
this.list = []
......
......@@ -60,10 +60,12 @@
:action="uploadPath"
:show-file-list="false"
:on-success="uploadUrl"
:before-upload="checkFileSize"
class="avatar-uploader"
accept=".jpg,.jpeg,.png,.gif">
<img v-if="dataForm.url" :src="dataForm.url" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"/>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过1024kb</div>
</el-upload>
</el-form-item>
<el-form-item label="广告位置" prop="position">
......@@ -129,7 +131,7 @@ export default {
data() {
return {
uploadPath,
list: undefined,
list: [],
total: 0,
listLoading: true,
listQuery: {
......@@ -182,7 +184,7 @@ export default {
this.listLoading = true
listAd(this.listQuery)
.then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
})
......@@ -218,6 +220,13 @@ export default {
uploadUrl: function(response) {
this.dataForm.url = response.data.url
},
checkFileSize: function(file) {
if (file.size > 1048576) {
this.$message.error(`${file.name}文件大于1024KB,请选择小于1024KB大小的图片`)
return false
}
return true
},
createData() {
this.$refs['dataForm'].validate(valid => {
if (valid) {
......
......@@ -245,7 +245,7 @@ export default {
return {
typeOptions: Object.assign({}, defaultTypeOptions),
statusOptions: Object.assign({}, defaultStatusOptions),
list: undefined,
list: [],
total: 0,
listLoading: true,
listQuery: {
......@@ -297,7 +297,7 @@ export default {
this.listLoading = true
listCoupon(this.listQuery)
.then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
})
......
......@@ -154,7 +154,7 @@ export default {
typeOptions: Object.assign({}, defaultTypeOptions),
useStatusOptions: Object.assign({}, defaultUseStatusOptions),
coupon: {},
list: undefined,
list: [],
total: 0,
listLoading: true,
listQuery: {
......@@ -187,7 +187,7 @@ export default {
this.listLoading = true
listCouponUser(this.listQuery)
.then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
})
......
......@@ -3,14 +3,15 @@
<!-- 查询和其他操作 -->
<div class="filter-container">
<el-input v-model="listQuery.goodsId" clearable class="filter-item" style="width: 200px;" placeholder="请输入商品编号"/>
<el-input v-model="listQuery.grouponRuleId" clearable class="filter-item" style="width: 200px;" placeholder="请输入团购规则ID" />
<el-button v-permission="['GET /admin/groupon/listRecord']" class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-button
:loading="downloadLoading"
class="filter-item"
type="primary"
icon="el-icon-download"
@click="handleDownload">导出
@click="handleDownload"
>导出
</el-button>
</div>
......@@ -20,21 +21,21 @@
<el-table-column type="expand">
<template slot-scope="scope">
<el-table :data="scope.row.subGroupons" border style="width: 100%">
<el-table-column align="center" label="订单ID" prop="orderId"/>
<el-table-column align="center" label="用户ID" prop="userId"/>
<el-table-column align="center" label="订单ID" prop="orderId" />
<el-table-column align="center" label="用户ID" prop="userId" />
</el-table>
</template>
</el-table-column>
<el-table-column align="center" label="订单ID" prop="groupon.orderId"/>
<el-table-column align="center" label="订单ID" prop="groupon.orderId" />
<el-table-column align="center" label="用户ID" prop="groupon.userId"/>
<el-table-column align="center" label="用户ID" prop="groupon.userId" />
<el-table-column align="center" label="参与人数" prop="subGroupons.length"/>
<el-table-column align="center" label="参与人数" prop="subGroupons.length" />
<el-table-column align="center" label="团购折扣" prop="rules.discount"/>
<el-table-column align="center" label="团购折扣" prop="rules.discount" />
<el-table-column align="center" label="团购要求" prop="rules.discountMember"/>
<el-table-column align="center" label="团购要求" prop="rules.discountMember" />
<el-table-column align="center" property="iconUrl" label="分享图片">
<template slot-scope="scope">
......@@ -42,15 +43,15 @@
</template>
</el-table-column>
<el-table-column align="center" label="开始时间" prop="rules.addTime"/>
<el-table-column align="center" label="开始时间" prop="rules.addTime" />
<el-table-column align="center" label="结束时间" prop="rules.expireTime"/>
<el-table-column align="center" label="结束时间" prop="rules.expireTime" />
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
<el-tooltip placement="top" content="返回顶部">
<back-to-top :visibility-height="100"/>
<back-to-top :visibility-height="100" />
</el-tooltip>
</div>
......@@ -93,7 +94,7 @@ export default {
listQuery: {
page: 1,
limit: 20,
goodsId: undefined,
grouponRuleId: undefined,
sort: 'add_time',
order: 'desc'
},
......@@ -109,7 +110,7 @@ export default {
getList() {
this.listLoading = true
listRecord(this.listQuery).then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
}).catch(() => {
......
......@@ -3,7 +3,7 @@
<!-- 查询和其他操作 -->
<div class="filter-container">
<el-input v-model="listQuery.goodsId" clearable class="filter-item" style="width: 200px;" placeholder="请输入商品编号"/>
<el-input v-model="listQuery.goodsId" clearable class="filter-item" style="width: 200px;" placeholder="请输入商品编号" />
<el-button v-permission="['GET /admin/groupon/list']" class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-button v-permission="['POST /admin/groupon/create']" class="filter-item" type="primary" icon="el-icon-edit" @click="handleCreate">添加</el-button>
<el-button
......@@ -11,15 +11,18 @@
class="filter-item"
type="primary"
icon="el-icon-download"
@click="handleDownload">导出
@click="handleDownload"
>导出
</el-button>
</div>
<!-- 查询结果 -->
<el-table v-loading="listLoading" :data="list" element-loading-text="正在查询中。。。" border fit highlight-current-row>
<el-table-column align="center" label="商品ID" prop="goodsId"/>
<el-table-column align="center" label="团购规则ID" prop="id" />
<el-table-column align="center" min-width="100" label="名称" prop="goodsName"/>
<el-table-column align="center" label="商品ID" prop="goodsId" />
<el-table-column align="center" min-width="100" label="名称" prop="goodsName" />
<el-table-column align="center" property="picUrl" label="图片">
<template slot-scope="scope">
......@@ -27,13 +30,17 @@
</template>
</el-table-column>
<el-table-column align="center" label="团购优惠" prop="discount"/>
<el-table-column align="center" label="团购优惠" prop="discount" />
<el-table-column align="center" label="团购要求" prop="discountMember"/>
<el-table-column align="center" label="团购要求" prop="discountMember" />
<el-table-column align="center" label="开始时间" prop="addTime"/>
<el-table-column align="center" label="状态" prop="status">
<template slot-scope="scope">
<el-tag :type="scope.row.status === 0 ? 'success' : 'error' ">{{ statusMap[scope.row.status] }}</el-tag>
</template>
</el-table-column>
<el-table-column align="center" label="结束时间" prop="expireTime"/>
<el-table-column align="center" label="结束时间" prop="expireTime" />
<el-table-column align="center" label="操作" width="200" class-name="small-padding fixed-width">
<template slot-scope="scope">
......@@ -51,23 +58,25 @@
:model="dataForm"
status-icon
label-position="left"
label-width="100px"
style="width: 400px; margin-left:50px;">
label-width="120px"
style="width: 400px; margin-left:50px;"
>
<el-form-item label="商品ID" prop="goodsId">
<el-input v-model="dataForm.goodsId"/>
<el-input v-model="dataForm.goodsId" />
</el-form-item>
<el-form-item label="团购折扣" prop="discount">
<el-input v-model="dataForm.discount"/>
<el-input v-model="dataForm.discount" />
</el-form-item>
<el-form-item label="团购人数要求" prop="discountMember">
<el-input v-model="dataForm.discountMember"/>
<el-input v-model="dataForm.discountMember" />
</el-form-item>
<el-form-item label="过期时间" prop="expireTime">
<el-date-picker
v-model="dataForm.expireTime"
type="datetime"
placeholder="选择日期"
value-format="yyyy-MM-dd HH:mm:ss"/>
value-format="yyyy-MM-dd HH:mm:ss"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
......@@ -80,7 +89,7 @@
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
<el-tooltip placement="top" content="返回顶部">
<back-to-top :visibility-height="100"/>
<back-to-top :visibility-height="100" />
</el-tooltip>
</div>
......@@ -120,8 +129,16 @@ export default {
update: '编辑',
create: '创建'
},
statusMap: [
'正常',
'到期下线',
'提前下线'
],
rules: {
goodsId: [{ required: true, message: '商品不能为空', trigger: 'blur' }]
goodsId: [{ required: true, message: '商品不能为空', trigger: 'blur' }],
discount: [{ required: true, message: '团购折扣不能为空', trigger: 'blur' }],
discountMember: [{ required: true, message: '团购人数不能为空', trigger: 'blur' }],
expireTime: [{ required: true, message: '过期时间不能为空', trigger: 'blur' }]
}
}
},
......@@ -132,7 +149,7 @@ export default {
getList() {
this.listLoading = true
listGroupon(this.listQuery).then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
}).catch(() => {
......
......@@ -35,7 +35,7 @@
<el-table-column align="center" label="阅读数量" prop="readCount"/>
<el-table-column align="center" label="操作" min-width="200" class-name="small-padding fixed-width">
<el-table-column align="center" label="操作" min-width="100" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button v-permission="['POST /admin/topic/update']" type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button v-permission="['POST /admin/topic/delete']" type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
......@@ -49,44 +49,6 @@
<back-to-top :visibility-height="100" />
</el-tooltip>
<!-- 添加或修改对话框 -->
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<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="title">
<el-input v-model="dataForm.title"/>
</el-form-item>
<el-form-item label="专题子标题" prop="subtitle">
<el-input v-model="dataForm.subtitle"/>
</el-form-item>
<el-form-item label="专题图片" prop="picUrl">
<el-upload
:headers="headers"
:action="uploadPath"
:show-file-list="false"
:on-success="uploadPicUrl"
class="avatar-uploader"
accept=".jpg,.jpeg,.png,.gif">
<img v-if="dataForm.picUrl" :src="dataForm.picUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"/>
</el-upload>
</el-form-item>
<el-form-item style="width: 700px;" label="专题内容">
<editor :init="editorInit" v-model="dataForm.content"/>
</el-form-item>
<el-form-item label="商品低价" prop="price">
<el-input v-model="dataForm.price"/>
</el-form-item>
<el-form-item label="阅读量" prop="readCount">
<el-input v-model="dataForm.readCount"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button v-if="dialogStatus=='create'" type="primary" @click="createData">确定</el-button>
<el-button v-else type="primary" @click="updateData">确定</el-button>
</div>
</el-dialog>
</div>
</template>
......@@ -120,20 +82,16 @@
</style>
<script>
import { listTopic, createTopic, updateTopic, deleteTopic } from '@/api/topic'
import { createStorage, uploadPath } from '@/api/storage'
import { listTopic, deleteTopic } from '@/api/topic'
import BackToTop from '@/components/BackToTop'
import Editor from '@tinymce/tinymce-vue'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
import { getToken } from '@/utils/auth'
export default {
name: 'Topic',
components: { BackToTop, Editor, Pagination },
components: { BackToTop, Pagination },
data() {
return {
uploadPath,
list: undefined,
list: [],
total: 0,
listLoading: true,
listQuery: {
......@@ -144,65 +102,9 @@ export default {
sort: 'add_time',
order: 'desc'
},
dataForm: {
id: undefined,
titile: undefined,
subtitle: undefined,
picUrl: undefined,
content: '',
price: undefined,
readCount: undefined,
goods: []
},
contentDetail: '',
contentDialogVisible: false,
dialogFormVisible: false,
dialogStatus: '',
textMap: {
update: '编辑',
create: '创建'
},
rules: {
title: [
{ required: true, message: '专题标题不能为空', trigger: 'blur' }
],
subtitle: [
{ required: true, message: '专题子标题不能为空', trigger: 'blur' }
],
content: [
{ required: true, message: '专题内容不能为空', trigger: 'blur' }
]
},
downloadLoading: false,
editorInit: {
language: 'zh_CN',
convert_urls: false,
plugins: [
'advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount'
],
toolbar: [
'searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample',
'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen'
],
images_upload_handler: function(blobInfo, success, failure) {
const formData = new FormData()
formData.append('file', blobInfo.blob())
createStorage(formData)
.then(res => {
success(res.data.data.url)
})
.catch(() => {
failure('上传失败,请重新上传')
})
}
}
}
},
computed: {
headers() {
return {
'X-Litemall-Admin-Token': getToken()
}
downloadLoading: false
}
},
created() {
......@@ -213,7 +115,7 @@ export default {
this.listLoading = true
listTopic(this.listQuery)
.then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
})
......@@ -227,88 +129,11 @@ export default {
this.listQuery.page = 1
this.getList()
},
resetForm() {
this.dataForm = {
id: undefined,
titile: undefined,
subtitle: undefined,
picUrl: undefined,
content: '',
price: undefined,
readCount: undefined,
goods: []
}
},
handleCreate() {
this.resetForm()
this.dialogStatus = 'create'
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
uploadPicUrl: function(response) {
this.dataForm.picUrl = response.data.url
},
createData() {
this.$refs['dataForm'].validate(valid => {
if (valid) {
createTopic(this.dataForm)
.then(response => {
this.list.unshift(response.data.data)
this.dialogFormVisible = false
this.$notify.success({
title: '成功',
message: '创建专题成功'
})
})
.catch(response => {
this.$notify.error({
title: '失败',
message: response.data.errmsg
})
})
}
})
},
showContent(content) {
this.contentDetail = content
this.contentDialogVisible = true
this.$router.push({ path: '/promotion/topic-create' })
},
handleUpdate(row) {
this.dataForm = Object.assign({}, row)
this.dialogStatus = 'update'
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
updateData() {
this.$refs['dataForm'].validate(valid => {
if (valid) {
updateTopic(this.dataForm)
.then(() => {
for (const v of this.list) {
if (v.id === this.dataForm.id) {
const index = this.list.indexOf(v)
this.list.splice(index, 1, this.dataForm)
break
}
}
this.dialogFormVisible = false
this.$notify.success({
title: '成功',
message: '更新专题成功'
})
})
.catch(response => {
this.$notify.error({
title: '失败',
message: response.data.errmsg
})
})
}
})
this.$router.push({ path: '/promotion/topic-edit', query: { id: row.id }})
},
handleDelete(row) {
deleteTopic(row)
......@@ -327,6 +152,10 @@ export default {
})
})
},
showContent(content) {
this.contentDetail = content
this.contentDialogVisible = true
},
handleDownload() {
this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => {
......
<template>
<div class="app-container">
<el-form ref="topic" :rules="rules" :model="topic" status-icon label-position="left" label-width="100px" style="width: 800px; margin-left:50px;">
<el-form-item label="专题标题" prop="title">
<el-input v-model="topic.title"/>
</el-form-item>
<el-form-item label="专题子标题" prop="subtitle">
<el-input v-model="topic.subtitle"/>
</el-form-item>
<el-form-item label="专题图片" prop="picUrl">
<el-upload
:headers="headers"
:action="uploadPath"
:show-file-list="false"
:on-success="uploadPicUrl"
class="avatar-uploader"
accept=".jpg,.jpeg,.png,.gif">
<img v-if="topic.picUrl" :src="topic.picUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"/>
</el-upload>
</el-form-item>
<el-form-item label="专题内容" prop="content">
<editor :init="editorInit" v-model="topic.content"/>
</el-form-item>
<el-form-item label="商品低价" prop="price">
<el-input v-model="topic.price"/>
</el-form-item>
<el-form-item label="阅读量" prop="readCount">
<el-input v-model="topic.readCount"/>
</el-form-item>
<el-form-item label="专题商品" prop="goods">
<el-button style="float:right;" size="mini" type="primary" @click="handleCreate()">创建商品</el-button>
<!-- 查询结果 -->
<el-table :data="goodsList" border fit highlight-current-row>
<el-table-column align="center" label="商品ID" prop="id"/>
<el-table-column align="center" property="picUrl" label="图片">
<template slot-scope="scope">
<img :src="scope.row.picUrl" width="60">
</template>
</el-table-column>
<el-table-column align="center" label="商品名称" prop="name"/>
<el-table-column align="center" label="商品介绍" prop="brief"/>
<el-table-column align="center" label="操作" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</div>
<el-dialog :visible.sync="addVisiable" title="添加商品">
<div class="search">
<el-input v-model="listQuery.goodsSn" clearable class="filter-item" style="width: 200px;" placeholder="请输入商品编号"/>
<el-input v-model="listQuery.name" clearable class="filter-item" style="width: 200px;" placeholder="请输入商品名称"/>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-table v-loading="listLoading" :data="list" element-loading-text="正在查询中。。。" border fit highlight-current-row @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"/>
<el-table-column align="center" label="商品ID" prop="id"/>
<el-table-column align="center" property="picUrl" label="图片">
<template slot-scope="scope">
<img :src="scope.row.picUrl" width="40">
</template>
</el-table-column>
<el-table-column align="center" label="商品名称" prop="name"/>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="addVisiable = false">取消</el-button>
<el-button type="primary" @click="confirmAdd">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<style>
.el-dialog {
width: 800px;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #20a0ff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 120px;
height: 120px;
line-height: 120px;
text-align: center;
}
.avatar {
width: 145px;
height: 145px;
display: block;
}
</style>
<script>
import { createTopic } from '@/api/topic'
import { listGoods } from '@/api/goods'
import { createStorage, uploadPath } from '@/api/storage'
import BackToTop from '@/components/BackToTop'
import Editor from '@tinymce/tinymce-vue'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
import { getToken } from '@/utils/auth'
export default {
name: 'TopicEdit',
components: { BackToTop, Editor, Pagination },
data() {
return {
uploadPath,
id: 0,
topic: {
goods: []
},
goodsList: [],
addVisiable: false,
list: [],
total: 0,
listLoading: false,
listQuery: {
page: 1,
limit: 5,
id: undefined,
name: undefined,
sort: 'add_time',
order: 'desc'
},
selectedlist: [],
rules: {
title: [
{ required: true, message: '专题标题不能为空', trigger: 'blur' }
],
subtitle: [
{ required: true, message: '专题子标题不能为空', trigger: 'blur' }
],
content: [
{ required: true, message: '专题内容不能为空', trigger: 'blur' }
],
price: [
{ required: true, message: '专题低价不能为空', trigger: 'blur' }
]
},
editorInit: {
language: 'zh_CN',
convert_urls: false,
height: 500,
plugins: [
'advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount'
],
toolbar: [
'searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample',
'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen'
],
images_upload_handler: function(blobInfo, success, failure) {
const formData = new FormData()
formData.append('file', blobInfo.blob())
createStorage(formData)
.then(res => {
success(res.data.data.url)
})
.catch(() => {
failure('上传失败,请重新上传')
})
}
}
}
},
computed: {
headers() {
return {
'X-Litemall-Admin-Token': getToken()
}
}
},
created() {
},
methods: {
getList() {
this.listLoading = true
listGoods(this.listQuery).then(response => {
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
}).catch(() => {
this.list = []
this.total = 0
this.listLoading = false
})
},
handleFilter() {
this.listQuery.page = 1
this.getList()
},
handleSelectionChange(val) {
this.selectedlist = val
},
uploadPicUrl: function(response) {
this.topic.picUrl = response.data.url
},
handleCreate() {
this.listQuery = {
page: 1,
limit: 5,
id: undefined,
name: undefined,
sort: 'add_time',
order: 'desc'
}
this.list = []
this.total = 0
this.selectedlist = []
this.addVisiable = true
},
confirmAdd() {
const newGoodsIds = []
const newGoodsList = []
this.selectedlist.forEach(item => {
const id = item.id
let found = false
this.topic.goods.forEach(goodsId => {
if (id === goodsId) {
found = true
}
})
if (!found) {
newGoodsIds.push(id)
newGoodsList.push(item)
}
})
if (newGoodsIds.length > 0) {
this.topic.goods = this.topic.goods.concat(newGoodsIds)
this.goodsList = this.goodsList.concat(newGoodsList)
}
this.addVisiable = false
},
handleDelete(row) {
for (var index = 0; index < this.topic.goods.length; index++) {
if (row.id === this.topic.goods[index]) {
this.topic.goods.splice(index, 1)
}
}
for (var index2 = 0; index2 < this.goodsList.length; index2++) {
if (row.id === this.goodsList[index2].id) {
this.goodsList.splice(index2, 1)
}
}
},
handleCancel() {
this.$router.push({ path: '/promotion/topic' })
},
handleConfirm() {
this.$refs['topic'].validate(valid => {
if (valid) {
createTopic(this.topic).then(response => {
this.$router.push({ path: '/promotion/topic' })
})
.catch(response => {
this.$notify.error({
title: '失败',
message: response.data.errmsg
})
})
}
})
}
}
}
</script>
<template>
<div class="app-container">
<el-form ref="topic" :rules="rules" :model="topic" status-icon label-position="left" label-width="100px" style="width: 800px; margin-left:50px;">
<el-form-item label="专题标题" prop="title">
<el-input v-model="topic.title"/>
</el-form-item>
<el-form-item label="专题子标题" prop="subtitle">
<el-input v-model="topic.subtitle"/>
</el-form-item>
<el-form-item label="专题图片" prop="picUrl">
<el-upload
:headers="headers"
:action="uploadPath"
:show-file-list="false"
:on-success="uploadPicUrl"
class="avatar-uploader"
accept=".jpg,.jpeg,.png,.gif">
<img v-if="topic.picUrl" :src="topic.picUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"/>
</el-upload>
</el-form-item>
<el-form-item label="专题内容" prop="content">
<editor :init="editorInit" v-model="topic.content"/>
</el-form-item>
<el-form-item label="商品低价" prop="price">
<el-input v-model="topic.price"/>
</el-form-item>
<el-form-item label="阅读量" prop="readCount">
<el-input v-model="topic.readCount"/>
</el-form-item>
<el-form-item label="专题商品" prop="goods">
<el-button style="float:right;" size="mini" type="primary" @click="handleCreate()">创建商品</el-button>
<!-- 查询结果 -->
<el-table :data="goodsList" border fit highlight-current-row>
<el-table-column align="center" label="商品ID" prop="id"/>
<el-table-column align="center" property="picUrl" label="图片">
<template slot-scope="scope">
<img :src="scope.row.picUrl" width="60">
</template>
</el-table-column>
<el-table-column align="center" label="商品名称" prop="name"/>
<el-table-column align="center" label="商品介绍" prop="brief"/>
<el-table-column align="center" label="操作" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</div>
<el-dialog :visible.sync="addVisiable" title="添加商品">
<div class="search">
<el-input v-model="listQuery.goodsSn" clearable class="filter-item" style="width: 200px;" placeholder="请输入商品编号"/>
<el-input v-model="listQuery.name" clearable class="filter-item" style="width: 200px;" placeholder="请输入商品名称"/>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
<el-table v-loading="listLoading" :data="list" element-loading-text="正在查询中。。。" border fit highlight-current-row @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"/>
<el-table-column align="center" label="商品ID" prop="id"/>
<el-table-column align="center" property="picUrl" label="图片">
<template slot-scope="scope">
<img :src="scope.row.picUrl" width="40">
</template>
</el-table-column>
<el-table-column align="center" label="商品名称" prop="name"/>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="addVisiable = false">取消</el-button>
<el-button type="primary" @click="confirmAdd">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<style>
.el-dialog {
width: 800px;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #20a0ff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 120px;
height: 120px;
line-height: 120px;
text-align: center;
}
.avatar {
width: 145px;
height: 145px;
display: block;
}
</style>
<script>
import { readTopic, updateTopic } from '@/api/topic'
import { listGoods } from '@/api/goods'
import { createStorage, uploadPath } from '@/api/storage'
import BackToTop from '@/components/BackToTop'
import Editor from '@tinymce/tinymce-vue'
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
import { getToken } from '@/utils/auth'
export default {
name: 'TopicEdit',
components: { BackToTop, Editor, Pagination },
data() {
return {
uploadPath,
id: 0,
topic: {},
goodsList: [],
addVisiable: false,
list: [],
total: 0,
listLoading: false,
listQuery: {
page: 1,
limit: 5,
id: undefined,
name: undefined,
sort: 'add_time',
order: 'desc'
},
selectedlist: [],
rules: {
title: [
{ required: true, message: '专题标题不能为空', trigger: 'blur' }
],
subtitle: [
{ required: true, message: '专题子标题不能为空', trigger: 'blur' }
],
content: [
{ required: true, message: '专题内容不能为空', trigger: 'blur' }
],
price: [
{ required: true, message: '专题低价不能为空', trigger: 'blur' }
]
},
editorInit: {
language: 'zh_CN',
convert_urls: false,
height: 500,
plugins: [
'advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount'
],
toolbar: [
'searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample',
'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen'
],
images_upload_handler: function(blobInfo, success, failure) {
const formData = new FormData()
formData.append('file', blobInfo.blob())
createStorage(formData)
.then(res => {
success(res.data.data.url)
})
.catch(() => {
failure('上传失败,请重新上传')
})
}
}
}
},
computed: {
headers() {
return {
'X-Litemall-Admin-Token': getToken()
}
}
},
created() {
if (this.$route.query.id == null) {
return
}
this.id = this.$route.query.id
this.getTopic()
},
methods: {
getTopic() {
this.listLoading = true
readTopic({ id: this.id })
.then(response => {
this.topic = response.data.data.topic
this.goodsList = response.data.data.goodsList
this.listLoading = false
})
.catch(() => {
this.topic = {}
this.goodsList = []
this.listLoading = false
})
},
getList() {
this.listLoading = true
listGoods(this.listQuery).then(response => {
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
}).catch(() => {
this.list = []
this.total = 0
this.listLoading = false
})
},
handleFilter() {
this.listQuery.page = 1
this.getList()
},
handleSelectionChange(val) {
this.selectedlist = val
},
uploadPicUrl: function(response) {
this.topic.picUrl = response.data.url
},
handleCreate() {
this.listQuery = {
page: 1,
limit: 5,
id: undefined,
name: undefined,
sort: 'add_time',
order: 'desc'
}
this.list = []
this.total = 0
this.selectedlist = []
this.addVisiable = true
},
confirmAdd() {
const newGoodsIds = []
const newGoodsList = []
this.selectedlist.forEach(item => {
const id = item.id
let found = false
this.topic.goods.forEach(goodsId => {
if (id === goodsId) {
found = true
}
})
if (!found) {
newGoodsIds.push(id)
newGoodsList.push(item)
}
})
if (newGoodsIds.length > 0) {
this.topic.goods = this.topic.goods.concat(newGoodsIds)
this.goodsList = this.goodsList.concat(newGoodsList)
}
this.addVisiable = false
},
handleDelete(row) {
for (var index = 0; index < this.topic.goods.length; index++) {
if (row.id === this.topic.goods[index]) {
this.topic.goods.splice(index, 1)
}
}
for (var index2 = 0; index2 < this.goodsList.length; index2++) {
if (row.id === this.goodsList[index2].id) {
this.goodsList.splice(index2, 1)
}
}
},
handleCancel() {
this.$router.push({ path: '/promotion/topic' })
},
handleConfirm() {
this.$refs['topic'].validate(valid => {
if (valid) {
updateTopic(this.topic).then(response => {
this.$router.push({ path: '/promotion/topic' })
})
.catch(response => {
this.$notify.error({
title: '失败',
message: response.data.errmsg
})
})
}
})
}
}
}
</script>
<script>
export default {
beforeCreate() {
created() {
const { params, query } = this.$route
const { path } = params
this.$router.replace({ path: '/' + path, query })
......
......@@ -162,7 +162,7 @@ export default {
roleOptions()
.then(response => {
this.roleOptions = response.data.data
this.roleOptions = response.data.data.list
})
},
methods: {
......@@ -178,7 +178,7 @@ export default {
this.listLoading = true
listAdmin(this.listQuery)
.then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
})
......
......@@ -79,7 +79,7 @@ export default {
this.listLoading = true
listLog(this.listQuery)
.then(response => {
this.list = response.data.data.items
this.list = response.data.data.list
this.total = response.data.data.total
this.listLoading = false
})
......
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