Commit 8aeef4e0 authored by gu-jinli1118's avatar gu-jinli1118
Browse files

20230831

parent 646116b0
Pipeline #31 failed with stages
in 0 seconds
export default {
namespaced: true,
state: {
id: 0,
name: ''
},
mutations: {
updateId (state, id) {
state.id = id
},
updateName (state, name) {
state.name = name
}
}
}
import CryptoJS from 'crypto-js'
// 加密
const keyStr = '-mall4j-password' // 解密用的key
export function encrypt(word){
const time = Date.now();
const key = CryptoJS.enc.Utf8.parse(keyStr);
const srcs = CryptoJS.enc.Utf8.parse(time + word); // 加密方式: 时间戳 + 密文
const encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
return encrypted.toString();
}
// 防抖 防止表单重复提交
export const Debounce = (fn, t) => {
let delay = t || 300
let timer
return function () {
let args = arguments
if (timer) {
clearTimeout(timer)
}
let callNow = !timer
timer = setTimeout(() => {
timer = null
}, delay)
if (callNow) fn.apply(this, args)
}
}
import Vue from 'vue'
import axios from 'axios'
import router from '@/router'
import qs from 'qs'
import merge from 'lodash/merge'
import { clearLoginInfo } from '@/utils'
import { Message } from 'element-ui'
const http = axios.create({
timeout: 1000 * 30,
withCredentials: true,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
})
/**
* 请求拦截
*/
http.interceptors.request.use(config => {
config.headers['Authorization'] = Vue.cookie.get('Authorization') // 请求头带上token
return config
}, error => {
return Promise.reject(error)
})
/**
* 响应拦截
*/
http.interceptors.response.use(response => {
// blob 格式处理
if (response.request.responseType === 'blob') {
return response
}
const res = response.data
// 00000 请求成功
if (res.code === '00000') {
return res
}
// A00001 用于直接显示提示用户的错误,内容由输入决定
if (res.code === 'A00001') {
Message({
message: res.msg || 'Error',
type: 'error',
duration: 1.5 * 1000
})
return Promise.reject(res)
}
// A00002 用于直接显示提示系统的成功,内容由输入决定
if (res.code === 'A00002') {
Message({
message: res.msg,
type: 'success',
duration: 1.5 * 1000
})
}
// A00004 未授权
if (res.code === 'A00004') {
clearLoginInfo()
router.push({ name: 'login' })
}
// A00005 服务器异常
if (res.code === 'A00005') {
console.error('============== 请求异常 ==============')
console.log('接口地址: ', response.config.url.replace(process.env.VUE_APP_BASE_API, ''))
console.log('异常信息: ', res)
console.error('============== 请求异常 end ==========')
Message({
message: '服务器出了点小差,请稍后再试',
type: 'error',
duration: 1.5 * 1000,
customClass: 'element-error-message-zindex'
})
return Promise.reject(res)
}
if (res.code === 'A00014') {
Message({
message: res.msg,
type: 'error',
duration: 1.5 * 1000
})
return Promise.reject(res)
}
}, error => {
switch (error.response.status) {
case 400:
Message({
message: error.response.data,
type: 'error',
duration: 1500,
customClass: 'element-error-message-zindex'
})
break
case 401:
clearLoginInfo()
router.push({ name: 'login' })
break
case 405:
Message({
message: 'http请求方式有误',
type: 'error',
duration: 1500,
customClass: 'element-error-message-zindex'
})
break
case 500:
Message({
message: '服务器出了点小差,请稍后再试',
type: 'error',
duration: 1500,
customClass: 'element-error-message-zindex'
})
break
case 501:
Message({
message: '服务器不支持当前请求所需要的某个功能',
type: 'error',
duration: 1500,
customClass: 'element-error-message-zindex'
})
break
}
return Promise.reject(error)
})
/**
* 请求地址处理
* @param {*} actionName action方法名称
*/
http.adornUrl = (actionName) => {
// 非生产环境 && 开启代理, 接口前缀统一使用[/proxyApi/]前缀做代理拦截!
return (process.env.NODE_ENV !== 'production' && process.env.OPEN_PROXY ? '/proxyApi' : process.env.VUE_APP_BASE_API) + actionName
}
/**
* get请求参数处理
* @param {*} params 参数对象
* @param {*} openDefultParams 是否开启默认参数?
*/
http.adornParams = (params = {}, openDefultParams = true) => {
var defaults = {
't': new Date().getTime()
}
return openDefultParams ? merge(defaults, params) : params
}
/**
* post请求数据处理
* @param {*} data 数据对象
* @param {*} openDefultdata 是否开启默认数据?
* @param {*} contentType 数据格式
* json: 'application/json; charset=utf-8'
* form: 'application/x-www-form-urlencoded; charset=utf-8'
*/
http.adornData = (data = {}, openDefultdata = true, contentType = 'json') => {
var defaults = {
't': new Date().getTime()
}
data = openDefultdata ? merge(defaults, data) : data
return contentType === 'json' ? JSON.stringify(data) : qs.stringify(data)
}
export default http
import Vue from 'vue'
import router from '@/router'
import store from '@/store'
/**
* 获取uuid
*/
export function getUUID () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16)
})
}
/**
* 是否有权限
* @param {*} key
*/
export function isAuth (key) {
let authorities = JSON.parse(sessionStorage.getItem('authorities') || '[]')
if (authorities.length) {
for (const i in authorities) {
const element = authorities[i]
if (element === key) {
return true
}
}
}
return false
}
/**
* 树形数据转换
* @param {*} data
* @param {*} id
* @param {*} pid
*/
export function treeDataTranslate (data, id = 'id', pid = 'parentId') {
var res = []
var temp = {}
for (var i = 0; i < data.length; i++) {
temp[data[i][id]] = data[i]
}
for (var k = 0; k < data.length; k++) {
if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) {
if (!temp[data[k][pid]]['children']) {
temp[data[k][pid]]['children'] = []
}
if (!temp[data[k][pid]]['_level']) {
temp[data[k][pid]]['_level'] = 1
}
data[k]['_level'] = temp[data[k][pid]]._level + 1
temp[data[k][pid]]['children'].push(data[k])
} else {
res.push(data[k])
}
}
return res
}
/**
* 将数组中的parentId列表取出,倒序排列
* @param {*} data
* @param {*} id
* @param {*} pid
*/
export function idList (data, val, id = 'id', children = 'children') {
let res = []
idListFromTree(data, val, res, id)
return res
}
/**
* @param {*} data
* @param {*} id
* @param {*} pid
*/
function idListFromTree (data, val, res = [], id = 'id', children = 'children') {
for (let i = 0; i < data.length; i++) {
const element = data[i]
if (element[children]) {
if (idListFromTree(element[children], val, res, id, children)) {
res.push(element[id])
return true
}
}
if (element[id] === val) {
res.push(element[id])
return true
}
}
}
/**
* 清除登录信息
*/
export function clearLoginInfo () {
Vue.cookie.delete('Authorization')
router.options.isAddDynamicMenuRoutes = false
}
/**
* 邮箱
* @param {*} s
*/
export function isEmail (s) {
return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s)
}
/**
* 手机号码
* @param {*} s
*/
export function isMobile (s) {
return /^1[0-9]{10}$/.test(s)
}
/**
* 电话号码
* @param {*} s
*/
export function isPhone (s) {
return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s)
}
/**
* URL地址
* @param {*} s
*/
export function isURL (s) {
return /^http[s]?:\/\/.*/.test(s)
}
<template>
<div class="site-wrapper site-page--not-found">
<div class="site-content__wrapper">
<div class="site-content">
<h2 class="not-found-title">400</h2>
<p class="not-found-desc">抱歉!您访问的页面<em>失联</em>啦 ...</p>
<el-button @click="$router.go(-1)">返回上一页</el-button>
<el-button type="primary" class="not-found-btn-gohome" @click="$router.push({ name: 'home' })">进入首页</el-button>
</div>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss">
.site-wrapper.site-page--not-found {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: hidden;
.site-content__wrapper {
padding: 0;
margin: 0;
background-color: #fff;
}
.site-content {
position: fixed;
top: 15%;
left: 50%;
z-index: 2;
padding: 30px;
text-align: center;
transform: translate(-50%, 0);
}
.not-found-title {
margin: 20px 0 15px;
font-size: 10em;
font-weight: 400;
color: rgb(55, 71, 79);
}
.not-found-desc {
margin: 0 0 30px;
font-size: 26px;
text-transform: uppercase;
color: rgb(118, 131, 143);
> em {
font-style: normal;
color: #ee8145;
}
}
.not-found-btn-gohome {
margin-left: 30px;
}
}
</style>
<template>
<div class="mod-home">
<p>一个基于spring boot、spring oauth2.0、mybatis、redis的轻量级、前后端分离、拥有完整sku和下单流程的完全开源商城</p>
<p>&nbsp;</p>
<p>该项目仅供学习参考、可供个人学习使用、如需商用联系作者进行授权,否则必将追究法律责任</p>
<p>&nbsp;</p>
<h2>前言</h2>
<p>
<code>mall4j商城</code>项目致力于为中小企业打造一个完整、易于维护的开源的电商系统,采用现阶段流行技术实现。后台管理系统包含商品管理、订单管理、运费模板、规格管理、会员管理、运营管理、内容管理、统计报表、权限管理、设置等模块。
</p>
<p>&nbsp;</p>
<h2>技术选型</h2>
<figure>
<table border="1"
cellspacing="0"
cellpadding="5px">
<thead>
<tr>
<th>技术</th>
<th>版本</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Spring Boot</td>
<td>3.0.4</td>
<td>MVC核心框架</td>
</tr>
<tr>
<td>MyBatis</td>
<td>3.5.0</td>
<td>ORM框架</td>
</tr>
<tr>
<td>MyBatisPlus</td>
<td>3.5.3.1</td>
<td>基于mybatis,使用lambda表达式的</td>
</tr>
<tr>
<td>Swagger-UI</td>
<td>4.0.0</td>
<td>文档生产工具</td>
</tr>
<tr>
<td>redisson</td>
<td>3.19.3</td>
<td>对redis进行封装、集成分布式锁等</td>
</tr>
<tr>
<td>hikari</td>
<td>3.2.0</td>
<td>数据库连接池</td>
</tr>
<tr>
<td>log4j2</td>
<td>2.17.2</td>
<td>更快的log日志工具</td>
</tr>
<tr>
<td>lombok</td>
<td>1.18.8</td>
<td>简化对象封装工具</td>
</tr>
<tr>
<td>hutool</td>
<td>5.8.15</td>
<td>更适合国人的java工具集</td>
</tr>
<tr>
<td>xxl-job</td>
<td>2.3.1</td>
<td>定时任务</td>
</tr>
</tbody>
</table>
</figure>
<p>&nbsp;</p>
<h2>部署教程</h2>
<p>&nbsp;</p>
<h3>1.开发环境</h3>
<figure>
<table border="1"
cellspacing="0"
cellpadding="5px">
<thead>
<tr>
<th>工具</th>
<th>版本</th>
</tr>
</thead>
<tbody>
<tr>
<td>jdk</td>
<td>17</td>
</tr>
<tr>
<td>mysql</td>
<td>5.7+</td>
</tr>
<tr>
<td>redis</td>
<td>3.2+</td>
</tr>
</tbody>
</table>
</figure>
<h3>2.启动</h3>
<ul>
<li>推荐使用idea,安装lombok插件,使用idea导入maven项目</li>
<li>
将shop.sql导入到mysql中,修改
<code>application-dev.yml</code>更改 datasource.url、user、password
</li>
<li>启动redis</li>
<li>
通过
<code>WebApplication</code>启动项目后台接口,
<code>ApiApplication</code> 启动项目前端接口
</li>
</ul>
<p>&nbsp;</p>
</div>
</template>
<script>
export default {}
</script>
<style>
.mod-home {
line-height: 1.5;
}
</style>
<template>
<div class="login">
<div class="login-box">
<div class="top">
<div class="logo"><img src="~@/assets/img/login-logo.png"
alt=""></div>
</div>
<div class="mid">
<el-form :model="dataForm"
:rules="dataRule"
ref="dataForm"
@keyup.enter.native="dataFormSubmit()"
status-icon>
<el-form-item prop="userName">
<el-input class="info"
v-model="dataForm.userName"
placeholder="帐号"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input class="info"
v-model="dataForm.password"
type="password"
placeholder="密码"></el-input>
</el-form-item>
<!-- <el-form-item prop="captcha">
<el-row :gutter="20">
<el-col :span="14">
<el-input v-model="dataForm.captcha"
placeholder="验证码">
</el-input>
</el-col>
<el-col :span="10"
class="login-captcha">
<img :src="captchaPath"
@click="getCaptcha()"
alt="">
</el-col>
</el-row>
</el-form-item> -->
<el-form-item>
<div class="item-btn"><input type="button"
value="登录"
@click="dataFormSubmit()"></div>
</el-form-item>
</el-form>
</div>
<div class="bottom">Copyright © 2019 广州市蓝海创新科技有限公司</div>
</div>
<Verify
ref="verify"
:captcha-type="'blockPuzzle'"
:img-size="{width:'400px',height:'200px'}"
@success="login"
/>
</div>
</template>
<script>
import { getUUID } from '@/utils'
import Verify from '@/components/verifition/Verify'
import { encrypt } from '@/utils/crypto'
export default {
components: {
Verify
},
data () {
return {
dataForm: {
userName: '',
password: '',
uuid: '',
captcha: ''
},
dataRule: {
userName: [
{ required: true, message: '帐号不能为空', trigger: 'blur' }
],
password: [
{ required: true, message: '密码不能为空', trigger: 'blur' }
],
captcha: [
{ required: true, message: '验证码不能为空', trigger: 'blur' }
]
},
captchaPath: ''
}
},
beforeDestroy () {
document.removeEventListener('keyup', this.handerKeyup)
},
created () {
this.getCaptcha()
document.addEventListener('keyup', this.handerKeyup)
},
methods: {
handerKeyup (e) {
var keycode = document.all ? event.keyCode : e.which
if (keycode === 13) {
this.dataFormSubmit()
}
},
// 提交表单
dataFormSubmit () {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.$refs.verify.show()
}
})
},
login (verifyResult) {
if (this.isSubmit) {
return
}
this.isSubmit = true
this.$http({
url: this.$http.adornUrl('/adminLogin'),
method: 'post',
data: this.$http.adornData({
'userName': this.dataForm.userName,
'passWord': encrypt(this.dataForm.password),
'captchaVerification': verifyResult.captchaVerification
})
}).then(({ data }) => {
this.$cookie.set('Authorization', data.accessToken)
this.$router.replace({ name: 'home' })
}).catch(() => {
this.isSubmit = false
})
},
// dataFormSubmit () {
// this.$refs['dataForm'].validate((valid) => {
// if (valid) {
// this.$http({
// url: this.$http.adornUrl('/login?grant_type=admin'),
// method: 'post',
// data: this.$http.adornData({
// 'principal': this.dataForm.userName,
// 'credentials': this.dataForm.password,
// 'sessionUUID': this.dataForm.uuid,
// 'imageCode': this.dataForm.captcha
// })
// }).then(({ data }) => {
// this.$cookie.set('Authorization', 'bearer' + data.access_token)
// this.$router.replace({ name: 'home' })
// }).catch(() => {
// this.getCaptcha()
// })
// }
// })
// },
// 获取验证码
getCaptcha () {
this.dataForm.uuid = getUUID()
this.captchaPath = this.$http.adornUrl(`/captcha.jpg?uuid=${this.dataForm.uuid}`)
}
}
}
</script>
<style lang="scss">
.login {
width: 100%;
height: 100%;
background: url(~@/assets/img/login-bg.png) no-repeat;
background-size: cover;
position: fixed;
}
.login .login-box {
position: absolute;
left: 50%;
transform: translateX(-50%);
height: 100%;
padding-top: 10%;
}
.login .login-box .top {
margin-bottom: 30px;
text-align: center;
}
.login .login-box .top .logo {
font-size: 0;
max-width: 50%;
margin: 0 auto;
}
.login .login-box .top .company {
font-size: 16px;
margin-top: 10px;
}
.login .login-box .mid {
font-size: 14px;
}
.login .login-box .mid .item-btn {
margin-top: 20px;
}
.login .login-box .mid .item-btn input {
border: 0;
width: 100%;
height: 40px;
box-shadow: 0;
background: #1f87e8;
color: #fff;
border-radius: 3px;
}
.info {
width: 410px;
}
.login-captcha {
height: 40px;
}
.login .login-box .bottom {
position: absolute;
bottom: 10%;
width: 100%;
color: #999;
font-size: 12px;
text-align: center;
}
</style>
<template>
<main class="site-content" :class="{ 'site-content--tabs': $route.meta.isTab }">
<!-- 主入口标签页 s -->
<el-tabs
v-if="$route.meta.isTab"
v-model="mainTabsActiveName"
:closable="true"
@tab-click="selectedTabHandle"
@tab-remove="removeTabHandle">
<el-dropdown class="site-tabs__tools" :show-timeout="0">
<i class="el-icon-arrow-down el-icon--right"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="tabsCloseCurrentHandle">关闭当前标签页</el-dropdown-item>
<el-dropdown-item @click.native="tabsCloseOtherHandle">关闭其它标签页</el-dropdown-item>
<el-dropdown-item @click.native="tabsCloseAllHandle">关闭全部标签页</el-dropdown-item>
<el-dropdown-item @click.native="tabsRefreshCurrentHandle">刷新当前标签页</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-tab-pane
v-for="item in mainTabs"
:key="item.name"
:label="item.title"
:name="item.name">
<el-card :body-style="siteContentViewHeight">
<iframe
v-if="item.type === 'iframe'"
:src="item.iframeUrl"
width="100%" height="100%" frameborder="0" scrolling="yes">
</iframe>
<keep-alive v-else>
<router-view v-if="item.name === mainTabsActiveName" />
</keep-alive>
</el-card>
</el-tab-pane>
</el-tabs>
<!-- 主入口标签页 e -->
<el-card v-else :body-style="siteContentViewHeight">
<keep-alive>
<router-view />
</keep-alive>
</el-card>
</main>
</template>
<script>
import { isURL } from '@/utils/validate'
export default {
data () {
return {
}
},
computed: {
documentClientHeight: {
get () { return this.$store.state.common.documentClientHeight }
},
menuActiveName: {
get () { return this.$store.state.common.menuActiveName },
set (val) { this.$store.commit('common/updateMenuActiveName', val) }
},
mainTabs: {
get () { return this.$store.state.common.mainTabs },
set (val) { this.$store.commit('common/updateMainTabs', val) }
},
mainTabsActiveName: {
get () { return this.$store.state.common.mainTabsActiveName },
set (val) { this.$store.commit('common/updateMainTabsActiveName', val) }
},
siteContentViewHeight () {
var height = this.documentClientHeight - 50 - 30 - 2
if (this.$route.meta.isTab) {
height -= 40
return isURL(this.$route.meta.iframeUrl) ? { height: height + 'px' } : { minHeight: height + 'px' }
}
return { minHeight: height + 'px' }
}
},
methods: {
// tabs, 选中tab
selectedTabHandle (tab) {
tab = this.mainTabs.filter(item => item.name === tab.name)
if (tab.length >= 1) {
this.$router.push({ name: tab[0].name })
}
},
// tabs, 删除tab
removeTabHandle (tabName) {
this.mainTabs = this.mainTabs.filter(item => item.name !== tabName)
if (this.mainTabs.length >= 1) {
// 当前选中tab被删除
if (tabName === this.mainTabsActiveName) {
this.$router.push({ name: this.mainTabs[this.mainTabs.length - 1].name }, () => {
this.mainTabsActiveName = this.$route.name
})
}
} else {
this.menuActiveName = ''
this.$router.push({ name: 'home' })
}
},
// tabs, 关闭当前
tabsCloseCurrentHandle () {
this.removeTabHandle(this.mainTabsActiveName)
},
// tabs, 关闭其它
tabsCloseOtherHandle () {
this.mainTabs = this.mainTabs.filter(item => item.name === this.mainTabsActiveName)
},
// tabs, 关闭全部
tabsCloseAllHandle () {
this.mainTabs = []
this.menuActiveName = ''
this.$router.push({ name: 'home' })
},
// tabs, 刷新当前
tabsRefreshCurrentHandle () {
var tempTabName = this.mainTabsActiveName
this.removeTabHandle(tempTabName)
this.$nextTick(() => {
this.$router.push({ name: tempTabName })
})
}
}
}
</script>
<template>
<el-dialog
title="修改密码"
:visible.sync="visible"
:append-to-body="true">
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="80px">
<el-form-item label="账号">
<span>{{ userName }}</span>
</el-form-item>
<el-form-item label="原密码" prop="password">
<el-input type="password" v-model="dataForm.password"></el-input>
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input type="password" v-model="dataForm.newPassword"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword">
<el-input type="password" v-model="dataForm.confirmPassword"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="dataFormSubmit()">确定</el-button>
</span>
</el-dialog>
</template>
<script>
import { clearLoginInfo } from '@/utils'
import { Debounce } from '@/utils/debounce'
import { encrypt } from '@/utils/crypto'
export default {
data () {
var validateConfirmPassword = (rule, value, callback) => {
if (this.dataForm.newPassword !== value) {
callback(new Error('确认密码与新密码不一致'))
} else {
callback()
}
}
return {
visible: false,
dataForm: {
password: '',
newPassword: '',
confirmPassword: ''
},
dataRule: {
password: [
{ required: true, message: '原密码不能为空', trigger: 'blur' }
],
newPassword: [
{ required: true, message: '新密码不能为空', trigger: 'blur' }
],
confirmPassword: [
{ required: true, message: '确认密码不能为空', trigger: 'blur' },
{ validator: validateConfirmPassword, trigger: 'blur' }
]
}
}
},
computed: {
userName: {
get () { return this.$store.state.user.name }
},
mainTabs: {
get () { return this.$store.state.common.mainTabs },
set (val) { this.$store.commit('common/updateMainTabs', val) }
}
},
methods: {
// 初始化
init () {
this.visible = true
this.$nextTick(() => {
this.$refs['dataForm'].resetFields()
})
},
// 表单提交
dataFormSubmit: Debounce(function () {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.$http({
url: this.$http.adornUrl('/sys/user/password'),
method: 'post',
data: this.$http.adornData({
'password': encrypt(this.dataForm.password),
'newPassword': encrypt(this.dataForm.newPassword)
})
}).then(({data}) => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.visible = false
this.$nextTick(() => {
this.mainTabs = []
clearLoginInfo()
this.$router.replace({ name: 'login' })
})
}
})
})
}
})
})
}
}
</script>
<template>
<nav class="site-navbar" :class="'site-navbar--' + navbarLayoutType">
<div class="site-navbar__header">
<h1 class="site-navbar__brand" @click="$router.push({ name: 'home' })">
<a class="site-navbar__brand-lg" href="javascript:;">mall4j建站后台</a>
<a class="site-navbar__brand-mini" href="javascript:;">mall4j</a>
</h1>
</div>
<div class="site-navbar__body clearfix">
<el-menu
class="site-navbar__menu"
mode="horizontal">
<el-menu-item class="site-navbar__switch" index="0" @click="sidebarFold = !sidebarFold">
<icon-svg name="zhedie"></icon-svg>
</el-menu-item>
</el-menu>
<el-menu
class="site-navbar__menu site-navbar__menu--right"
mode="horizontal">
<el-menu-item class="site-navbar__avatar" index="3">
<el-dropdown :show-timeout="0" placement="bottom">
<span class="el-dropdown-link">
{{ userName }}
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="updatePasswordHandle()">修改密码</el-dropdown-item>
<el-dropdown-item @click.native="logoutHandle()">退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-menu-item>
</el-menu>
</div>
<!-- 弹窗, 修改密码 -->
<update-password v-if="updatePassowrdVisible" ref="updatePassowrd"></update-password>
</nav>
</template>
<script>
import UpdatePassword from './main-navbar-update-password'
import { clearLoginInfo } from '@/utils'
export default {
data () {
return {
updatePassowrdVisible: false
}
},
components: {
UpdatePassword
},
computed: {
navbarLayoutType: {
get () { return this.$store.state.common.navbarLayoutType }
},
sidebarFold: {
get () { return this.$store.state.common.sidebarFold },
set (val) { this.$store.commit('common/updateSidebarFold', val) }
},
mainTabs: {
get () { return this.$store.state.common.mainTabs },
set (val) { this.$store.commit('common/updateMainTabs', val) }
},
userName: {
get () { return this.$store.state.user.name }
}
},
methods: {
// 修改密码
updatePasswordHandle () {
this.updatePassowrdVisible = true
this.$nextTick(() => {
this.$refs.updatePassowrd.init()
})
},
// 退出
logoutHandle () {
this.$confirm(`确定进行[退出]操作?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$http({
url: this.$http.adornUrl('/logOut'),
method: 'post',
data: this.$http.adornData()
}).then(({data}) => {
clearLoginInfo()
this.$router.push({ name: 'login' })
})
}).catch(() => {})
}
}
}
</script>
<template>
<el-submenu
v-if="menu.list && menu.list.length >= 1"
:index="menu.menuId + ''"
:popper-class="'site-sidebar--' + sidebarLayoutSkin + '-popper'">
<template slot="title">
<icon-svg :name="menu.icon || ''" class="site-sidebar__menu-icon"></icon-svg>
<span>{{ menu.name }}</span>
</template>
<sub-menu
v-for="item in menu.list"
:key="item.menuId"
:menu="item"
:dynamicMenuRoutes="dynamicMenuRoutes">
</sub-menu>
</el-submenu>
<el-menu-item v-else :index="menu.menuId + ''" @click="gotoRouteHandle(menu)">
<icon-svg :name="menu.icon || ''" class="site-sidebar__menu-icon"></icon-svg>
<span>{{ menu.name }}</span>
</el-menu-item>
</template>
<script>
import SubMenu from './main-sidebar-sub-menu'
export default {
name: 'sub-menu',
props: {
menu: {
type: Object,
required: true
},
dynamicMenuRoutes: {
type: Array,
required: true
}
},
components: {
SubMenu
},
computed: {
sidebarLayoutSkin: {
get () { return this.$store.state.common.sidebarLayoutSkin }
}
},
methods: {
// 通过menuId与动态(菜单)路由进行匹配跳转至指定路由
gotoRouteHandle (menu) {
var route = this.dynamicMenuRoutes.filter(item => item.meta.menuId === menu.menuId)
if (route.length >= 1) {
this.$router.push({ name: route[0].name })
}
}
}
}
</script>
<template>
<aside class="site-sidebar" :class="'site-sidebar--' + sidebarLayoutSkin">
<div class="site-sidebar__inner">
<el-menu
:default-active="menuActiveName || 'home'"
:collapse="sidebarFold"
:collapseTransition="false"
class="site-sidebar__menu">
<el-menu-item index="home" @click="$router.push({ name: 'home' })">
<icon-svg name="shouye" class="site-sidebar__menu-icon"></icon-svg>
<span slot="title">首页</span>
</el-menu-item>
<sub-menu
v-for="menu in menuList"
:key="menu.menuId"
:menu="menu"
:dynamicMenuRoutes="dynamicMenuRoutes">
</sub-menu>
</el-menu>
</div>
</aside>
</template>
<script>
import SubMenu from './main-sidebar-sub-menu'
import { isURL } from '@/utils/validate'
export default {
data () {
return {
dynamicMenuRoutes: []
}
},
components: {
SubMenu
},
computed: {
sidebarLayoutSkin: {
get () { return this.$store.state.common.sidebarLayoutSkin }
},
sidebarFold: {
get () { return this.$store.state.common.sidebarFold }
},
menuList: {
get () { return this.$store.state.common.menuList },
set (val) { this.$store.commit('common/updateMenuList', val) }
},
menuActiveName: {
get () { return this.$store.state.common.menuActiveName },
set (val) { this.$store.commit('common/updateMenuActiveName', val) }
},
mainTabs: {
get () { return this.$store.state.common.mainTabs },
set (val) { this.$store.commit('common/updateMainTabs', val) }
},
mainTabsActiveName: {
get () { return this.$store.state.common.mainTabsActiveName },
set (val) { this.$store.commit('common/updateMainTabsActiveName', val) }
}
},
watch: {
$route: 'routeHandle'
},
created () {
this.menuList = JSON.parse(sessionStorage.getItem('menuList') || '[]')
this.dynamicMenuRoutes = JSON.parse(sessionStorage.getItem('dynamicMenuRoutes') || '[]')
this.routeHandle(this.$route)
},
methods: {
// 路由操作
routeHandle (route) {
if (route.meta.isTab) {
// tab选中, 不存在先添加
var tab = this.mainTabs.filter(item => item.name === route.name)[0]
if (!tab) {
if (route.meta.isDynamic) {
route = this.dynamicMenuRoutes.filter(item => item.name === route.name)[0]
if (!route) {
return console.error('未能找到可用标签页!')
}
}
tab = {
menuId: route.meta.menuId || route.name,
name: route.name,
title: route.meta.title,
type: isURL(route.meta.iframeUrl) ? 'iframe' : 'module',
iframeUrl: route.meta.iframeUrl || ''
}
this.mainTabs = this.mainTabs.concat(tab)
}
this.menuActiveName = tab.menuId + ''
this.mainTabsActiveName = tab.name
}
}
}
}
</script>
<template>
<div
class="site-wrapper"
:class="{ 'site-sidebar--fold': sidebarFold }"
v-loading.fullscreen.lock="loading"
element-loading-text="拼命加载中">
<template v-if="!loading">
<main-navbar />
<main-sidebar />
<div class="site-content__wrapper" :style="{ 'min-height': documentClientHeight + 'px' }">
<main-content />
</div>
</template>
</div>
</template>
<script>
import MainNavbar from './main-navbar'
import MainSidebar from './main-sidebar'
import MainContent from './main-content'
export default {
data () {
return {
loading: true
}
},
components: {
MainNavbar,
MainSidebar,
MainContent
},
computed: {
documentClientHeight: {
get () { return this.$store.state.common.documentClientHeight },
set (val) { this.$store.commit('common/updateDocumentClientHeight', val) }
},
sidebarFold: {
get () { return this.$store.state.common.sidebarFold }
},
userId: {
get () { return this.$store.state.user.id },
set (val) { this.$store.commit('user/updateId', val) }
},
userName: {
get () { return this.$store.state.user.name },
set (val) { this.$store.commit('user/updateName', val) }
}
},
created () {
this.getUserInfo()
},
mounted () {
this.resetDocumentClientHeight()
},
methods: {
// 重置窗口可视高度
resetDocumentClientHeight () {
this.documentClientHeight = document.documentElement['clientHeight']
window.onresize = () => {
this.documentClientHeight = document.documentElement['clientHeight']
}
},
// 获取当前管理员信息
getUserInfo () {
this.$http({
url: this.$http.adornUrl('/sys/user/info'),
method: 'get',
params: this.$http.adornParams()
}).then(({data}) => {
this.loading = false
this.userId = data.userId
this.userName = data.username
})
}
}
}
</script>
<template>
<div class="mod-index-img">
<el-dialog :title="!dataForm.imgId ? '新增' : '修改'"
:close-on-click-modal="false"
:visible.sync="visible">
<el-form :model="dataForm"
ref="dataForm"
:rules="dataRule"
label-width="100px">
<el-form-item label="轮播图片" prop="imgUrl">
<pic-upload v-model="dataForm.imgUrl"></pic-upload>
</el-form-item>
<el-form-item label="顺序"
prop="seq"
:rules="[
{ required: false, pattern: /\s\S+|S+\s|\S/, message: '请输入正确的顺序', trigger: 'blur' }
]">
<el-input v-model="dataForm.seq"></el-input>
</el-form-item>
<el-form-item label="状态"
prop="status">
<el-radio-group v-model="dataForm.status">
<el-radio :label="0">禁用</el-radio>
<el-radio :label="1">正常</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="类型">
<el-radio-group v-model="dataForm.type"
@change="deleteRelation">
<el-radio :label="-1"></el-radio>
<el-radio :label="0">商品</el-radio>
<!-- <el-radio :label="1">店铺</el-radio>
<el-radio :label="2">活动</el-radio> -->
</el-radio-group>
<div v-if="dataForm.relation!=null">
<el-card :body-style="{ padding: '0px' }"
style="height: 160px;width: 120px">
<img :src="card.pic"
style="height:104px;width:100%">
<div class="card-prod-bottom">
<span class="card-prod-name">{{card.name}}</span>
<el-button type="text"
class="card-prod-name-button"
@click="deleteRelation">删除</el-button>
</div>
</el-card>
</div>
<div v-if="dataForm.relation==null">
<el-button @click="addProd"
v-if=" dataForm.type == 0"
size="small">选择商品</el-button>
<!-- <el-button @click="addShop"
v-if=" dataForm.type == 1"
size="small">选择店铺</el-button>
<el-button @click="addActivity"
v-if="dataForm.type == 2"
size="small">选择活动</el-button> -->
</div>
</el-form-item>
<el-form-item>
<el-button type="primary"
@click="dataFormSubmit()">确定</el-button>
</el-form-item>
</el-form>
</el-dialog>
<!-- 商品选择弹窗-->
<prods-select v-if="prodsSelectVisible"
ref="prodsSelect"
:isSingle="true"
@refreshSelectProds="selectCouponProds"></prods-select>
</div>
</template>
<script>
import PicUpload from '@/components/pic-upload'
import ProdsSelect from '@/components/prods-select'
import { Debounce } from '@/utils/debounce'
export default {
data () {
return {
dataForm: {
status: 1,
des: '',
imgUrl: '',
seq: 0,
imgId: 0,
type: -1,
relation: null
},
dataRule: {
imgUrl: [
{required: true, message: '轮播图片不能为空', trigger: 'blur'}
]
},
// 关联数据
card: {
id: 0,
pic: '',
name: '',
realData: {
prod: [],
shop: [],
activity: []
}
},
page: {
total: 0, // 总页数
currentPage: 1, // 当前页数
pageSize: 10 // 每页显示多少条
},
prodsSelectVisible: false,
visible: false
}
},
components: {
PicUpload,
ProdsSelect
},
methods: {
// 获取分类数据
init (id) {
this.visible = true
this.dataForm.imgId = id || 0
if (this.dataForm.imgId) {
// 获取产品数据
this.$http({
url: this.$http.adornUrl(`/admin/indexImg/info/${this.dataForm.imgId}`),
method: 'get',
params: this.$http.adornParams()
}).then(({ data }) => {
this.dataForm = data
if (data.relation) {
this.card.pic = data.pic
this.card.name = data.prodName
this.card.id = data.relation
}
})
} else {
this.$nextTick(() => {
this.$refs['dataForm'].resetFields()
this.dataForm.imgUrl = ''
this.relation = null
})
}
},
// 表单提交
dataFormSubmit: Debounce(function () {
this.$refs['dataForm'].validate((valid) => {
if (!valid) {
return
}
let param = this.dataForm
this.$http({
url: this.$http.adornUrl(`/admin/indexImg`),
method: param.imgId ? 'put' : 'post',
data: this.$http.adornData(param)
}).then(({ data }) => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.visible = false
this.$emit('refreshDataList', this.page)
}
})
})
})
}),
// 删除关联数据
deleteRelation () {
this.dataForm.relation = null
},
// 打开选择商品
addProd () {
this.prodsSelectVisible = true
this.$nextTick(() => {
this.$refs.prodsSelect.init(this.card.realData.prod)
})
},
// 添加指定商品
selectCouponProds (prods) {
this.card.realData.prods = prods
if (prods.length) {
let selectProd = prods[0]
this.dataForm.relation = selectProd.prodId
this.card.pic = selectProd.pic
this.card.name = selectProd.prodName
this.card.id = selectProd.prodId
} else {
this.card = {}
this.relation = null
}
},
addShop () {
alert('选择店铺')
},
addActivity () {
alert('选择活动')
}
}
}
</script>
<style lang="scss">
//card样式
.card-prod-bottom {
position: relative;
text-align: left;
.card-prod-name {
margin: auto;
padding: 0 6px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 118px;
display: inline-block;
}
.card-prod-name-button {
position: absolute;
top: 24px;
right: 10px;
}
}
</style>
<template>
<div class="mod-prod">
<avue-crud ref="crud"
:page="page"
:data="dataList"
:table-loading="dataListLoading"
:option="tableOption"
@search-change="searchChange"
@selection-change="selectionChange"
@on-load="getDataList">
<template slot="menuLeft">
<el-button type="primary"
icon="el-icon-plus"
size="small"
v-if="isAuth('admin:indexImg:save')"
@click.stop="addOrUpdateHandle()">新增</el-button>
<el-button type="danger"
@click="deleteHandle()"
size="small"
v-if="isAuth('admin:indexImg:delete')"
:disabled="dataListSelections.length <= 0">批量删除</el-button>
</template>
<template slot-scope="scope"
slot="imgUrl">
<img v-if="scope.row.imgUrl" :src="scope.row.imgUrl"
width="100"
height="100" />
<img v-else src="~@/assets/img/def.png"
width="100"
height="100" />
</template>
<template slot-scope="scope"
slot="menu">
<el-button type="primary"
icon="el-icon-edit"
size="small"
v-if="isAuth('admin:indexImg:update')"
@click="addOrUpdateHandle(scope.row.imgId)">修改</el-button>
<el-button type="danger"
icon="el-icon-delete"
size="small"
v-if="isAuth('admin:indexImg:delete')"
@click="deleteHandle(scope.row.imgId)">删除</el-button>
</template>
</avue-crud>
<!-- 弹窗, 新增 / 修改 -->
<add-or-update v-if="addOrUpdateVisible"
ref="addOrUpdate"
@refreshDataList="getDataList"></add-or-update>
</div>
</template>
<script>
import AddOrUpdate from './indexImg-add-or-update'
import { tableOption } from '@/crud/admin/indexImg'
export default {
data () {
return {
dataForm: {
indexImg: ''
},
dataList: [],
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false,
resourcesUrl: process.env.VUE_APP_RESOURCES_URL,
// 修改
tableOption: tableOption,
page: {
total: 0, // 总页数
currentPage: 1, // 当前页数
pageSize: 10 // 每页显示多少条
}
}
},
components: {
AddOrUpdate
},
methods: {
// 获取数据列表
getDataList (page, params, done) {
this.dataListLoading = true
this.$http({
url: this.$http.adornUrl('/admin/indexImg/page'),
method: 'get',
params: this.$http.adornParams(
Object.assign(
{
current: page == null ? this.page.currentPage : page.currentPage,
size: page == null ? this.page.pageSize : page.pageSize
},
params
)
)
}).then(({ data }) => {
data.records.forEach(item => {
item.imgUrl = item.imgUrl ? this.resourcesUrl + item.imgUrl : ''
})
this.dataList = data.records
this.page.total = data.total
this.dataListLoading = false
if (done) {
done()
}
})
},
// 新增 / 修改
addOrUpdateHandle (id) {
this.addOrUpdateVisible = true
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id)
})
},
// 删除
deleteHandle (id) {
var ids = id ? [id] : this.dataListSelections.map(item => {
return item.imgId
})
this.$confirm(`确定进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$http({
url: this.$http.adornUrl('/admin/indexImg'),
method: 'delete',
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.getDataList()
}
})
})
})
},
// 条件查询
searchChange (params, done) {
this.getDataList(this.page, params, done)
},
// 多选变化
selectionChange (val) {
this.dataListSelections = val
}
}
}
</script>
<template>
<el-dialog :title="!dataForm.id ? '新增' : '修改'"
:close-on-click-modal="false"
:visible.sync="visible">
<el-form :model="dataForm"
:rules="dataRule"
ref="dataForm"
@keyup.enter.native="dataFormSubmit()"
label-width="80px">
<el-form-item label="创建时间"
prop="createTime">
<el-date-picker v-model="dataForm.createTime"
type="datetime"
placeholder="选择日期"
value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker>
</el-form-item>
<el-form-item label="姓名"
prop="userName">
<el-input v-model="dataForm.userName"
placeholder="姓名"></el-input>
</el-form-item>
<el-form-item label="邮箱"
prop="email">
<el-input v-model="dataForm.email"
placeholder="邮箱"></el-input>
</el-form-item>
<el-form-item label="联系方式"
prop="contact">
<el-input v-model="dataForm.contact"
placeholder="联系方式"></el-input>
</el-form-item>
<el-form-item label="留言内容"
prop="content">
<tiny-mce v-model="dataForm.content"
ref="content"></tiny-mce>
</el-form-item>
<el-form-item label="留言回复"
prop="reply">
<tiny-mce v-model="dataForm.reply"
ref="reply"></tiny-mce>
</el-form-item>
<el-form-item label="状态"
size="mini"
prop="status">
<el-radio-group v-model="dataForm.status">
<el-radio :label="0">未审核</el-radio>
<el-radio :label="1">审核通过</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<span slot="footer"
class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary"
@click="dataFormSubmit()">确定</el-button>
</span>
</el-dialog>
</template>
<script>
import { isEmail } from '@/utils/validate'
import TinyMce from '@/components/tiny-mce'
export default {
data () {
var validateEmail = (rule, value, callback) => {
if (!isEmail(value)) {
callback(new Error('邮箱格式错误'))
} else {
callback()
}
}
return {
visible: false,
dataForm: {
id: 0,
createTime: '',
userName: '',
email: '',
contact: '',
content: '',
reply: '',
status: 0
},
page: {
total: 0, // 总页数
currentPage: 1, // 当前页数
pageSize: 10 // 每页显示多少条
},
dataRule: {
userMail: [
{ required: true, message: '邮箱不能为空', trigger: 'blur' },
{ validator: validateEmail, trigger: 'blur' }
]
}
}
},
components: {
TinyMce
},
methods: {
init (id) {
this.dataForm.id = id || 0
this.visible = true
this.$nextTick(() => {
this.$refs.dataForm.resetFields()
this.$refs.content.setContent('')
this.$refs.reply.setContent('')
})
if (this.dataForm.id) {
this.$http({
url: this.$http.adornUrl(`/admin/message/info/${this.dataForm.id}`),
method: 'get',
params: this.$http.adornParams()
}).then(({ data }) => {
this.dataForm = data
this.$refs.content.setContent(data.content)
this.$refs.reply.setContent(data.reply)
})
}
},
// 表单提交
dataFormSubmit () {
this.$refs['dataForm'].validate(valid => {
if (valid) {
this.$http({
url: this.$http.adornUrl(`/admin/message`),
method: this.dataForm.id ? 'put' : 'post',
data: this.$http.adornData({
id: this.dataForm.id || undefined,
createTime: this.dataForm.createTime,
userName: this.dataForm.userName,
email: this.dataForm.email,
contact: this.dataForm.contact,
content: this.dataForm.content,
reply: this.dataForm.reply,
status: this.dataForm.status
})
}).then(({ data }) => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.visible = false
this.$emit('refreshDataList', this.page)
}
})
})
}
})
}
}
}
</script>
<template>
<div class="mod-user">
<avue-crud ref="crud"
:page="page"
:data="dataList"
:option="tableOption"
:permission="permission"
@search-change="searchChange"
@selection-change="selectionChange"
@on-load="getDataList">
<template slot="menuLeft">
<el-button type="primary"
icon="el-icon-plus"
size="small"
v-if="isAuth('admin:message:save')"
@click.stop="addOrUpdateHandle()">新增</el-button>
<el-button type="danger"
@click="deleteHandle()"
v-if="isAuth('admin:message:delete')"
:disabled="dataListSelections.length <= 0">批量删除</el-button>
</template>
<template slot-scope="scope"
slot="status">
<el-tag v-if="scope.row.status === 0"
size="small"
type="danger">未审核</el-tag>
<el-tag v-else
size="small">审核通过</el-tag>
</template>
<template slot-scope="scope"
slot="menu">
<el-button type="text"
size="small"
v-if="isAuth('admin:message:release')"
@click="setMessageRelease(scope.row.id)">公开留言</el-button>
<el-button type="text"
size="small"
v-if="isAuth('admin:message:cancel')"
@click="setMessageCancel(scope.row.id)">取消公开</el-button>
<el-button type="text"
size="small"
v-if="isAuth('admin:message:update')"
@click="addOrUpdateHandle(scope.row.id)">修改</el-button>
<el-button type="text"
size="small"
v-if="isAuth('admin:message:delete')"
@click="deleteHandle(scope.row.id)">删除</el-button>
</template>
</avue-crud>
<!-- 弹窗, 新增 / 修改 -->
<add-or-update v-if="addOrUpdateVisible"
ref="addOrUpdate"
@refreshDataList="getDataList"></add-or-update>
</div>
</template>
<script>
import AddOrUpdate from './message-add-or-update'
import { tableOption } from '@/crud/admin/message'
export default {
data () {
return {
dataForm: {
message: ''
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false,
tableOption: tableOption,
page: {
total: 0, // 总页数
currentPage: 1, // 当前页数
pageSize: 10 // 每页显示多少条
},
permission: {
delBtn: this.isAuth('prod:prod:delete')
}
}
},
components: {
AddOrUpdate
},
methods: {
// 获取数据列表
getDataList (page, params, done) {
this.dataListLoading = true
this.$http({
url: this.$http.adornUrl('/admin/message/page'),
method: 'get',
params: this.$http.adornParams(
Object.assign(
{
current: page == null ? this.page.currentPage : page.currentPage,
size: page == null ? this.page.pageSize : page.pageSize
},
params
)
)
}).then(({ data }) => {
this.dataList = data.records
this.page.total = data.total
this.dataListLoading = false
if (done) {
done()
}
})
},
// 新增 / 修改
addOrUpdateHandle (id) {
this.addOrUpdateVisible = true
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id)
})
},
// 公开留言
setMessageRelease (id) {
if (id) {
this.$http({
url: this.$http.adornUrl(`/admin/message/release/${id}`),
method: 'put',
data: this.$http.adornData({
id: id
})
}).then(({ data }) => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1000,
onClose: () => {
this.visible = false
this.getDataList(this.page)
}
})
})
}
},
// 取消公开留言
setMessageCancel (id) {
if (id) {
this.$http({
url: this.$http.adornUrl(`/admin/message/cancel/${id}`),
method: 'put',
data: this.$http.adornData({
id: id
})
}).then(({ data }) => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1000,
onClose: () => {
this.visible = false
this.getDataList(this.page)
}
})
})
}
},
// 删除
deleteHandle (id) {
var ids = id
? [id]
: this.dataListSelections.map(item => {
return item.id
})
this.$confirm(`确定进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
this.$http({
url: this.$http.adornUrl(`/admin/message/${ids}`),
method: 'delete',
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.getDataList(this.page)
}
})
})
})
.catch(() => { })
},
// 条件查询
searchChange (params, done) {
this.getDataList(this.page, params, done)
},
// 多选变化
selectionChange (val) {
this.dataListSelections = val
}
}
}
</script>
<template>
<!-- 发货信息,用于导出代发货订单的excel交给快递公司 -->
<el-dialog :modal="false"
title="请输入发货信息"
:close-on-click-modal="false"
:visible.sync="visible"
width="38%">
<el-form :model="dataForm"
:rules="dataRule"
ref="dataForm"
@keyup.enter.native="dataFormSubmit()"
label-width="120px">
<el-form-item label="发件人姓名"
prop="consignmentName">
<el-input v-model="dataForm.consignmentName"
controls-position="right"
label="发件人姓名"></el-input>
</el-form-item>
<el-form-item label="发货人手机号"
prop="consignmentMobile">
<el-input v-model="dataForm.consignmentMobile"
controls-position="right"
label="发货人手机号"></el-input>
</el-form-item>
<el-form-item label="发货地址"
prop="consignmentAddr">
<el-input v-model="dataForm.consignmentAddr"
controls-position="right"
label="发货地址"></el-input>
</el-form-item>
</el-form>
<span slot="footer"
class="dialog-footer">
<el-button size="small" @click="visible = false">取消</el-button>
<el-button type="primary" size = "small"
@click="dataFormSubmit()">确定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
data () {
return {
visible: false,
dataForm: {
consignmentName: '',
consignmentMobile: '',
consignmentAddr: ''
},
dataRule: {
consignmentName: [
{ required: true, message: '不能为空', trigger: 'blur' }
],
consignmentMobile: [
{ required: true, message: '不能为空', trigger: 'blur' }
],
consignmentAddr: [
{ required: true, message: '不能为空', trigger: 'blur' }
]
}
}
},
methods: {
init (orderNumber, dvyId, dvyFlowId) {
this.visible = true
this.$nextTick(() => {
this.$refs['dataForm'].resetFields()
})
},
// 表单提交
dataFormSubmit () {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.visible = false
this.$emit('inputCallback', this.dataForm)
}
})
}
}
}
</script>
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