我们发布啦
This commit is contained in:
15
admin/src/views/appSetting/index.vue
Normal file
15
admin/src/views/appSetting/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/appSetting/routine/index.vue
Normal file
15
admin/src/views/appSetting/routine/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
13
admin/src/views/appSetting/routine/routineTemplate.vue
Normal file
13
admin/src/views/appSetting/routine/routineTemplate.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "routineTemplate"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/appSetting/wxAccount/index.vue
Normal file
15
admin/src/views/appSetting/wxAccount/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
626
admin/src/views/appSetting/wxAccount/reply/follow/index.vue
Normal file
626
admin/src/views/appSetting/wxAccount/reply/follow/index.vue
Normal file
@@ -0,0 +1,626 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<router-link v-show="$route.path.indexOf('keyword') !== -1" :to="{path: '/appSetting/publicAccount/wxReply/keyword'}">
|
||||
<el-button size="mini" class="mr20 mb20" icon="el-icon-back">返回</el-button>
|
||||
</router-link>
|
||||
<el-row :gutter="30" v-loading="loading">
|
||||
<el-col v-bind="grid" class="acea-row">
|
||||
<div class="left mb15 ml40">
|
||||
<img class="top" src="@/assets/imgs/mobilehead.png">
|
||||
<img class="bottom" src="@/assets/imgs/mobilefoot.png">
|
||||
<div class="centent">
|
||||
<div class="time-wrapper"><span class="time">9:36</span></div>
|
||||
<div v-if="formValidate.type !== 'news'" class="view-item text-box clearfix">
|
||||
<div class="avatar fl"><img src="@/assets/imgs/head.gif"></div>
|
||||
<div class="box-content fl">
|
||||
<span
|
||||
v-if="formValidate.type === 'text'"
|
||||
v-text="formValidate.contents.content"
|
||||
/>
|
||||
<div v-if="formValidate.contents.mediaId" class="box-content_pic">
|
||||
<img v-if="formValidate.type === 'image'" :src="formValidate.contents.srcUrl">
|
||||
<i class="el-icon-service" v-else></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="formValidate.type === 'news'">
|
||||
<div class="newsBox">
|
||||
<!--<div class="news_pic mb15" style="backgroundImage: url('@/assets/imgs/mobilefoot.png');backgroundSize:'100% 100%'}" />-->
|
||||
<div class="news_pic mb15" :style="{backgroundImage: 'url(' + (formValidate.contents.articleData.imageInput?formValidate.contents.articleData.imageInput[0]:'') + ')',backgroundSize:'100% 100%'}" />
|
||||
<span class="news_sp">{{ formValidate.contents.articleData.title }}</span>
|
||||
</div>
|
||||
<!--<div v-for="(j, i) in formValidate.contents.list" :key="i">-->
|
||||
<!--<div v-if="i === 0">-->
|
||||
<!--<div class="news_pic mb15" :style="{backgroundImage: 'url(' + (j.image_input) + ')',backgroundSize:'100% 100%'}" />-->
|
||||
<!--<span class="news_sp">{{ j.title }}</span>-->
|
||||
<!--</div>-->
|
||||
<!--<div v-else class="news_cent">-->
|
||||
<!--<span v-if="j.synopsis" class="news_sp1">{{ j.title }}</span>-->
|
||||
<!--<div v-if="j.image_input.length!==0" class="news_cent_img"><img :src="j.image_input"></div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xl="11" :lg="12" :md="14" :sm="22" :xs="22">
|
||||
<div class="box-card right ml50">
|
||||
<el-form
|
||||
ref="formValidate"
|
||||
:model="formValidate"
|
||||
:rules="ruleValidate"
|
||||
label-width="100px"
|
||||
class="mt20"
|
||||
@submit.native.prevent
|
||||
>
|
||||
<el-form-item v-if="$route.path.indexOf('keyword') !== -1" label="关键字:" prop="val">
|
||||
<div class="arrbox">
|
||||
<el-tag
|
||||
v-for="(item, index) in labelarr"
|
||||
:key="index"
|
||||
type="success"
|
||||
closable
|
||||
class="mr5"
|
||||
:disable-transitions="false"
|
||||
@close="handleClose(item)"
|
||||
>{{ item }}
|
||||
</el-tag>
|
||||
<el-input
|
||||
v-model="val"
|
||||
size="mini"
|
||||
class="arrbox_ip"
|
||||
placeholder="输入后回车"
|
||||
style="width: 90%;"
|
||||
@change="addlabel"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="规则状态:">
|
||||
<el-radio-group v-model="formValidate.status">
|
||||
<el-radio :label="true">启用</el-radio>
|
||||
<el-radio :label="false">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="消息类型:" prop="type">
|
||||
<el-select
|
||||
v-model="formValidate.type"
|
||||
placeholder="请选择规则状态"
|
||||
style="width: 90%;"
|
||||
@change="RuleFactor(formValidate.type)"
|
||||
>
|
||||
<el-option label="文字消息" value="text">文字消息</el-option>
|
||||
<el-option label="图片消息" value="image">图片消息</el-option>
|
||||
<el-option label="图文消息" value="news">图文消息</el-option>
|
||||
<el-option label="声音消息" value="voice">声音消息</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formValidate.type === 'text'" label="规则内容:" prop="content">
|
||||
<el-input
|
||||
v-model="formValidate.contents.content"
|
||||
placeholder="请填写规则内容"
|
||||
style="width: 90%;"
|
||||
@input="change($event)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formValidate.type === 'news'" label="选取图文:">
|
||||
<el-button size="mini" type="primary" @click="changePic">选择图文消息</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="formValidate.type === 'image' || formValidate.type === 'voice'"
|
||||
:label="formValidate.type === 'image'?'图片地址:':'语音地址:'"
|
||||
prop="mediaId"
|
||||
>
|
||||
<div class="acea-row row-middle">
|
||||
<el-input
|
||||
v-model="formValidate.contents.mediaId"
|
||||
readonly="readonly"
|
||||
placeholder="default size"
|
||||
style="width: 75%;"
|
||||
class="mr10"
|
||||
/>
|
||||
<el-upload
|
||||
class="upload-demo mr10 mb15"
|
||||
action
|
||||
:http-request="handleUploadForm"
|
||||
:headers="myHeaders"
|
||||
:show-file-list="false"
|
||||
multiple
|
||||
>
|
||||
<el-button size="mini" type="primary">点击上传</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
<span v-show="formValidate.type === 'image'">文件最大2Mb,支持bmp/png/jpeg/jpg/gif格式</span>
|
||||
<span v-show="formValidate.type === 'voice'">文件最大2Mb,支持mp3/wma/wav/amr格式,播放长度不超过60s</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-col :span="24">
|
||||
<div class="acea-row row-center">
|
||||
<el-button
|
||||
type="primary"
|
||||
class="ml50"
|
||||
@click="submenus('formValidate')"
|
||||
>保存并发布
|
||||
</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { replySaveApi, replyEditApi, replyInfoApi, replyListApi, keywordsInfoApi, replyUpdateApi } from '@/api/wxApi'
|
||||
import { fileImageApi } from '@/api/systemSetting'
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: { },
|
||||
data() {
|
||||
const validateContent = (rule, value, callback) => {
|
||||
if (this.formValidate.type === 'text') {
|
||||
if (this.formValidate.contents.content === '') {
|
||||
callback(new Error('请填写规则内容'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
const validateSrc = (rule, value, callback) => {
|
||||
if (this.formValidate.type === 'image' && this.formValidate.contents.mediaId === '') {
|
||||
callback(new Error('请上传'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validateVal = (rule, value, callback) => {
|
||||
if (this.labelarr.length === 0) {
|
||||
callback(new Error('请输入后回车'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
loading: false,
|
||||
visible: false,
|
||||
grid: {
|
||||
xl: 7,
|
||||
lg: 12,
|
||||
md: 10,
|
||||
sm: 24,
|
||||
xs: 24
|
||||
},
|
||||
delfromData: {},
|
||||
isShow: false,
|
||||
maxCols: 3,
|
||||
scrollerHeight: '600',
|
||||
contentTop: '130',
|
||||
contentWidth: '98%',
|
||||
modals: false,
|
||||
val: '',
|
||||
formatImg: ['jpg', 'jpeg', 'png', 'bmp', 'gif'],
|
||||
formatVoice: ['mp3', 'wma', 'wav', 'amr'],
|
||||
header: {},
|
||||
formValidate: {
|
||||
status: true,
|
||||
type: '',
|
||||
keywords: '',
|
||||
contents: {
|
||||
content: '',
|
||||
articleData:{},
|
||||
mediaId: '',
|
||||
srcUrl: '',
|
||||
articleId: null
|
||||
},
|
||||
id: null
|
||||
},
|
||||
ruleValidate: {
|
||||
val: [
|
||||
{ required: true, validator: validateVal, trigger: 'blur' }
|
||||
],
|
||||
type: [
|
||||
{ required: true, message: '请选择消息类型', trigger: 'change' }
|
||||
],
|
||||
content: [
|
||||
{ required: true, validator: validateContent, trigger: 'blur' }
|
||||
],
|
||||
mediaId: [
|
||||
{ required: true, validator: validateSrc, trigger: 'change' }
|
||||
]
|
||||
},
|
||||
labelarr: [],
|
||||
myHeaders: { 'X-Token': getToken() }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
fileUrl() {
|
||||
return https + `/wechat/reply/upload/image`
|
||||
},
|
||||
voiceUrl() {
|
||||
return https + `/wechat/reply/upload/voice`
|
||||
},
|
||||
httpsURL() {
|
||||
return process.env.VUE_APP_BASE_API.replace('api/', '')
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route(to, from) {
|
||||
if (this.$route.params.id) {
|
||||
// this.formValidate.keywords = this.$route.params.key
|
||||
this.details()
|
||||
} else {
|
||||
// this.labelarr = []
|
||||
// this.$refs['formValidate'].resetFields()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.$route.params.id) {
|
||||
this.details()
|
||||
}
|
||||
if (this.$route.path.indexOf('keyword') === -1) {
|
||||
this.followDetails()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
change (e) {
|
||||
this.$forceUpdate()
|
||||
},
|
||||
// 上传
|
||||
handleUploadForm(param){
|
||||
const formData = new FormData()
|
||||
formData.append('media', param.file)
|
||||
let loading = this.$loading({
|
||||
lock: true,
|
||||
text: '上传中,请稍候...',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
fileImageApi(formData, {type: this.formValidate.type === 'image'?'image':'voice'}).then(res => {
|
||||
loading.close()
|
||||
this.formValidate.contents.mediaId = res.mediaId
|
||||
this.formValidate.contents.srcUrl = res.url
|
||||
this.$message.success('上传成功')
|
||||
}).catch(() => {
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
changePic() {
|
||||
const _this = this
|
||||
this.$modalArticle(function(row) {
|
||||
_this.formValidate.contents.articleData ={
|
||||
title: row.title,
|
||||
imageInput : row.imageInput
|
||||
}
|
||||
_this.formValidate.contents.articleId = row.id
|
||||
})
|
||||
},
|
||||
handleClosePic() {
|
||||
this.visible = false
|
||||
},
|
||||
// 详情
|
||||
details() {
|
||||
this.loading = true
|
||||
replyInfoApi({id:this.$route.params.id}).then(async res => {
|
||||
const info = res || null
|
||||
this.formValidate = {
|
||||
status: info.status,
|
||||
type: info.type,
|
||||
keywords: info.keywords,
|
||||
id: info.id,
|
||||
contents: {
|
||||
content: JSON.parse(info.data).content,
|
||||
mediaId: JSON.parse(info.data).mediaId,
|
||||
srcUrl: JSON.parse(info.data).srcUrl
|
||||
}
|
||||
}
|
||||
this.labelarr = info.keywords.split(',') || []
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 关注回复,无效关键词详情
|
||||
followDetails() {
|
||||
this.loading = true
|
||||
keywordsInfoApi({ keywords: this.$route.path.indexOf('follow') !== -1 ? 'subscribe' : 'default'}).then(async res => {
|
||||
const info = res || null
|
||||
this.formValidate = {
|
||||
status: info.status,
|
||||
type: info.type,
|
||||
keywords: info.keywords,
|
||||
data: '',
|
||||
id: info.id,
|
||||
contents: {
|
||||
content: JSON.parse(info.data).content || '',
|
||||
mediaId: JSON.parse(info.data).mediaId || '',
|
||||
srcUrl: JSON.parse(info.data).srcUrl || '',
|
||||
articleData: JSON.parse(info.data).articleData || {},
|
||||
}
|
||||
}
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
// if (res.message === '数据不存在') return
|
||||
// this.$message.error(res.message)
|
||||
})
|
||||
},
|
||||
// 下拉选择
|
||||
RuleFactor(type) {
|
||||
switch (type) {
|
||||
case 'text':
|
||||
this.formValidate.contents.mediaId = ''
|
||||
this.formValidate.contents.srcUrl = ''
|
||||
this.formValidate.contents.articleData = {}
|
||||
break
|
||||
case 'news':
|
||||
this.formValidate.contents.mediaId = ''
|
||||
this.formValidate.contents.content = ''
|
||||
this.formValidate.contents.srcUrl = ''
|
||||
this.formValidate.contents.articleData = {}
|
||||
break
|
||||
default:
|
||||
this.formValidate.contents.content = ''
|
||||
this.formValidate.contents.mediaId = ''
|
||||
this.formValidate.contents.articleData = {}
|
||||
}
|
||||
// this.$refs['formValidate'].resetFields();
|
||||
},
|
||||
handleClose(tag) {
|
||||
const index = this.labelarr.indexOf(tag)
|
||||
this.labelarr.splice(index, 1)
|
||||
},
|
||||
addlabel() {
|
||||
const count = this.labelarr.indexOf(this.val)
|
||||
if (count === -1) {
|
||||
this.labelarr.push(this.val)
|
||||
}
|
||||
this.val = ''
|
||||
},
|
||||
// 保存
|
||||
submenus(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.formValidate.keywords = this.labelarr.join(',')
|
||||
this.formValidate.data = JSON.stringify(this.formValidate.contents)
|
||||
if (this.$route.path.indexOf('keyword') !== -1) {
|
||||
this.$route.params.id ? replyUpdateApi({id:this.$route.params.id}, this.formValidate).then(async res => {
|
||||
this.operation()
|
||||
}).catch(res => {
|
||||
this.$message.error(res.message)
|
||||
}) : replySaveApi(this.formValidate).then(async res => {
|
||||
this.operation()
|
||||
}).catch(res => {
|
||||
this.$message.error(res.message)
|
||||
})
|
||||
} else {
|
||||
this.$route.path.indexOf('follow') !== -1 ? this.formValidate.keywords = 'subscribe' : this.formValidate.keywords ='default'
|
||||
replyUpdateApi({id:this.formValidate.id}, this.formValidate).then(async res => {
|
||||
this.$message.success('操作成功')
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
// 保存成功操作
|
||||
operation() {
|
||||
this.$modalSure('继续添加').then(() => {
|
||||
setTimeout(() => {
|
||||
this.labelarr = []
|
||||
this.val = ''
|
||||
this.$refs['formValidate'].resetFields()
|
||||
this.formValidate.contents.mediaId = ''
|
||||
}, 1000)
|
||||
}).catch(() => {
|
||||
setTimeout(() => {
|
||||
this.$router.push({ path: `/publicAccount/wxReply/keyword` })
|
||||
}, 500)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.newsBox{
|
||||
background: #fff;
|
||||
}
|
||||
.arrbox {
|
||||
background-color: white;
|
||||
font-size: 12px;
|
||||
border: 1px solid #dcdee2;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 0px;
|
||||
padding:0 5px;
|
||||
text-align: left;
|
||||
box-sizing: border-box;
|
||||
width: 90%;
|
||||
}
|
||||
.news_sp{
|
||||
font-size: 12px;
|
||||
color: #000000;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
padding: 0 12px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
}
|
||||
.arrbox_ip {
|
||||
font-size: 12px;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: auto !important;
|
||||
max-width: inherit;
|
||||
min-width: 80px;
|
||||
vertical-align: top;
|
||||
color: #34495e;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.left {
|
||||
min-width: 390px;
|
||||
min-height: 550px;
|
||||
position: relative;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.top {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.centent {
|
||||
background: #F4F5F9;
|
||||
min-height: 545px;
|
||||
width: 320px;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.right {
|
||||
background: #fff;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.box-content {
|
||||
position: relative;
|
||||
max-width: 60%;
|
||||
min-height: 40px;
|
||||
margin-left: 15px;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
line-height: 1.5;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.box-content_pic {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.box-content_pic img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.box-content:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -13px;
|
||||
top: 11px;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 8px solid transparent;
|
||||
border-right: 8px solid transparent;
|
||||
border-top: 10px solid #ccc;
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.box-content:after {
|
||||
content: '';
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -12px;
|
||||
top: 11px;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 8px solid transparent;
|
||||
border-right: 8px solid transparent;
|
||||
border-top: 10px solid #f5f5f5;
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.time-wrapper {
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
margin-top: 62px;
|
||||
}
|
||||
|
||||
.time {
|
||||
display: inline-block;
|
||||
color: #f5f5f5;
|
||||
background: rgba(0, 0, 0, .3);
|
||||
padding: 3px 8px;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.text-box {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.modelBox{
|
||||
.ivu-modal-body{
|
||||
padding: 0 16px 16px 16px !important;
|
||||
}
|
||||
}
|
||||
.news_pic{
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background-size: 100%;
|
||||
background-position: center center;
|
||||
border-radius: 5px 5px 0 0;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.news_cent{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background: #fff;
|
||||
border-top: 1px dashed #eee;
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
justify-content: space-between;
|
||||
.news_sp1{
|
||||
font-size: 12px;
|
||||
color: #000000;
|
||||
width: 71%;
|
||||
}
|
||||
.news_cent_img{
|
||||
width: 81px;
|
||||
height: 46px;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
3
admin/src/views/appSetting/wxAccount/reply/index.vue
Normal file
3
admin/src/views/appSetting/wxAccount/reply/index.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
156
admin/src/views/appSetting/wxAccount/reply/keyword/index.vue
Normal file
156
admin/src/views/appSetting/wxAccount/reply/keyword/index.vue
Normal file
@@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="container">
|
||||
<el-form size="small" :inline="true">
|
||||
<el-form-item label="回复类型:">
|
||||
<el-select v-model="tableFrom.type" placeholder="请选择类型" @change="seachList" class="selWidth">
|
||||
<el-option label="文本消息" value="text"></el-option>
|
||||
<el-option label="图片消息" value="image"></el-option>
|
||||
<el-option label="图文消息" value="news"></el-option>
|
||||
<el-option label="音频消息" value="voice"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键字:">
|
||||
<el-input v-model="tableFrom.keywords" placeholder="请输入关键字" class="selWidth" size="small">
|
||||
<el-button slot="append" icon="el-icon-search" size="small" @click="seachList" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<router-link :to="{path: '/appSetting/publicAccount/wxReply/keyword/save'}">
|
||||
<el-button size="small" type="primary">添加关键字</el-button>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
size="small"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
width="60"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="keywords"
|
||||
label="关键字"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column
|
||||
label="回复类型"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.type | keywordStatusFilter}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="status"
|
||||
label="是否显示"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.status"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
@change="onchangeIsShow(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<router-link :to="{path: '/appSetting/publicAccount/wxReply/keyword/save/' + scope.row.id}">
|
||||
<el-button type="text" size="small">编辑</el-button>
|
||||
</router-link>
|
||||
<el-button type="text" size="small" @click="handleDelete(scope.row.id, scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { replyListApi, replyDeleteApi, replyUpdateApi } from '@/api/wxApi'
|
||||
import { getToken } from '@/utils/auth'
|
||||
export default {
|
||||
name: 'WechatKeyword',
|
||||
data() {
|
||||
return {
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
tableFrom: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
keywords: '',
|
||||
type: ''
|
||||
},
|
||||
listLoading: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
seachList() {
|
||||
this.tableFrom.page = 1
|
||||
this.getList()
|
||||
},
|
||||
onchangeIsShow(row) {
|
||||
replyUpdateApi(row.id, row).then(() => {
|
||||
this.$message.success('修改成功')
|
||||
})
|
||||
},
|
||||
// 列表
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
replyListApi(this.tableFrom).then(res => {
|
||||
this.tableData.data = res.list
|
||||
this.tableData.total = res.total
|
||||
this.listLoading = false
|
||||
}).catch(res => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
pageChange(page) {
|
||||
this.tableFrom.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val
|
||||
this.getList()
|
||||
},
|
||||
// 删除
|
||||
handleDelete(id, idx) {
|
||||
this.$modalSure().then(() => {
|
||||
replyDeleteApi(id).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.getList()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
422
admin/src/views/appSetting/wxAccount/wxMenus.vue
Normal file
422
admin/src/views/appSetting/wxAccount/wxMenus.vue
Normal file
@@ -0,0 +1,422 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<el-row :gutter="30">
|
||||
<el-col v-bind="grid" class="left mb15 ml40">
|
||||
<div>
|
||||
<img class="top" src="@/assets/imgs/mobilehead.png">
|
||||
<img class="bottom" src="@/assets/imgs/mobilefoot.png">
|
||||
<div
|
||||
style="background: #F4F5F9; min-height: 438px; position: absolute;
|
||||
top: 63px; width: 320px; "
|
||||
/>
|
||||
<div class="textbot">
|
||||
<div v-for="(item,indx) in list" :key="indx" class="li" :class="{active:item === formValidate}">
|
||||
<div>
|
||||
<div class="add" @click="add(item,indx)">
|
||||
<i class="el-icon-plus" />
|
||||
<div class="arrow" />
|
||||
</div>
|
||||
<div class="tianjia">
|
||||
<div
|
||||
v-for="(j,index) in item.sub_button"
|
||||
:key="index"
|
||||
class="addadd menuBox"
|
||||
:class="{active:j === formValidate}"
|
||||
@click="gettem(j,index,indx)"
|
||||
>
|
||||
<el-tooltip class="item" effect="dark" :content="j.name" placement="top-start">
|
||||
<el-button>{{ j.name || '二级菜单' }}</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text menuBox" @click="gettem(item,indx,null)">
|
||||
<el-tooltip class="item" effect="dark" :content="item.name" placement="top-start">
|
||||
<el-button>{{ item.name || '一级菜单' }}</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="list.length < 3" class="li">
|
||||
<div class="text" @click="addtext"><i class="el-icon-plus" /></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xl="11" :lg="12" :md="22" :sm="22" :xs="22">
|
||||
<div v-if="checkedMenuId !== null">
|
||||
<div class="dividerTitle acea-row row-between row-bottom">
|
||||
<span class="title">菜单信息</span>
|
||||
<el-button slot="extra" size="small" type="danger" @click="deltMenus">删除</el-button>
|
||||
<el-divider />
|
||||
</div>
|
||||
<el-col :span="24" class="userAlert">
|
||||
<div class="box-card right">
|
||||
<el-alert
|
||||
class="mb15"
|
||||
title="已添加子菜单,仅可设置菜单名称"
|
||||
type="success"
|
||||
show-icon
|
||||
/>
|
||||
<el-form ref="formValidate" :model="formValidate" :rules="ruleValidate" label-width="100px" class="mt20">
|
||||
<el-form-item label="菜单名称" prop="name">
|
||||
<el-input v-model="formValidate.name" placeholder="请填写菜单名称" class="spwidth" />
|
||||
</el-form-item>
|
||||
<el-form-item label="规则状态" prop="type">
|
||||
<el-select v-model="formValidate.type" placeholder="请选择规则状态" class="spwidth">
|
||||
<el-option value="click" label="关键字">关键字</el-option>
|
||||
<el-option value="view" label="跳转网页">跳转网页</el-option>
|
||||
<el-option value="miniprogram" label="小程序">小程序</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div v-if="formValidate.type === 'click'">
|
||||
<el-form-item label="关键字" prop="key">
|
||||
<el-input v-model="formValidate.key" placeholder="请填写关键字" class="spwidth" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="formValidate.type === 'miniprogram'">
|
||||
<el-form-item label="appid" prop="appid">
|
||||
<el-input v-model="formValidate.appid" placeholder="请填写appid" class="spwidth" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备用网页" prop="pagepath">
|
||||
<el-input v-model="formValidate.pagepath" placeholder="请填写备用网页" class="spwidth" />
|
||||
</el-form-item>
|
||||
<el-form-item label="小程序路径" prop="url">
|
||||
<el-input v-model="formValidate.url" placeholder="请填写小程序路径" class="spwidth" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="formValidate.type === 'view'">
|
||||
<el-form-item label="跳转地址" prop="url">
|
||||
<el-input v-model="formValidate.url" placeholder="请填写跳转地址" class="spwidth" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-col>
|
||||
</div>
|
||||
<el-col v-if="isTrue" :span="24">
|
||||
<el-button size="mini" type="primary" style="display: block;margin: 10px auto;" @click="submenus('formValidate')">保存并发布</el-button>
|
||||
</el-col>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { wechatMenuApi, wechatMenuAddApi } from '@/api/wxApi'
|
||||
export default {
|
||||
name: 'WechatMenus',
|
||||
data() {
|
||||
return {
|
||||
grid: {
|
||||
xl: 8,
|
||||
lg: 8,
|
||||
md: 8,
|
||||
sm: 8,
|
||||
xs: 24
|
||||
},
|
||||
grid2: {
|
||||
xl: 16,
|
||||
lg: 16,
|
||||
md: 16,
|
||||
sm: 16,
|
||||
xs: 24
|
||||
},
|
||||
modal2: false,
|
||||
formValidate: {
|
||||
name: '',
|
||||
type: 'click',
|
||||
appid: '',
|
||||
url: '',
|
||||
key: '',
|
||||
pagepath: '',
|
||||
id: 0
|
||||
},
|
||||
ruleValidate: {
|
||||
name: [
|
||||
{ required: true, message: '请填写菜单名称', trigger: 'blur' }
|
||||
],
|
||||
key: [
|
||||
{ required: true, message: '请填写关键字', trigger: 'blur' }
|
||||
],
|
||||
appid: [
|
||||
{ required: true, message: '请填写appid', trigger: 'blur' }
|
||||
],
|
||||
pagepath: [
|
||||
{ required: true, message: '请填写备用网页', trigger: 'blur' }
|
||||
],
|
||||
url: [
|
||||
{ required: true, message: '请填写跳转地址', trigger: 'blur' }
|
||||
],
|
||||
type: [
|
||||
{ required: true, message: '请选择规则状态', trigger: 'change' }
|
||||
]
|
||||
},
|
||||
parentMenuId: null,
|
||||
list: [],
|
||||
checkedMenuId: null,
|
||||
isTrue: false,
|
||||
isAsync: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getMenus()
|
||||
if (this.list.length) {
|
||||
this.formValidate = this.list[this.activeClass]
|
||||
} else {
|
||||
return this.formValidate
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 添加一级字段函数
|
||||
defaultMenusData() {
|
||||
return {
|
||||
type: 'click',
|
||||
name: '',
|
||||
sub_button: []
|
||||
}
|
||||
},
|
||||
// 添加二级字段函数
|
||||
defaultChildData() {
|
||||
return {
|
||||
type: 'click',
|
||||
name: ''
|
||||
}
|
||||
},
|
||||
// 获取 菜单
|
||||
getMenus() {
|
||||
wechatMenuApi({ isAsync:this.isAsync }).then(async res => {
|
||||
const data = res.menu
|
||||
this.list = data.button
|
||||
})
|
||||
},
|
||||
// 点击保存提交
|
||||
submenus(name) {
|
||||
if (this.isTrue && !this.checkedMenuId && this.checkedMenuId !== 0) {
|
||||
this.putData()
|
||||
} else {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.putData()
|
||||
} else {
|
||||
if (!this.check()) return false
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
// 新增data
|
||||
putData() {
|
||||
const data = {
|
||||
button: this.list
|
||||
}
|
||||
wechatMenuAddApi(data).then(async res => {
|
||||
this.$message.success('提交成功')
|
||||
this.checkedMenuId = null
|
||||
this.formValidate = {}
|
||||
this.isTrue = false
|
||||
})
|
||||
},
|
||||
// 点击元素
|
||||
gettem(item, index, pid) {
|
||||
this.checkedMenuId = index
|
||||
this.formValidate = item
|
||||
this.parentMenuId = pid
|
||||
this.isTrue = true
|
||||
},
|
||||
// 增加二级
|
||||
add(item, index) {
|
||||
if (!this.check()) return false
|
||||
if (item.sub_button.length < 5) {
|
||||
const data = this.defaultChildData()
|
||||
const id = item.sub_button.length
|
||||
item.sub_button.push(data)
|
||||
this.formValidate = data
|
||||
this.checkedMenuId = id
|
||||
this.parentMenuId = index
|
||||
this.isTrue = true
|
||||
}
|
||||
},
|
||||
// 增加一级
|
||||
addtext() {
|
||||
if (!this.check()) return false
|
||||
const data = this.defaultMenusData()
|
||||
const id = this.list.length
|
||||
this.list.push(data)
|
||||
this.formValidate = data
|
||||
this.checkedMenuId = id
|
||||
this.parentMenuId = null
|
||||
this.isTrue = true
|
||||
},
|
||||
// 判断函数
|
||||
check: function() {
|
||||
const reg = /[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/
|
||||
if (this.checkedMenuId === null) return true
|
||||
if (!this.isTrue) return true
|
||||
if (!this.formValidate.name) {
|
||||
this.$message.warning('请输入按钮名称!')
|
||||
return false
|
||||
}
|
||||
if (this.formValidate.type === 'click' && !this.formValidate.key) {
|
||||
this.$message.warning('请输入关键字!')
|
||||
return false
|
||||
}
|
||||
if (this.formValidate.type === 'view' && !(reg.test(this.formValidate.url))) {
|
||||
this.$message.warning('请输入正确的跳转地址!')
|
||||
return false
|
||||
}
|
||||
if (this.formValidate.type === 'miniprogram' &&
|
||||
(!this.formValidate.appid ||
|
||||
!this.formValidate.pagepath ||
|
||||
!this.formValidate.url)) {
|
||||
this.$message.warning('请填写完整小程序配置!')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
// 删除
|
||||
deltMenus() {
|
||||
if (this.isTrue) {
|
||||
this.$modalSure().then(() => {
|
||||
this.del()
|
||||
})
|
||||
} else {
|
||||
this.$message.warning('请选择菜单!')
|
||||
}
|
||||
},
|
||||
// 确认删除
|
||||
del() {
|
||||
this.parentMenuId === null ? this.list.splice(this.checkedMenuId, 1) : this.list[this.parentMenuId].sub_button.splice(this.checkedMenuId, 1)
|
||||
this.parentMenuId = null
|
||||
this.formValidate = {
|
||||
name: '',
|
||||
type: 'click',
|
||||
appid: '',
|
||||
url: '',
|
||||
key: '',
|
||||
pagepath: '',
|
||||
id: 0
|
||||
}
|
||||
this.isTrue = true
|
||||
this.modal2 = false
|
||||
this.checkedMenuId = null
|
||||
this.$refs['formValidate'].resetFields()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.menuBox{
|
||||
/deep/.el-button{
|
||||
border: none;
|
||||
background: bottom;
|
||||
padding: 0 !important;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
*{
|
||||
-moz-user-select: none; /*火狐*/
|
||||
-webkit-user-select: none; /*webkit浏览器*/
|
||||
-ms-user-select: none; /*IE10*/
|
||||
-khtml-user-select: none; /*早期浏览器*/
|
||||
user-select: none;
|
||||
}
|
||||
.title{
|
||||
margin-bottom: -19px !important;
|
||||
padding-bottom: 17px !important;
|
||||
}
|
||||
.left {
|
||||
min-width: 390px;
|
||||
min-height: 550px;
|
||||
position: relative;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.top {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.textbot {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 59px;
|
||||
width: 100%;
|
||||
}
|
||||
.active {
|
||||
border: 1px solid #44B549 !important;
|
||||
color: #44B549 !important;
|
||||
}
|
||||
.li {
|
||||
float: left;
|
||||
width: 93px;
|
||||
line-height: 48px;
|
||||
border: 1px solid #E7E7EB;
|
||||
background: #FAFAFA;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
color: #999;
|
||||
position: relative;
|
||||
}
|
||||
.text{
|
||||
height: 50px;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap;
|
||||
}
|
||||
.text:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.add {
|
||||
position: absolute;
|
||||
bottom: 65px;
|
||||
width: 100%;
|
||||
line-height: 48px;
|
||||
border: 1px solid #E7E7EB;
|
||||
background: #FAFAFA;
|
||||
}
|
||||
.arrow {
|
||||
position: absolute;
|
||||
bottom: -16px;
|
||||
left: 36px;
|
||||
/* 圆角的位置需要细心调试哦 */
|
||||
width: 0;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
border: solid 8px;
|
||||
border-color:#fff #F4F5F9 #F4F5F9 #F4F5F9;
|
||||
}
|
||||
.tianjia {
|
||||
position: absolute;
|
||||
bottom: 115px;
|
||||
width: 100%;
|
||||
line-height: 48px;
|
||||
background: #FAFAFA;
|
||||
}
|
||||
.addadd {
|
||||
width: 100%;
|
||||
line-height: 48px;
|
||||
border: 1px solid #E7E7EB;
|
||||
background: #FAFAFA;
|
||||
height: 48px;
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.right {
|
||||
background: #fff;
|
||||
min-height: 400px;
|
||||
}
|
||||
.spwidth{
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
226
admin/src/views/appSetting/wxAccount/wxTemplate/index.vue
Normal file
226
admin/src/views/appSetting/wxAccount/wxTemplate/index.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="container">
|
||||
<el-form size="small" :inline="true" label-width="100px">
|
||||
<el-form-item label="状态:">
|
||||
<el-select v-model="tableFrom.status" placeholder="请选择状态" clearable class="selWidth">
|
||||
<el-option :label="item.label" :value="item.value" v-for="(item, index) in switchData" :key="index"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型:">
|
||||
<el-select v-model="tableFrom.type" placeholder="请选择类型" clearable class="selWidth">
|
||||
<el-option label="订阅消息" value="0"></el-option>
|
||||
<el-option label="模板消息" value="1"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板名称:">
|
||||
<el-input v-model="tableFrom.name" placeholder="请输入模板名称" class="selWidth" size="small"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="微信模板ID:">
|
||||
<el-input v-model="tableFrom.tempId" placeholder="请输入微信模板ID" class="selWidth" size="small"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="seachList" size="small">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button type="primary" @click="add" size="small">添加模板消息</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
class="table"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
label="ID"
|
||||
width="80"
|
||||
prop="id"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="tempId"
|
||||
label="模板ID"
|
||||
min-width="340"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="模板名"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column
|
||||
label="回复内容"
|
||||
min-width="200"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-for="(item, index) in scope.row.content.split('\n')" :key="index" style="display: block">{{item}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="状态"
|
||||
width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.status"
|
||||
class="demo"
|
||||
active-text="开启"
|
||||
inactive-text="关闭"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@click.native="onchangeIsShow(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
label="添加时间"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column label="操作" min-width="150" fixed="right" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="edit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="small" @click="handleDelete(scope.row, scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!--编辑-->
|
||||
<el-dialog
|
||||
title="编辑订单"
|
||||
:visible.sync="dialogVisible"
|
||||
width="500px"
|
||||
:before-close="handleClose">
|
||||
<zb-parser
|
||||
v-if="dialogVisible"
|
||||
:form-id="105"
|
||||
:is-create="isCreate"
|
||||
:edit-data="editData"
|
||||
@submit="handlerSubmit"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import { wechatTemplateListApi, wechatTemplateStatusApi, wechatTemplateSaveApi, wechatTemplateUpdateApi, wechatTemplateDeleteApi} from '@/api/wxApi'
|
||||
import zbParser from '@/components/FormGenerator/components/parser/ZBParser'
|
||||
export default {
|
||||
name: "Templates",
|
||||
components: { zbParser },
|
||||
data() {
|
||||
return {
|
||||
labelPosition:'right',
|
||||
isCreate: 0,
|
||||
editData: {},
|
||||
dialogVisible: false,
|
||||
switchData: constants.switchStatus,
|
||||
tableFrom: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
status: '',
|
||||
name: '',
|
||||
type: this.$route.path.indexOf('routineTemplate') !== -1? '0' :'1',
|
||||
tempId: ''
|
||||
},
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
listLoading: true,
|
||||
tempId: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
seachList() {
|
||||
this.tableFrom.page = 1
|
||||
this.getList()
|
||||
},
|
||||
// 订单删除
|
||||
handleDelete(row, idx) {
|
||||
this.$modalSure().then(() => {
|
||||
wechatTemplateDeleteApi( row.id ).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.tableData.data.splice(idx, 1)
|
||||
})
|
||||
})
|
||||
},
|
||||
handleClose() {
|
||||
this.dialogVisible = false
|
||||
this.editData = {}
|
||||
},
|
||||
handlerSubmit(formValue) {
|
||||
this.isCreate === 0 ? wechatTemplateSaveApi(formValue).then(data => {
|
||||
this.$message.success('新增成功')
|
||||
this.dialogVisible = false
|
||||
this.editData = {}
|
||||
this.getList()
|
||||
}) : wechatTemplateUpdateApi(this.tempId, formValue).then(data => {
|
||||
this.$message.success('编辑成功')
|
||||
this.dialogVisible = false
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
add() {
|
||||
this.dialogVisible = true
|
||||
},
|
||||
edit(row) {
|
||||
this.tempId = row.id
|
||||
this.dialogVisible = true
|
||||
this.isCreate = 1
|
||||
this.editData = JSON.parse(JSON.stringify(row))
|
||||
},
|
||||
// 列表
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
wechatTemplateListApi(this.tableFrom).then(res => {
|
||||
this.tableData.data = res.list || []
|
||||
this.tableData.total = res.total
|
||||
this.listLoading = false
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
pageChange(page) {
|
||||
this.tableFrom.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val
|
||||
this.getList()
|
||||
},
|
||||
// 修改状态
|
||||
onchangeIsShow(row) {
|
||||
wechatTemplateStatusApi(row.id, {status: row.status}).then(() => {
|
||||
this.$message.success('修改成功')
|
||||
this.getList()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.selWidth {
|
||||
width: 350px;
|
||||
}
|
||||
</style>
|
||||
205
admin/src/views/content/article/edit.vue
Normal file
205
admin/src/views/content/article/edit.vue
Normal file
@@ -0,0 +1,205 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<el-form ref="pram" label-width="150px" :model="pram">
|
||||
<el-form-item label="标题" prop="title" :rules="[{required:true, message:'请填写标题', trigger:['blur','change']}]">
|
||||
<el-input v-model="pram.title" placeholder="标题" maxlength="100"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="作者" prop="author" :rules="[{required:true, message:'请填作者', trigger:['blur','change']}]">
|
||||
<el-input v-model="pram.author" placeholder="作者" maxlength="20"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="文章分类">
|
||||
<!-- prop="cid" :rules="[{required:true, message:'请选择文章分类', trigger:['blur','change']}]"-->
|
||||
<el-cascader v-model="pram.cid" :options="categoryTreeData" :props="categoryProps" style="width:100%;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="图文封面" prop="imageInput" :rules="[{ required: true, message: '请上传图文封面', trigger: 'change' }]">
|
||||
<div class="upLoadPicBox" @click="modalPicTap('1')">
|
||||
<div v-if="pram.imageInput" class="pictrue"><img :src="pram.imageInput"></div>
|
||||
<div v-else class="upLoad">
|
||||
<i class="el-icon-camera cameraIconfont" />
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!--<el-form-item label="微信公众号封面" prop="imageInput" :rules="[{ required: true, message: '请上传图文封面', trigger: 'change' }]">-->
|
||||
<!--<div class="upLoadPicBox">-->
|
||||
<!--<div v-if="pram.imageInput" class="pictrue"><img :src="pram.imageInput"></div>-->
|
||||
<!--<el-upload-->
|
||||
<!--v-else-->
|
||||
<!--class="upload-demo mr10 mb15"-->
|
||||
<!--action-->
|
||||
<!--:http-request="handleUploadForm"-->
|
||||
<!--:headers="myHeaders"-->
|
||||
<!--:show-file-list="false"-->
|
||||
<!--multiple-->
|
||||
<!-->-->
|
||||
<!--<div class="upLoad">-->
|
||||
<!--<i class="el-icon-camera cameraIconfont" />-->
|
||||
<!--</div>-->
|
||||
<!--</el-upload>-->
|
||||
<!--</div>-->
|
||||
<!--</el-form-item>-->
|
||||
<el-form-item label="文章简介" prop="synopsis" :rules="[{required:true, message:'请填写文章简介', trigger:['blur','change']}]">
|
||||
<el-input v-model="pram.synopsis" maxlength="100" type="textarea" :rows="2" resize="none" placeholder="文章简介" />
|
||||
</el-form-item>
|
||||
<el-form-item label="文章内容" prop="content" :rules="[{required:true, message:'请填写文章内容', trigger:['blur','change']}]">
|
||||
<ueditor-from v-model="pram.content" :content="pram.content" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否Banner">
|
||||
<el-switch v-model="pram.isBanner" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否热门">
|
||||
<el-switch v-model="pram.isHot" />
|
||||
</el-form-item>
|
||||
<el-form-item label="原文链接">
|
||||
<p>原文链接选填,填写之后在图文左下方会出现此链接</p>
|
||||
<el-input v-model="pram.url" placeholder="原文链接" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handerSubmit('pram')">保存</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Tinymce from '@/components/Tinymce/index'
|
||||
import * as categoryApi from '@/api/categoryApi.js'
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import * as articleApi from '@/api/article.js'
|
||||
import * as selfUtil from '@/utils/ZBKJIutil.js'
|
||||
import { fileImageApi } from '@/api/systemSetting'
|
||||
import { getToken } from '@/utils/auth'
|
||||
export default {
|
||||
// name: "edit",
|
||||
components: { Tinymce },
|
||||
props: {
|
||||
isEdit: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
editData: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
constants,
|
||||
categoryTreeData: [],
|
||||
categoryProps: {
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
children: 'child',
|
||||
expandTrigger: 'hover',
|
||||
checkStrictly: true,
|
||||
emitPath: false
|
||||
},
|
||||
pram: {
|
||||
author: null,
|
||||
cid: 0,
|
||||
content: null,
|
||||
imageInput: '',
|
||||
isBanner: false,
|
||||
isHot: null,
|
||||
shareSynopsis: null,
|
||||
shareTitle: null,
|
||||
sort: 0,
|
||||
synopsis: null,
|
||||
title: null,
|
||||
url: null,
|
||||
id: null
|
||||
// mediaId: null
|
||||
},
|
||||
myHeaders: { 'X-Token': getToken() }
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handlerGetCategoryTreeData()
|
||||
this.hadlerInitEditData()
|
||||
},
|
||||
methods: {
|
||||
// 上传
|
||||
handleUploadForm(param){
|
||||
const formData = new FormData()
|
||||
formData.append('media', param.file)
|
||||
let loading = this.$loading({
|
||||
lock: true,
|
||||
text: '上传中,请稍候...',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
fileImageApi(formData, {type: 'image'}).then(res => {
|
||||
loading.close()
|
||||
this.pram.mediaId = res.mediaId
|
||||
|
||||
// this.formValidate.contents.mediaId = res.mediaId
|
||||
// this.formValidate.contents.srcUrl = res.url
|
||||
this.$message.success('上传成功')
|
||||
}).catch(() => {
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
modalPicTap(tit) {
|
||||
const _this = this
|
||||
this.$modalUpload(function(img) {
|
||||
_this.pram.imageInput = img[0].sattDir
|
||||
}, tit, 'content')
|
||||
},
|
||||
hadlerInitEditData() {
|
||||
if (this.isEdit !== 1) return
|
||||
const { author, cid, content, imageInput,
|
||||
isBanner, isHot, shareSynopsis, shareTitle, sort, synopsis, title, url, id } = this.editData
|
||||
this.pram.author = author
|
||||
this.pram.cid = Number.parseInt(cid)
|
||||
this.pram.content = content
|
||||
this.pram.imageInput = imageInput
|
||||
this.pram.isBanner = isBanner
|
||||
this.pram.isHot = isHot
|
||||
this.pram.shareSynopsis = shareSynopsis
|
||||
this.pram.shareTitle = shareTitle
|
||||
this.pram.sort = sort
|
||||
this.pram.synopsis = synopsis
|
||||
this.pram.title = title
|
||||
this.pram.url = url
|
||||
this.pram.id = id
|
||||
// this.pram.mediaId = mediaId
|
||||
},
|
||||
handlerGetCategoryTreeData() {
|
||||
const _pram = { type: constants.categoryType[2].value, status: 1 }
|
||||
categoryApi.treeCategroy(_pram).then(data => {
|
||||
this.categoryTreeData = selfUtil.addTreeListLabelForCasCard(data)
|
||||
})
|
||||
},
|
||||
handerSubmit(form) {
|
||||
this.$refs[form].validate(valid => {
|
||||
if (!valid) return
|
||||
if (this.isEdit === 0) {
|
||||
this.handlerSave()
|
||||
} else {
|
||||
this.handlerUpdate()
|
||||
}
|
||||
})
|
||||
},
|
||||
handlerUpdate() {
|
||||
this.pram.cid = Array.isArray(this.pram.cid) ? this.pram.cid[0] : this.pram.cid
|
||||
this.pram.shareTitle = this.pram.title
|
||||
this.pram.shareSynopsis = this.pram.synopsis
|
||||
articleApi.UpdateArticle(this.pram).then(data => {
|
||||
this.$message.success('编辑文章成功')
|
||||
this.$emit('hideDialog')
|
||||
})
|
||||
},
|
||||
handlerSave() {
|
||||
this.pram.cid = Array.isArray(this.pram.cid) ? this.pram.cid[0] : this.pram.cid
|
||||
this.pram.shareTitle = this.pram.title
|
||||
this.pram.shareSynopsis = this.pram.synopsis
|
||||
articleApi.AddArticle(this.pram).then(data => {
|
||||
this.$message.success('新增文章成功')
|
||||
this.$emit('hideDialog')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
192
admin/src/views/content/article/list.vue
Normal file
192
admin/src/views/content/article/list.vue
Normal file
@@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="container">
|
||||
<el-form inline size="small">
|
||||
<el-form-item>
|
||||
<el-input class="selWidth" v-model="listPram.keywords" placeholder="请输入关键词" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="listPram.cid" clearable placeholder="请选择文章分类">
|
||||
<el-option
|
||||
v-for="item in categoryTreeData"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handerSearch">搜索</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-button size="mini" type="primary" @click="handlerOpenEdit(0)">添加文章</el-button>
|
||||
</div>
|
||||
<el-table :data="listData.list" size="mini"
|
||||
class="table"
|
||||
highlight-current-row>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
min-width="50"
|
||||
/>
|
||||
<el-table-column label="图片" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<div class="demo-image__preview">
|
||||
<el-image
|
||||
style="width: 36px; height: 36px"
|
||||
:src="scope.row.imageInput[0]"
|
||||
:preview-src-list="[scope.row.imageInput[0]]"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="title" label="标题" min-width="180" />
|
||||
<el-table-column prop="visit" label="文章分类" min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.cid | articleTypeFilter }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="visit" label="浏览量" min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.visit | filterEmpty }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="author" label="作者" min-width="180" />
|
||||
<el-table-column prop="synopsis" label="文章简介" show-overflow-tooltip min-width="250"/>
|
||||
<el-table-column prop="shareTitle" label="分享标题" show-overflow-tooltip min-width="200"/>
|
||||
<el-table-column prop="updateTime" label="更新时间" min-width="180"/>
|
||||
<el-table-column label="操作" min-width="180" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handlerOpenEdit(1, scope.row)">编辑</el-button>
|
||||
<el-button type="text" disabled>关联产品</el-button>
|
||||
<el-button type="text" @click="handlerDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="listPram.page"
|
||||
:page-sizes="constants.page.limit"
|
||||
:layout="constants.page.layout"
|
||||
:total="listData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</el-card>
|
||||
<el-dialog
|
||||
:visible.sync="editDialogConfig.visible"
|
||||
:title="editDialogConfig.isEdit === 0?'创建文章':'编辑文章'"
|
||||
top="1vh"
|
||||
width="80%"
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<edit
|
||||
v-if="editDialogConfig.visible"
|
||||
:is-edit="editDialogConfig.isEdit"
|
||||
:edit-data="editDialogConfig.editData"
|
||||
@hideDialog="handlerHideDialog"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as articleApi from '@/api/article.js'
|
||||
import * as categoryApi from '@/api/categoryApi.js'
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import * as selfUtil from '@/utils/ZBKJIutil.js'
|
||||
import edit from './edit'
|
||||
export default {
|
||||
// name: "list",
|
||||
components: { edit },
|
||||
data() {
|
||||
return {
|
||||
constants,
|
||||
listPram: {
|
||||
keywords: null,
|
||||
cid: null,
|
||||
page: 1,
|
||||
limit: constants.page.limit[0]
|
||||
},
|
||||
listData: { list: [], total: 0 },
|
||||
editDialogConfig: {
|
||||
visible: false,
|
||||
data: {},
|
||||
isEdit: 0 // 0=add 1=edit
|
||||
},
|
||||
categoryTreeData: [],
|
||||
categoryProps: {
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
children: 'child',
|
||||
expandTrigger: 'hover',
|
||||
checkStrictly: true,
|
||||
emitPath: false
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handlerGetListData(this.listPram)
|
||||
this.handlerGetTreeList()
|
||||
},
|
||||
methods: {
|
||||
handlerGetTreeList() {
|
||||
categoryApi.listCategroy({ type: 3, status: '' }).then(data => {
|
||||
this.categoryTreeData = data.list
|
||||
localStorage.setItem('articleClass', JSON.stringify(data.list))
|
||||
})
|
||||
},
|
||||
handerSearch() {
|
||||
this.listPram.page = 1
|
||||
this.handlerGetListData(this.listPram)
|
||||
},
|
||||
handlerGetListData(pram) {
|
||||
articleApi.ListArticle(pram).then(data => {
|
||||
this.listData = data
|
||||
})
|
||||
},
|
||||
handlerOpenEdit(isEdit, editData) { // 0=add 1=edit
|
||||
if (isEdit === 1) {
|
||||
this.editDialogConfig.isEdit = 1
|
||||
this.editDialogConfig.editData = editData
|
||||
}else{
|
||||
this.editDialogConfig.isEdit = 0
|
||||
}
|
||||
this.editDialogConfig.visible = true
|
||||
},
|
||||
// handlerGetCategoryTreeData() {
|
||||
// const _pram = { type: constants.categoryType[2].value, status: 1 }
|
||||
// categoryApi.treeCategroy(_pram).then(data => {
|
||||
// this.categoryTreeData = selfUtil.addTreeListLabelForCasCard(data)
|
||||
// })
|
||||
// },
|
||||
handlerHideDialog() {
|
||||
this.handlerGetListData(this.listPram)
|
||||
this.editDialogConfig.visible = false
|
||||
},
|
||||
handlerDelete(rowData) {
|
||||
this.$confirm('确定删除当前数据', '提示').then(result => {
|
||||
articleApi.DelArticle(rowData).then(data => {
|
||||
this.$message.success('删除数据成功')
|
||||
this.handlerGetListData(this.listPram)
|
||||
})
|
||||
})
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.listPram.limit = val
|
||||
this.handlerGetListData(this.listPram)
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.listPram.page = val
|
||||
this.handlerGetListData(this.listPram)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
23
admin/src/views/content/articleclass/list.vue
Normal file
23
admin/src/views/content/articleclass/list.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<category-list :biztype="constants.categoryType[2]" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import categoryList from '@/components/Category/list'
|
||||
import * as constants from '@/utils/constants.js'
|
||||
export default {
|
||||
// name: "list",
|
||||
components: { categoryList },
|
||||
data() {
|
||||
return {
|
||||
constants
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
102
admin/src/views/dashboard/admin/components/BarChart.vue
Normal file
102
admin/src/views/dashboard/admin/components/BarChart.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<div :class="className" :style="{height:height,width:width}" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import resize from './mixins/resize'
|
||||
|
||||
const animationDuration = 6000
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '300px'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.initChart()
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
return
|
||||
}
|
||||
this.chart.dispose()
|
||||
this.chart = null
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
this.chart = echarts.init(this.$el, 'macarons')
|
||||
|
||||
this.chart.setOption({
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { // 坐标轴指示器,坐标轴触发有效
|
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
top: 10,
|
||||
left: '2%',
|
||||
right: '2%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [{
|
||||
type: 'category',
|
||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||
axisTick: {
|
||||
alignWithLabel: true
|
||||
}
|
||||
}],
|
||||
yAxis: [{
|
||||
type: 'value',
|
||||
axisTick: {
|
||||
show: false
|
||||
}
|
||||
}],
|
||||
series: [{
|
||||
name: 'pageA',
|
||||
type: 'bar',
|
||||
stack: 'vistors',
|
||||
barWidth: '60%',
|
||||
data: [79, 52, 200, 334, 390, 330, 220],
|
||||
animationDuration
|
||||
}, {
|
||||
name: 'pageB',
|
||||
type: 'bar',
|
||||
stack: 'vistors',
|
||||
barWidth: '60%',
|
||||
data: [80, 52, 200, 334, 390, 330, 220],
|
||||
animationDuration
|
||||
}, {
|
||||
name: 'pageC',
|
||||
type: 'bar',
|
||||
stack: 'vistors',
|
||||
barWidth: '60%',
|
||||
data: [30, 52, 200, 334, 390, 330, 220],
|
||||
animationDuration
|
||||
}]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
118
admin/src/views/dashboard/admin/components/BoxCard.vue
Normal file
118
admin/src/views/dashboard/admin/components/BoxCard.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<el-card class="box-card-component" style="margin-left:8px;">
|
||||
<div slot="header" class="box-card-header">
|
||||
<img src="https://wpimg.wallstcn.com/e7d23d71-cf19-4b90-a1cc-f56af8c0903d.png">
|
||||
</div>
|
||||
<div style="position:relative;">
|
||||
<pan-thumb :image="avatar" class="panThumb" />
|
||||
<mallki class-name="mallki-text" text="vue-element-admin" />
|
||||
<div style="padding-top:35px;" class="progress-item">
|
||||
<span>Vue</span>
|
||||
<el-progress :percentage="70" />
|
||||
</div>
|
||||
<div class="progress-item">
|
||||
<span>JavaScript</span>
|
||||
<el-progress :percentage="18" />
|
||||
</div>
|
||||
<div class="progress-item">
|
||||
<span>Css</span>
|
||||
<el-progress :percentage="12" />
|
||||
</div>
|
||||
<div class="progress-item">
|
||||
<span>ESLint</span>
|
||||
<el-progress :percentage="100" status="success" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import PanThumb from '@/components/PanThumb'
|
||||
import Mallki from '@/components/TextHoverEffect/Mallki'
|
||||
|
||||
export default {
|
||||
components: { PanThumb, Mallki },
|
||||
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
success: 'success',
|
||||
pending: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
statisticsData: {
|
||||
article_count: 1024,
|
||||
pageviews_count: 1024
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'name',
|
||||
'avatar',
|
||||
'roles'
|
||||
])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box-card-component{
|
||||
.el-card__header {
|
||||
padding: 0px!important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.box-card-component {
|
||||
.box-card-header {
|
||||
position: relative;
|
||||
height: 220px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: all 0.2s linear;
|
||||
&:hover {
|
||||
transform: scale(1.1, 1.1);
|
||||
filter: contrast(130%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.mallki-text {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.panThumb {
|
||||
z-index: 100;
|
||||
height: 70px!important;
|
||||
width: 70px!important;
|
||||
position: absolute!important;
|
||||
top: -45px;
|
||||
left: 0px;
|
||||
border: 5px solid #ffffff;
|
||||
background-color: #fff;
|
||||
margin: auto;
|
||||
box-shadow: none!important;
|
||||
/deep/ .pan-info {
|
||||
box-shadow: none!important;
|
||||
}
|
||||
}
|
||||
.progress-item {
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
@media only screen and (max-width: 1510px){
|
||||
.mallki-text{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
135
admin/src/views/dashboard/admin/components/LineChart.vue
Normal file
135
admin/src/views/dashboard/admin/components/LineChart.vue
Normal file
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<div :class="className" :style="{height:height,width:width}" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import resize from './mixins/resize'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '350px'
|
||||
},
|
||||
autoResize: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
chartData: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
chartData: {
|
||||
deep: true,
|
||||
handler(val) {
|
||||
this.setOptions(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.initChart()
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
return
|
||||
}
|
||||
this.chart.dispose()
|
||||
this.chart = null
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
this.chart = echarts.init(this.$el, 'macarons')
|
||||
this.setOptions(this.chartData)
|
||||
},
|
||||
setOptions({ expectedData, actualData } = {}) {
|
||||
this.chart.setOption({
|
||||
xAxis: {
|
||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||
boundaryGap: false,
|
||||
axisTick: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: 10,
|
||||
right: 10,
|
||||
bottom: 20,
|
||||
top: 30,
|
||||
containLabel: true
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross'
|
||||
},
|
||||
padding: [5, 10]
|
||||
},
|
||||
yAxis: {
|
||||
axisTick: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['expected', 'actual']
|
||||
},
|
||||
series: [{
|
||||
name: 'expected', itemStyle: {
|
||||
normal: {
|
||||
color: '#FF005A',
|
||||
lineStyle: {
|
||||
color: '#FF005A',
|
||||
width: 2
|
||||
}
|
||||
}
|
||||
},
|
||||
smooth: true,
|
||||
type: 'line',
|
||||
data: expectedData,
|
||||
animationDuration: 2800,
|
||||
animationEasing: 'cubicInOut'
|
||||
},
|
||||
{
|
||||
name: 'actual',
|
||||
smooth: true,
|
||||
type: 'line',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#3888fa',
|
||||
lineStyle: {
|
||||
color: '#3888fa',
|
||||
width: 2
|
||||
},
|
||||
areaStyle: {
|
||||
color: '#f3f8ff'
|
||||
}
|
||||
}
|
||||
},
|
||||
data: actualData,
|
||||
animationDuration: 2800,
|
||||
animationEasing: 'quadraticOut'
|
||||
}]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
181
admin/src/views/dashboard/admin/components/PanelGroup.vue
Normal file
181
admin/src/views/dashboard/admin/components/PanelGroup.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<el-row :gutter="40" class="panel-group">
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('newVisitis')">
|
||||
<div class="card-panel-icon-wrapper icon-people">
|
||||
<svg-icon icon-class="peoples" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
New Visits
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('messages')">
|
||||
<div class="card-panel-icon-wrapper icon-message">
|
||||
<svg-icon icon-class="message" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
Messages
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('purchases')">
|
||||
<div class="card-panel-icon-wrapper icon-money">
|
||||
<svg-icon icon-class="money" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
Purchases
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
|
||||
<div class="card-panel" @click="handleSetLineChartData('shoppings')">
|
||||
<div class="card-panel-icon-wrapper icon-shopping">
|
||||
<svg-icon icon-class="shopping" class-name="card-panel-icon" />
|
||||
</div>
|
||||
<div class="card-panel-description">
|
||||
<div class="card-panel-text">
|
||||
Shoppings
|
||||
</div>
|
||||
<count-to :start-val="0" :end-val="13600" :duration="3600" class="card-panel-num" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CountTo from 'vue-count-to'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CountTo
|
||||
},
|
||||
methods: {
|
||||
handleSetLineChartData(type) {
|
||||
this.$emit('handleSetLineChartData', type)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.panel-group {
|
||||
margin-top: 18px;
|
||||
|
||||
.card-panel-col {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.card-panel {
|
||||
height: 108px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
color: #666;
|
||||
background: #fff;
|
||||
box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
|
||||
border-color: rgba(0, 0, 0, .05);
|
||||
|
||||
&:hover {
|
||||
.card-panel-icon-wrapper {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.icon-people {
|
||||
background: #40c9c6;
|
||||
}
|
||||
|
||||
.icon-message {
|
||||
background: #36a3f7;
|
||||
}
|
||||
|
||||
.icon-money {
|
||||
background: #f4516c;
|
||||
}
|
||||
|
||||
.icon-shopping {
|
||||
background: #34bfa3
|
||||
}
|
||||
}
|
||||
|
||||
.icon-people {
|
||||
color: #40c9c6;
|
||||
}
|
||||
|
||||
.icon-message {
|
||||
color: #36a3f7;
|
||||
}
|
||||
|
||||
.icon-money {
|
||||
color: #f4516c;
|
||||
}
|
||||
|
||||
.icon-shopping {
|
||||
color: #34bfa3
|
||||
}
|
||||
|
||||
.card-panel-icon-wrapper {
|
||||
float: left;
|
||||
margin: 14px 0 0 14px;
|
||||
padding: 16px;
|
||||
transition: all 0.38s ease-out;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.card-panel-icon {
|
||||
float: left;
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.card-panel-description {
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin: 26px;
|
||||
margin-left: 0px;
|
||||
|
||||
.card-panel-text {
|
||||
line-height: 18px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
font-size: 16px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.card-panel-num {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:550px) {
|
||||
.card-panel-description {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.card-panel-icon-wrapper {
|
||||
float: none !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0 !important;
|
||||
|
||||
.svg-icon {
|
||||
display: block;
|
||||
margin: 14px auto !important;
|
||||
float: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
79
admin/src/views/dashboard/admin/components/PieChart.vue
Normal file
79
admin/src/views/dashboard/admin/components/PieChart.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div :class="className" :style="{height:height,width:width}" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import resize from './mixins/resize'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '300px'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.initChart()
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
return
|
||||
}
|
||||
this.chart.dispose()
|
||||
this.chart = null
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
this.chart = echarts.init(this.$el, 'macarons')
|
||||
|
||||
this.chart.setOption({
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
left: 'center',
|
||||
bottom: '10',
|
||||
data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts']
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'WEEKLY WRITE ARTICLES',
|
||||
type: 'pie',
|
||||
roseType: 'radius',
|
||||
radius: [15, 95],
|
||||
center: ['50%', '38%'],
|
||||
data: [
|
||||
{ value: 320, name: 'Industries' },
|
||||
{ value: 240, name: 'Technology' },
|
||||
{ value: 149, name: 'Forex' },
|
||||
{ value: 100, name: 'Gold' },
|
||||
{ value: 59, name: 'Forecasts' }
|
||||
],
|
||||
animationEasing: 'cubicInOut',
|
||||
animationDuration: 2600
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
116
admin/src/views/dashboard/admin/components/RaddarChart.vue
Normal file
116
admin/src/views/dashboard/admin/components/RaddarChart.vue
Normal file
@@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<div :class="className" :style="{height:height,width:width}" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
require('echarts/theme/macarons') // echarts theme
|
||||
import resize from './mixins/resize'
|
||||
|
||||
const animationDuration = 3000
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '300px'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.initChart()
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
return
|
||||
}
|
||||
this.chart.dispose()
|
||||
this.chart = null
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
this.chart = echarts.init(this.$el, 'macarons')
|
||||
|
||||
this.chart.setOption({
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { // 坐标轴指示器,坐标轴触发有效
|
||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||||
}
|
||||
},
|
||||
radar: {
|
||||
radius: '66%',
|
||||
center: ['50%', '42%'],
|
||||
splitNumber: 8,
|
||||
splitArea: {
|
||||
areaStyle: {
|
||||
color: 'rgba(127,95,132,.3)',
|
||||
opacity: 1,
|
||||
shadowBlur: 45,
|
||||
shadowColor: 'rgba(0,0,0,.5)',
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetY: 15
|
||||
}
|
||||
},
|
||||
indicator: [
|
||||
{ name: 'Sales', max: 10000 },
|
||||
{ name: 'Administration', max: 20000 },
|
||||
{ name: 'Information Technology', max: 20000 },
|
||||
{ name: 'Customer Support', max: 20000 },
|
||||
{ name: 'Development', max: 20000 },
|
||||
{ name: 'Marketing', max: 20000 }
|
||||
]
|
||||
},
|
||||
legend: {
|
||||
left: 'center',
|
||||
bottom: '10',
|
||||
data: ['Allocated Budget', 'Expected Spending', 'Actual Spending']
|
||||
},
|
||||
series: [{
|
||||
type: 'radar',
|
||||
symbolSize: 0,
|
||||
areaStyle: {
|
||||
normal: {
|
||||
shadowBlur: 13,
|
||||
shadowColor: 'rgba(0,0,0,.2)',
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetY: 10,
|
||||
opacity: 1
|
||||
}
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: [5000, 7000, 12000, 11000, 15000, 14000],
|
||||
name: 'Allocated Budget'
|
||||
},
|
||||
{
|
||||
value: [4000, 9000, 15000, 15000, 13000, 11000],
|
||||
name: 'Expected Spending'
|
||||
},
|
||||
{
|
||||
value: [5500, 11000, 12000, 15000, 12000, 12000],
|
||||
name: 'Actual Spending'
|
||||
}
|
||||
],
|
||||
animationDuration: animationDuration
|
||||
}]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
81
admin/src/views/dashboard/admin/components/TodoList/Todo.vue
Normal file
81
admin/src/views/dashboard/admin/components/TodoList/Todo.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<li :class="{ completed: todo.done, editing: editing }" class="todo">
|
||||
<div class="view">
|
||||
<input
|
||||
:checked="todo.done"
|
||||
class="toggle"
|
||||
type="checkbox"
|
||||
@change="toggleTodo( todo)"
|
||||
>
|
||||
<label @dblclick="editing = true" v-text="todo.text" />
|
||||
<button class="destroy" @click="deleteTodo( todo )" />
|
||||
</div>
|
||||
<input
|
||||
v-show="editing"
|
||||
v-focus="editing"
|
||||
:value="todo.text"
|
||||
class="edit"
|
||||
@keyup.enter="doneEdit"
|
||||
@keyup.esc="cancelEdit"
|
||||
@blur="doneEdit"
|
||||
>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Todo',
|
||||
directives: {
|
||||
focus(el, { value }, { context }) {
|
||||
if (value) {
|
||||
context.$nextTick(() => {
|
||||
el.focus()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
todo: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editing: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deleteTodo(todo) {
|
||||
this.$emit('deleteTodo', todo)
|
||||
},
|
||||
editTodo({ todo, value }) {
|
||||
this.$emit('editTodo', { todo, value })
|
||||
},
|
||||
toggleTodo(todo) {
|
||||
this.$emit('toggleTodo', todo)
|
||||
},
|
||||
doneEdit(e) {
|
||||
const value = e.target.value.trim()
|
||||
const { todo } = this
|
||||
if (!value) {
|
||||
this.deleteTodo({
|
||||
todo
|
||||
})
|
||||
} else if (this.editing) {
|
||||
this.editTodo({
|
||||
todo,
|
||||
value
|
||||
})
|
||||
this.editing = false
|
||||
}
|
||||
},
|
||||
cancelEdit(e) {
|
||||
e.target.value = this.todo.text
|
||||
this.editing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
320
admin/src/views/dashboard/admin/components/TodoList/index.scss
Normal file
320
admin/src/views/dashboard/admin/components/TodoList/index.scss
Normal file
@@ -0,0 +1,320 @@
|
||||
.todoapp {
|
||||
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
line-height: 1.4em;
|
||||
color: #4d4d4d;
|
||||
min-width: 230px;
|
||||
max-width: 550px;
|
||||
margin: 0 auto ;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-weight: 300;
|
||||
background: #fff;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
color: inherit;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
:focus {
|
||||
outline: 0;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.todoapp {
|
||||
background: #fff;
|
||||
margin: 130px 0 40px 0;
|
||||
position: relative;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.todoapp input::-webkit-input-placeholder {
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
.todoapp input::-moz-placeholder {
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
.todoapp input::input-placeholder {
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
.todoapp h1 {
|
||||
position: absolute;
|
||||
top: -155px;
|
||||
width: 100%;
|
||||
font-size: 100px;
|
||||
font-weight: 100;
|
||||
text-align: center;
|
||||
color: rgba(175, 47, 47, 0.15);
|
||||
-webkit-text-rendering: optimizeLegibility;
|
||||
-moz-text-rendering: optimizeLegibility;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
.new-todo,
|
||||
.edit {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: 18px;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: 1.4em;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
padding: 6px;
|
||||
border: 1px solid #999;
|
||||
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
box-sizing: border-box;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
.new-todo {
|
||||
padding: 10px 16px 16px 60px;
|
||||
border: none;
|
||||
background: rgba(0, 0, 0, 0.003);
|
||||
box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
.main {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
border-top: 1px solid #e6e6e6;
|
||||
}
|
||||
.toggle-all {
|
||||
text-align: center;
|
||||
border: none;
|
||||
/* Mobile Safari */
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
}
|
||||
.toggle-all+label {
|
||||
width: 60px;
|
||||
height: 34px;
|
||||
font-size: 0;
|
||||
position: absolute;
|
||||
top: -52px;
|
||||
left: -13px;
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.toggle-all+label:before {
|
||||
content: '❯';
|
||||
font-size: 22px;
|
||||
color: #e6e6e6;
|
||||
padding: 10px 27px 10px 27px;
|
||||
}
|
||||
.toggle-all:checked+label:before {
|
||||
color: #737373;
|
||||
}
|
||||
.todo-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.todo-list li {
|
||||
position: relative;
|
||||
font-size: 24px;
|
||||
border-bottom: 1px solid #ededed;
|
||||
}
|
||||
.todo-list li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.todo-list li.editing {
|
||||
border-bottom: none;
|
||||
padding: 0;
|
||||
}
|
||||
.todo-list li.editing .edit {
|
||||
display: block;
|
||||
width: 506px;
|
||||
padding: 12px 16px;
|
||||
margin: 0 0 0 43px;
|
||||
}
|
||||
.todo-list li.editing .view {
|
||||
display: none;
|
||||
}
|
||||
.todo-list li .toggle {
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
/* auto, since non-WebKit browsers doesn't support input styling */
|
||||
height: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto 0;
|
||||
border: none;
|
||||
/* Mobile Safari */
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
.todo-list li .toggle {
|
||||
opacity: 0;
|
||||
}
|
||||
.todo-list li .toggle+label {
|
||||
/*
|
||||
Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
|
||||
IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
|
||||
*/
|
||||
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center left;
|
||||
background-size: 36px;
|
||||
}
|
||||
.todo-list li .toggle:checked+label {
|
||||
background-size: 36px;
|
||||
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
|
||||
}
|
||||
.todo-list li label {
|
||||
word-break: break-all;
|
||||
padding: 15px 15px 15px 50px;
|
||||
display: block;
|
||||
line-height: 1.0;
|
||||
font-size: 14px;
|
||||
transition: color 0.4s;
|
||||
}
|
||||
.todo-list li.completed label {
|
||||
color: #d9d9d9;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.todo-list li .destroy {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 10px;
|
||||
bottom: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: auto 0;
|
||||
font-size: 30px;
|
||||
color: #cc9a9a;
|
||||
transition: color 0.2s ease-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
.todo-list li .destroy:hover {
|
||||
color: #af5b5e;
|
||||
}
|
||||
.todo-list li .destroy:after {
|
||||
content: '×';
|
||||
}
|
||||
.todo-list li:hover .destroy {
|
||||
display: block;
|
||||
}
|
||||
.todo-list li .edit {
|
||||
display: none;
|
||||
}
|
||||
.todo-list li.editing:last-child {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
.footer {
|
||||
color: #777;
|
||||
position: relative;
|
||||
padding: 10px 15px;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e6e6e6;
|
||||
}
|
||||
.footer:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 40px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6, 0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6, 0 17px 2px -6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.todo-count {
|
||||
float: left;
|
||||
text-align: left;
|
||||
}
|
||||
.todo-count strong {
|
||||
font-weight: 300;
|
||||
}
|
||||
.filters {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
list-style: none;
|
||||
}
|
||||
.filters li {
|
||||
display: inline;
|
||||
}
|
||||
.filters li a {
|
||||
color: inherit;
|
||||
font-size: 12px;
|
||||
padding: 3px 7px;
|
||||
text-decoration: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.filters li a:hover {
|
||||
border-color: rgba(175, 47, 47, 0.1);
|
||||
}
|
||||
.filters li a.selected {
|
||||
border-color: rgba(175, 47, 47, 0.2);
|
||||
}
|
||||
.clear-completed,
|
||||
html .clear-completed:active {
|
||||
float: right;
|
||||
position: relative;
|
||||
line-height: 20px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.clear-completed:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.info {
|
||||
margin: 65px auto 0;
|
||||
color: #bfbfbf;
|
||||
font-size: 10px;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||
text-align: center;
|
||||
}
|
||||
.info p {
|
||||
line-height: 1;
|
||||
}
|
||||
.info a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-weight: 400;
|
||||
}
|
||||
.info a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
/*
|
||||
Hack to remove background from Mobile Safari.
|
||||
Can't use it globally since it destroys checkboxes in Firefox
|
||||
*/
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
.toggle-all,
|
||||
.todo-list li .toggle {
|
||||
background: none;
|
||||
}
|
||||
.todo-list li .toggle {
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 430px) {
|
||||
.footer {
|
||||
height: 50px;
|
||||
}
|
||||
.filters {
|
||||
bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
127
admin/src/views/dashboard/admin/components/TodoList/index.vue
Normal file
127
admin/src/views/dashboard/admin/components/TodoList/index.vue
Normal file
@@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<section class="todoapp">
|
||||
<!-- header -->
|
||||
<header class="header">
|
||||
<input class="new-todo" autocomplete="off" placeholder="Todo List" @keyup.enter="addTodo">
|
||||
</header>
|
||||
<!-- main section -->
|
||||
<section v-show="todos.length" class="main">
|
||||
<input id="toggle-all" :checked="allChecked" class="toggle-all" type="checkbox" @change="toggleAll({ done: !allChecked })">
|
||||
<label for="toggle-all" />
|
||||
<ul class="todo-list">
|
||||
<todo
|
||||
v-for="(todo, index) in filteredTodos"
|
||||
:key="index"
|
||||
:todo="todo"
|
||||
@toggleTodo="toggleTodo"
|
||||
@editTodo="editTodo"
|
||||
@deleteTodo="deleteTodo"
|
||||
/>
|
||||
</ul>
|
||||
</section>
|
||||
<!-- footer -->
|
||||
<footer v-show="todos.length" class="footer">
|
||||
<span class="todo-count">
|
||||
<strong>{{ remaining }}</strong>
|
||||
{{ remaining | pluralize('item') }} left
|
||||
</span>
|
||||
<ul class="filters">
|
||||
<li v-for="(val, key) in filters" :key="key">
|
||||
<a :class="{ selected: visibility === key }" @click.prevent="visibility = key">{{ key | capitalize }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- <button class="clear-completed" v-show="todos.length > remaining" @click="clearCompleted">
|
||||
Clear completed
|
||||
</button> -->
|
||||
</footer>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Todo from './Todo.vue'
|
||||
|
||||
const STORAGE_KEY = 'todos'
|
||||
const filters = {
|
||||
all: todos => todos,
|
||||
active: todos => todos.filter(todo => !todo.done),
|
||||
completed: todos => todos.filter(todo => todo.done)
|
||||
}
|
||||
const defalutList = [
|
||||
{ text: 'star this repository', done: false },
|
||||
{ text: 'fork this repository', done: false },
|
||||
{ text: 'follow author', done: false },
|
||||
{ text: 'vue-element-admin', done: true },
|
||||
{ text: 'vue', done: true },
|
||||
{ text: 'element-ui', done: true },
|
||||
{ text: 'axios', done: true },
|
||||
{ text: 'webpack', done: true }
|
||||
]
|
||||
export default {
|
||||
components: { Todo },
|
||||
filters: {
|
||||
pluralize: (n, w) => n === 1 ? w : w + 's',
|
||||
capitalize: s => s.charAt(0).toUpperCase() + s.slice(1)
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visibility: 'all',
|
||||
filters,
|
||||
// todos: JSON.parse(window.localStorage.getItem(STORAGE_KEY)) || defalutList
|
||||
todos: defalutList
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
allChecked() {
|
||||
return this.todos.every(todo => todo.done)
|
||||
},
|
||||
filteredTodos() {
|
||||
return filters[this.visibility](this.todos)
|
||||
},
|
||||
remaining() {
|
||||
return this.todos.filter(todo => !todo.done).length
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setLocalStorage() {
|
||||
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(this.todos))
|
||||
},
|
||||
addTodo(e) {
|
||||
const text = e.target.value
|
||||
if (text.trim()) {
|
||||
this.todos.push({
|
||||
text,
|
||||
done: false
|
||||
})
|
||||
this.setLocalStorage()
|
||||
}
|
||||
e.target.value = ''
|
||||
},
|
||||
toggleTodo(val) {
|
||||
val.done = !val.done
|
||||
this.setLocalStorage()
|
||||
},
|
||||
deleteTodo(todo) {
|
||||
this.todos.splice(this.todos.indexOf(todo), 1)
|
||||
this.setLocalStorage()
|
||||
},
|
||||
editTodo({ todo, value }) {
|
||||
todo.text = value
|
||||
this.setLocalStorage()
|
||||
},
|
||||
clearCompleted() {
|
||||
this.todos = this.todos.filter(todo => !todo.done)
|
||||
this.setLocalStorage()
|
||||
},
|
||||
toggleAll({ done }) {
|
||||
this.todos.forEach(todo => {
|
||||
todo.done = done
|
||||
this.setLocalStorage()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
||||
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<el-table :data="list" style="width: 100%;padding-top: 15px;">
|
||||
<el-table-column label="Order_No" min-width="200">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.order_no | orderNoFilter }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Price" width="195" align="center">
|
||||
<template slot-scope="scope">
|
||||
¥{{ scope.row.price | toThousandFilter }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Status" width="100" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag :type="row.status | statusFilter">
|
||||
{{ row.status }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { transactionList } from '@/api/remote-search'
|
||||
|
||||
export default {
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
success: 'success',
|
||||
pending: 'danger'
|
||||
}
|
||||
return statusMap[status]
|
||||
},
|
||||
orderNoFilter(str) {
|
||||
return str.substring(0, 30)
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: null
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
transactionList().then(response => {
|
||||
this.list = response.data.items.slice(0, 8)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
55
admin/src/views/dashboard/admin/components/mixins/resize.js
Normal file
55
admin/src/views/dashboard/admin/components/mixins/resize.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
$_sidebarElm: null,
|
||||
$_resizeHandler: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$_resizeHandler = debounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
}, 100)
|
||||
this.$_initResizeEvent()
|
||||
this.$_initSidebarResizeEvent()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$_destroyResizeEvent()
|
||||
this.$_destroySidebarResizeEvent()
|
||||
},
|
||||
// to fixed bug when cached by keep-alive
|
||||
// https://github.com/PanJiaChen/vue-element-admin/issues/2116
|
||||
activated() {
|
||||
this.$_initResizeEvent()
|
||||
this.$_initSidebarResizeEvent()
|
||||
},
|
||||
deactivated() {
|
||||
this.$_destroyResizeEvent()
|
||||
this.$_destroySidebarResizeEvent()
|
||||
},
|
||||
methods: {
|
||||
// use $_ for mixins properties
|
||||
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
||||
$_initResizeEvent() {
|
||||
window.addEventListener('resize', this.$_resizeHandler)
|
||||
},
|
||||
$_destroyResizeEvent() {
|
||||
window.removeEventListener('resize', this.$_resizeHandler)
|
||||
},
|
||||
$_sidebarResizeHandler(e) {
|
||||
if (e.propertyName === 'width') {
|
||||
this.$_resizeHandler()
|
||||
}
|
||||
},
|
||||
$_initSidebarResizeEvent() {
|
||||
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
||||
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
|
||||
},
|
||||
$_destroySidebarResizeEvent() {
|
||||
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
120
admin/src/views/dashboard/admin/index.vue
Normal file
120
admin/src/views/dashboard/admin/index.vue
Normal file
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="dashboard-editor-container">
|
||||
<panel-group @handleSetLineChartData="handleSetLineChartData" />
|
||||
|
||||
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
|
||||
<line-chart :chart-data="lineChartData" />
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="32">
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<raddar-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<pie-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="24" :lg="8">
|
||||
<div class="chart-wrapper">
|
||||
<bar-chart />
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="8">
|
||||
<el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;">
|
||||
<transaction-table />
|
||||
</el-col>
|
||||
<el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
|
||||
<todo-list />
|
||||
</el-col>
|
||||
<el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
|
||||
<box-card />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PanelGroup from './components/PanelGroup'
|
||||
import LineChart from './components/LineChart'
|
||||
import RaddarChart from './components/RaddarChart'
|
||||
import PieChart from './components/PieChart'
|
||||
import BarChart from './components/BarChart'
|
||||
import TransactionTable from './components/TransactionTable'
|
||||
import TodoList from './components/TodoList'
|
||||
import BoxCard from './components/BoxCard'
|
||||
|
||||
const lineChartData = {
|
||||
newVisitis: {
|
||||
expectedData: [100, 120, 161, 134, 105, 160, 165],
|
||||
actualData: [120, 82, 91, 154, 162, 140, 145]
|
||||
},
|
||||
messages: {
|
||||
expectedData: [200, 192, 120, 144, 160, 130, 140],
|
||||
actualData: [180, 160, 151, 106, 145, 150, 130]
|
||||
},
|
||||
purchases: {
|
||||
expectedData: [80, 100, 121, 104, 105, 90, 100],
|
||||
actualData: [120, 90, 100, 138, 142, 130, 130]
|
||||
},
|
||||
shoppings: {
|
||||
expectedData: [130, 140, 141, 142, 145, 150, 160],
|
||||
actualData: [120, 82, 91, 154, 162, 140, 130]
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'DashboardAdmin',
|
||||
components: {
|
||||
PanelGroup,
|
||||
LineChart,
|
||||
RaddarChart,
|
||||
PieChart,
|
||||
BarChart,
|
||||
TransactionTable,
|
||||
TodoList,
|
||||
BoxCard
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
lineChartData: lineChartData.newVisitis
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSetLineChartData(type) {
|
||||
this.lineChartData = lineChartData[type]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dashboard-editor-container {
|
||||
padding: 32px;
|
||||
background-color: rgb(240, 242, 245);
|
||||
position: relative;
|
||||
|
||||
.github-corner {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
border: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.chart-wrapper {
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:1024px) {
|
||||
.chart-wrapper {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
176
admin/src/views/dashboard/components/baseInfo.vue
Normal file
176
admin/src/views/dashboard/components/baseInfo.vue
Normal file
@@ -0,0 +1,176 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-row :gutter="24" class="baseInfo">
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false" dis-hover :padding="12">
|
||||
<div slot="header" class="acea-row row-between-wrapper">
|
||||
<span>销售额</span>
|
||||
<el-tag type="success">昨日</el-tag>
|
||||
</div>
|
||||
<div class="content" v-if="sales">
|
||||
<span class="content-number spBlock mb15">{{ sales.count }}</span>
|
||||
<div>
|
||||
<span class="content-time mr20">日同比:<i class="content-is" :class="Number(sales.dayRate)>=0?'up':'down'">{{ sales.dayRate }}</i><i :class="Number(sales.dayRate)>=0?'el-icon-caret-top':'el-icon-caret-bottom'" /></span>
|
||||
<span class="content-time">周同比:<i class="content-is" :class="Number(sales.weekRate)>=0?'up':'down'">{{ sales.weekRate }}</i><i :class="Number(sales.weekRate)>=0?'el-icon-caret-top':'el-icon-caret-bottom'" /></span>
|
||||
</div>
|
||||
<el-divider></el-divider>
|
||||
<div class="acea-row row-between-wrapper">
|
||||
<span class="content-time">总销售额</span>
|
||||
<span>{{sales.total}} 元</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false" dis-hover :padding="12">
|
||||
<div slot="header" class="acea-row row-between-wrapper">
|
||||
<span>用户量访问</span>
|
||||
<el-tag type="success">昨日</el-tag>
|
||||
</div>
|
||||
<div class="content" v-if="views">
|
||||
<span class="content-number spBlock mb15">{{ views.count }}</span>
|
||||
<div>
|
||||
<span class="content-time mr20">日同比:<i class="content-is" :class="Number(views.dayRate)>=0?'up':'down'">{{ views.dayRate }}</i><i :class="Number(views.dayRate)>=0?'el-icon-caret-top':'el-icon-caret-bottom'" /></span>
|
||||
<span class="content-time">周同比:<i class="content-is" :class="Number(views.weekRate)>=0?'up':'down'">{{ views.weekRate }}</i><i :class="Number(views.weekRate)>=0?'el-icon-caret-top':'el-icon-caret-bottom'" /></span>
|
||||
</div>
|
||||
<el-divider></el-divider>
|
||||
<div class="acea-row row-between-wrapper">
|
||||
<span class="content-time">总访问量</span>
|
||||
<span>{{ views.total }} Pv</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false" dis-hover :padding="12">
|
||||
<div slot="header" class="acea-row row-between-wrapper">
|
||||
<span>订单量</span>
|
||||
<el-tag type="success">昨日</el-tag>
|
||||
</div>
|
||||
<div class="content" v-if="order">
|
||||
<span class="content-number spBlock mb15">{{ order.count }}</span>
|
||||
<div>
|
||||
<span class="content-time mr20">日同比:<i class="content-is" :class="Number(order.dayRate)>=0?'up':'down'">{{ order.dayRate }}</i><i :class="Number(order.dayRate)>=0?'el-icon-caret-top':'el-icon-caret-bottom'" /></span>
|
||||
<span class="content-time">周同比:<i class="content-is" :class="Number(order.weekRate)>=0?'up':'down'">{{ order.weekRate }}</i><i :class="Number(order.weekRate)>=0?'el-icon-caret-top':'el-icon-caret-bottom'" /></span>
|
||||
</div>
|
||||
<el-divider></el-divider>
|
||||
<div class="acea-row row-between-wrapper">
|
||||
<span class="content-time">总订单量</span>
|
||||
<span>{{ order.total }} 单</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false" dis-hover :padding="12">
|
||||
<div slot="header" class="acea-row row-between-wrapper">
|
||||
<span>新增用户</span>
|
||||
<el-tag type="success">昨日</el-tag>
|
||||
</div>
|
||||
<div class="content" v-if="user">
|
||||
<span class="content-number spBlock mb15">{{ user.count }}</span>
|
||||
<div>
|
||||
<span class="content-time mr20">日同比:<i class="content-is" :class="Number(user.dayRate)>=0?'up':'down'">{{ user.dayRate }}</i><i :class="Number(user.dayRate)>=0?'el-icon-caret-top':'el-icon-caret-bottom'" /></span>
|
||||
<span class="content-time">周同比:<i class="content-is" :class="Number(user.weekRate)>=0?'up':'down'">{{ user.weekRate }}</i><i :class="Number(user.weekRate)>=0?'el-icon-caret-top':'el-icon-caret-bottom'" /></span>
|
||||
</div>
|
||||
<el-divider></el-divider>
|
||||
<div class="acea-row row-between-wrapper">
|
||||
<span class="content-time">总用户</span>
|
||||
<span>{{ user.total }} 人</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {statisticsOrderApi, statisticsSalesApi, statisticsUserApi, statisticsViewsApi} from '@/api/dashboard'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
infoList: [],
|
||||
grid: {
|
||||
xl: 6,
|
||||
lg: 6,
|
||||
md: 12,
|
||||
sm: 12,
|
||||
xs: 24
|
||||
},
|
||||
excessStyle: {
|
||||
color: '#f56a00',
|
||||
backgroundColor: '#fde3cf'
|
||||
},
|
||||
avatarList: [],
|
||||
sales: null,
|
||||
order: null,
|
||||
user: null,
|
||||
views: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 订单量
|
||||
statisticsOrder() {
|
||||
statisticsOrderApi().then(async res => {
|
||||
this.order = res
|
||||
})
|
||||
},
|
||||
// 销售额
|
||||
statisticsSales() {
|
||||
statisticsSalesApi().then(async res => {
|
||||
this.sales = res
|
||||
})
|
||||
},
|
||||
// 新增用户
|
||||
statisticsUser() {
|
||||
statisticsUserApi().then(async res => {
|
||||
this.user = res
|
||||
})
|
||||
},
|
||||
// 用户访问量
|
||||
statisticsViews() {
|
||||
statisticsViewsApi().then(async res => {
|
||||
this.views = res
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.statisticsOrder();
|
||||
this.statisticsSales();
|
||||
this.statisticsUser();
|
||||
this.statisticsViews();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.ivu-mb{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.up, .el-icon-caret-top {
|
||||
color: #F5222D;
|
||||
font-size: 12px;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.down, .el-icon-caret-bottom {
|
||||
color: #39C15B;
|
||||
font-size: 12px;
|
||||
opacity: 100% !important;
|
||||
}
|
||||
|
||||
.baseInfo {
|
||||
/deep/ .el-card__header {
|
||||
padding: 15px 20px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
&-number {
|
||||
font-size: 30px;
|
||||
}
|
||||
&-time{
|
||||
font-size:14px;
|
||||
/*color: #8C8C8C;*/
|
||||
}
|
||||
}
|
||||
</style>
|
||||
110
admin/src/views/dashboard/components/gridMenu.vue
Normal file
110
admin/src/views/dashboard/components/gridMenu.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-row :gutter="24" class="dashboard-console-grid">
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false">
|
||||
<router-link :to="{path:'/user/index'}">
|
||||
<i class="el-icon-user" style="color:#69c0ff" />
|
||||
<p>会员管理</p>
|
||||
</router-link>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false">
|
||||
<router-link :to="{path:'/operation/setting'}">
|
||||
<i class="el-icon-setting" style="color:#95de64" />
|
||||
<p>系统设置</p>
|
||||
</router-link>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false">
|
||||
<router-link :to="{path:'/store/index'}">
|
||||
<i class="el-icon-goods" style="color:#ff9c6e" />
|
||||
<p>商品</p>
|
||||
</router-link>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false">
|
||||
<router-link :to="{path:'/order/index'}">
|
||||
<i class="el-icon-s-order" style="color:#b37feb" />
|
||||
<p>订单管理</p>
|
||||
</router-link>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false">
|
||||
<router-link :to="{path:'/operation/systemSms/config'}">
|
||||
<i class="el-icon-message" style="color:#ffd666" />
|
||||
<p>短信配置</p>
|
||||
</router-link>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false">
|
||||
<router-link :to="{path:'/content/articleManager'}">
|
||||
<i class="el-icon-notebook-1" style="color:#5cdbd3" />
|
||||
<p>文章管理</p>
|
||||
</router-link>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false">
|
||||
<router-link :to="{path:'/distribution/index'}">
|
||||
<i class="el-icon-s-finance" style="color:#ff85c0" />
|
||||
<p>分销管理</p>
|
||||
</router-link>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col v-bind="grid" class="ivu-mb">
|
||||
<el-card :bordered="false">
|
||||
<router-link :to="{path:'/marketing/coupon/list'}">
|
||||
<i class="el-icon-s-ticket" style="color:#ffc069" />
|
||||
<p>优惠券</p>
|
||||
</router-link>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
grid: {
|
||||
xl: 3,
|
||||
lg: 6,
|
||||
md: 6,
|
||||
sm: 8,
|
||||
xs: 8
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.ivu-mb{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.divBox {
|
||||
padding: 0 20px !important;
|
||||
}
|
||||
|
||||
.dashboard-console-grid {
|
||||
text-align: center;
|
||||
.ivu-card-body {
|
||||
padding: 0;
|
||||
}
|
||||
i {
|
||||
font-size: 32px;
|
||||
}
|
||||
a {
|
||||
display: block;
|
||||
color: inherit;
|
||||
}
|
||||
p {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
187
admin/src/views/dashboard/components/userChart.vue
Normal file
187
admin/src/views/dashboard/components/userChart.vue
Normal file
@@ -0,0 +1,187 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-row :gutter="24">
|
||||
<el-col :xl="16" :lg="12" :md="24" :sm="24" :xs="24" class="ivu-mb mb10 dashboard-console-visit">
|
||||
<el-card :bordered="false" dis-hover>
|
||||
<div slot="header">
|
||||
<div class="acea-row row-middle">
|
||||
<el-avatar icon="el-icon-s-operation" size="small" style="color:#1890ff;background:#e6f7ff;font-size: 13px"/>
|
||||
<span class="ivu-pl-8">用户</span>
|
||||
</div>
|
||||
</div>
|
||||
<echarts-from ref="userChart" :echartsTitle="line" :xAxis="xAxis" :series="series" v-if="infoList"></echarts-from>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xl="8" :lg="12" :md="24" :sm="24" :xs="24">
|
||||
<el-card :bordered="false" dis-hover class="dashboard-console-visit">
|
||||
<div slot="header">
|
||||
<div class="acea-row row-middle">
|
||||
<el-avatar icon="el-icon-picture-outline-round" size="small" style="color:#1890ff;background:#e6f7ff;font-size: 13px" />
|
||||
<span class="ivu-pl-8">购买用户统计</span>
|
||||
</div>
|
||||
</div>
|
||||
<echarts-from ref="visitChart" :echartsTitle="circle" :legendData="legendData"
|
||||
:series="seriesUser" v-if="chartBuy"></echarts-from>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {chartUserApi, chartBuyApi} from '@/api/dashboard';
|
||||
import echartsFrom from '@/components/echarts/index';
|
||||
|
||||
export default {
|
||||
name: 'user-chart',
|
||||
components: {echartsFrom},
|
||||
data() {
|
||||
return {
|
||||
line: 'line',
|
||||
circle: 'circle',
|
||||
xAxis: [],
|
||||
infoList: {},
|
||||
series: [],
|
||||
xData: [],
|
||||
y1Data: [],
|
||||
y2Data: [],
|
||||
lists: [],
|
||||
bing_data: [],
|
||||
bing_xdata: [],
|
||||
|
||||
legendData: [],
|
||||
seriesUser: [],
|
||||
chartBuy: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 统计
|
||||
getStatistics() {
|
||||
chartUserApi().then(async res => {
|
||||
this.infoList = res
|
||||
let data = []
|
||||
for (let key in res) {
|
||||
data.push(res[key])
|
||||
this.xAxis.push(key)
|
||||
}
|
||||
this.series = [
|
||||
{
|
||||
data: data,
|
||||
name: '人数(人)',
|
||||
type: 'line',
|
||||
tooltip: true,
|
||||
smooth: true,
|
||||
symbol: 'none',
|
||||
areaStyle: {
|
||||
normal: {
|
||||
opacity: 0.2
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
// this.bing_data = res.bing_data;
|
||||
// this.bing_xdata = res.bing_xdata;
|
||||
})
|
||||
},
|
||||
// 用户购买统计
|
||||
getRank() {
|
||||
chartBuyApi().then(async res => {
|
||||
this.chartBuy = res
|
||||
this.legendData = ["未消费用户", "消费一次用户", "留存客户", "回流客户"]
|
||||
this.seriesUser = [{
|
||||
"name": "未消费用户",
|
||||
"value": res.zero,
|
||||
"itemStyle": {
|
||||
"color": "#5cadff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "消费一次用户",
|
||||
"value": res.one,
|
||||
"itemStyle": {
|
||||
"color": "#b37feb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "留存客户",
|
||||
"value": res.history,
|
||||
"itemStyle": {
|
||||
"color": "#19be6b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "回流客户",
|
||||
"value": res.back,
|
||||
"itemStyle": {
|
||||
"color": "#ff9900"
|
||||
}
|
||||
}]
|
||||
})
|
||||
},
|
||||
// 监听页面宽度变化,刷新表格
|
||||
handleResize() {
|
||||
if (this.infoList && this.series.length !== 0) this.$refs.userChart.handleResize();
|
||||
if (this.infoList) this.$refs.visitChart.handleResize();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getStatistics();
|
||||
this.getRank();
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.visitChart) {
|
||||
this.visitChart.dispose();
|
||||
this.visitChart = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.acea-row{
|
||||
/deep/.el-avatar--small {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
.ivu-pl-8{
|
||||
margin-left: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.dashboard-console-visit {
|
||||
/deep/.el-card__header{
|
||||
padding: 14px 20px !important;
|
||||
}
|
||||
ul {
|
||||
li {
|
||||
list-style-type: none;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.trees-coadd {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.scollhide {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
.scollhide::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.names {
|
||||
display: inline-block;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
width: 84%;
|
||||
margin-bottom: -7px;
|
||||
}
|
||||
</style>
|
||||
594
admin/src/views/dashboard/components/visitChart.vue
Normal file
594
admin/src/views/dashboard/components/visitChart.vue
Normal file
@@ -0,0 +1,594 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-row :gutter="24">
|
||||
<el-col san="24" class="ivu-mb">
|
||||
<el-card :bordered="false" class="dashboard-console-visit">
|
||||
<div slot="header">
|
||||
<div class="acea-row row-between-wrapper">
|
||||
<div class="acea-row row-middle">
|
||||
<el-avatar icon="el-icon-s-data" size="small" style="color:#1890ff;background:#e6f7ff;font-size: 13px" />
|
||||
<span class="ivu-pl-8">订单</span>
|
||||
</div>
|
||||
<div class="checkTime">
|
||||
<el-radio-group v-model="visitDate" class="ivu-mr-8">
|
||||
<el-radio label="last30" @change="handleChangeVisitType">30天</el-radio>
|
||||
<el-radio label="week" @change="handleChangeWeek">周</el-radio>
|
||||
<el-radio label="month" @change="handleChangeMonth">月</el-radio>
|
||||
<el-radio label="year" @change="handleChangeYear">年</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h4>订单量趋势</h4>
|
||||
<echarts-from ref="visitChart" :series="series" :xAxis="xAxis" v-if="info"></echarts-from>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { chartOrder30Api, chartOrderWeekApi, chartOrderMonthApi, chartOrderYearApi } from '@/api/dashboard';
|
||||
import echartsFrom from '@/components/echarts/index';
|
||||
|
||||
export default {
|
||||
components: {echartsFrom},
|
||||
data() {
|
||||
return {
|
||||
infoList: null,
|
||||
visitDate: 'last30',
|
||||
series: [],
|
||||
xAxis: [],
|
||||
info: {},
|
||||
legendData: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 时间改变
|
||||
handleChangeVisitType() {
|
||||
this.xAxis = []
|
||||
this.legendData = []
|
||||
chartOrder30Api().then(async res => {
|
||||
this.info = res
|
||||
let pices = []
|
||||
let qualitys = []
|
||||
for (let key in res.price) {
|
||||
pices.push(Number(res.price[key]))
|
||||
this.xAxis.push(key)
|
||||
}
|
||||
for (let key in res.quality) {
|
||||
qualitys.push(Number(res.quality[key]))
|
||||
}
|
||||
this.series = [{
|
||||
"name":"订单金额",
|
||||
"type":"bar",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#69cdff"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#3eb3f7"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#1495eb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": pices
|
||||
},
|
||||
{
|
||||
"name":"订单数",
|
||||
"type":"bar",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#6fdeab"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#44d693"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#2cc981"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": qualitys
|
||||
}]
|
||||
})
|
||||
},
|
||||
handleChangeWeek() {
|
||||
this.xAxis = []
|
||||
this.legendData = []
|
||||
chartOrderWeekApi().then(async res => {
|
||||
this.info = res
|
||||
this.legendData = ["上周金额", "本周金额", "上周订单数", "本周订单数"]
|
||||
let prePrice = []
|
||||
let price = []
|
||||
let qualitys = []
|
||||
let preQuality = []
|
||||
for (let key in res.prePrice) {
|
||||
prePrice.push(Number(res.prePrice[key]))
|
||||
this.xAxis.push(key)
|
||||
}
|
||||
for (let key in res.price) {
|
||||
price.push(Number(res.price[key]))
|
||||
}
|
||||
for (let key in res.preQuality) {
|
||||
preQuality.push(Number(res.preQuality[key]))
|
||||
}
|
||||
for (let key in res.quality) {
|
||||
qualitys.push(Number(res.quality[key]))
|
||||
}
|
||||
this.series = [
|
||||
{
|
||||
"name":"上周金额",
|
||||
"type":"bar",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#69cdff"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#3eb3f7"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#1495eb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": prePrice
|
||||
},
|
||||
{
|
||||
"name":"本周金额",
|
||||
"type":"bar",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#69cdff"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#3eb3f7"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#1495eb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": price
|
||||
},
|
||||
{
|
||||
"name":"上周订单数",
|
||||
"type":"line",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#6fdeab"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#44d693"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#2cc981"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": preQuality
|
||||
},
|
||||
{
|
||||
"name":"本周订单数",
|
||||
"type":"line",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#6fdeab"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#44d693"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#2cc981"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": qualitys
|
||||
}
|
||||
]
|
||||
})
|
||||
},
|
||||
handleChangeMonth() {
|
||||
this.xAxis = []
|
||||
this.legendData = []
|
||||
chartOrderMonthApi().then(async res => {
|
||||
this.info = res
|
||||
this.legendData = ["上月金额", "本月金额", "上月订单数", "本月订单数"]
|
||||
let prePrice = []
|
||||
let price = []
|
||||
let qualitys = []
|
||||
let preQuality = []
|
||||
for (let key in res.prePrice) {
|
||||
prePrice.push(Number(res.prePrice[key]))
|
||||
this.xAxis.push(key)
|
||||
}
|
||||
for (let key in res.price) {
|
||||
price.push(Number(res.price[key]))
|
||||
}
|
||||
for (let key in res.preQuality) {
|
||||
preQuality.push(Number(res.preQuality[key]))
|
||||
}
|
||||
for (let key in res.quality) {
|
||||
qualitys.push(Number(res.quality[key]))
|
||||
}
|
||||
this.series = [
|
||||
{
|
||||
"name":"上月金额",
|
||||
"type":"bar",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#69cdff"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#3eb3f7"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#1495eb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": prePrice
|
||||
},
|
||||
{
|
||||
"name":"本月金额",
|
||||
"type":"bar",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#69cdff"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#3eb3f7"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#1495eb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": price
|
||||
},
|
||||
{
|
||||
"name":"上月订单数",
|
||||
"type":"line",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#6fdeab"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#44d693"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#2cc981"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": preQuality
|
||||
},
|
||||
{
|
||||
"name":"本月订单数",
|
||||
"type":"line",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#6fdeab"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#44d693"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#2cc981"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": qualitys
|
||||
}
|
||||
]
|
||||
})
|
||||
},
|
||||
handleChangeYear() {
|
||||
this.xAxis = []
|
||||
this.legendData = []
|
||||
chartOrderYearApi().then(async res => {
|
||||
this.info = res
|
||||
this.legendData = ["去年金额", "今年金额", "去年订单数", "今年订单数"]
|
||||
let prePrice = []
|
||||
let price = []
|
||||
let qualitys = []
|
||||
let preQuality = []
|
||||
for (let key in res.prePrice) {
|
||||
prePrice.push(Number(res.prePrice[key]))
|
||||
this.xAxis.push(key)
|
||||
}
|
||||
for (let key in res.price) {
|
||||
price.push(Number(res.price[key]))
|
||||
}
|
||||
for (let key in res.preQuality) {
|
||||
preQuality.push(Number(res.preQuality[key]))
|
||||
}
|
||||
for (let key in res.quality) {
|
||||
qualitys.push(Number(res.quality[key]))
|
||||
}
|
||||
this.series = [
|
||||
{
|
||||
"name":"去年金额",
|
||||
"type":"bar",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#69cdff"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#3eb3f7"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#1495eb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": prePrice
|
||||
},
|
||||
{
|
||||
"name":"今年金额",
|
||||
"type":"bar",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#69cdff"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#3eb3f7"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#1495eb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": price
|
||||
},
|
||||
{
|
||||
"name":"去年订单数",
|
||||
"type":"line",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#6fdeab"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#44d693"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#2cc981"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": preQuality
|
||||
},
|
||||
{
|
||||
"name":"今年订单数",
|
||||
"type":"line",
|
||||
"itemStyle":{
|
||||
"normal":{
|
||||
"color":{
|
||||
"x":0,
|
||||
"y":0,
|
||||
"x2":0,
|
||||
"y2":1,
|
||||
"colorStops":[
|
||||
{
|
||||
"offset":0,
|
||||
"color":"#6fdeab"
|
||||
},
|
||||
{
|
||||
"offset":0.5,
|
||||
"color":"#44d693"
|
||||
},
|
||||
{
|
||||
"offset":1,
|
||||
"color":"#2cc981"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": qualitys
|
||||
}
|
||||
]
|
||||
})
|
||||
},
|
||||
// 监听页面宽度变化,刷新表格
|
||||
handleResize() {
|
||||
if (this.infoList) this.$refs.visitChart.handleResize();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.handleChangeVisitType();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.acea-row{
|
||||
/deep/.el-avatar--small {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
.checkTime{
|
||||
/deep/.el-radio__input{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.ivu-pl-8{
|
||||
margin-left: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.divBox {
|
||||
padding: 0 20px !important;
|
||||
}
|
||||
.dashboard-console-visit {
|
||||
/deep/.el-card__header{
|
||||
padding: 14px 20px !important;
|
||||
}
|
||||
ul {
|
||||
li {
|
||||
list-style-type: none;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ivu-mb{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
72
admin/src/views/dashboard/editor/index.vue
Normal file
72
admin/src/views/dashboard/editor/index.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<div class="dashboard-editor-container">
|
||||
<div class=" clearfix">
|
||||
<pan-thumb :image="avatar" style="float: left">
|
||||
Your roles:
|
||||
<span v-for="item in roles" :key="item" class="pan-info-roles">{{ item }}</span>
|
||||
</pan-thumb>
|
||||
<div class="info-container">
|
||||
<span class="display_name">{{ name }}</span>
|
||||
<span style="font-size:20px;padding-top:20px;display:inline-block;">Editor's Dashboard</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<img :src="emptyGif" class="emptyGif">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import PanThumb from '@/components/PanThumb'
|
||||
|
||||
export default {
|
||||
name: 'DashboardEditor',
|
||||
components: { PanThumb },
|
||||
data() {
|
||||
return {
|
||||
emptyGif: 'https://wpimg.wallstcn.com/0e03b7da-db9e-4819-ba10-9016ddfdaed3'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'name',
|
||||
'avatar',
|
||||
'roles'
|
||||
])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.emptyGif {
|
||||
display: block;
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.dashboard-editor-container {
|
||||
background-color: #e3e3e3;
|
||||
min-height: 100vh;
|
||||
padding: 50px 60px 0px;
|
||||
.pan-info-roles {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
display: block;
|
||||
}
|
||||
.info-container {
|
||||
position: relative;
|
||||
margin-left: 190px;
|
||||
height: 150px;
|
||||
line-height: 200px;
|
||||
.display_name {
|
||||
font-size: 48px;
|
||||
line-height: 48px;
|
||||
color: #212121;
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
43
admin/src/views/dashboard/index.vue
Normal file
43
admin/src/views/dashboard/index.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--头部-->
|
||||
<base-info ref="baseInfo"/>
|
||||
<!--小方块-->
|
||||
<grid-menu class="mb20"/>
|
||||
<!--订单统计-->
|
||||
<visit-chart ref="visitChart"/>
|
||||
<!--用户-->
|
||||
<user-chart ref="userChart" class="mb20"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import adminDashboard from './admin'
|
||||
import editorDashboard from './editor'
|
||||
|
||||
|
||||
import baseInfo from './components/baseInfo';
|
||||
import gridMenu from './components/gridMenu';
|
||||
import visitChart from './components/visitChart';
|
||||
import userChart from './components/userChart';
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
components: { baseInfo, gridMenu, visitChart, userChart, adminDashboard, editorDashboard },
|
||||
data() {
|
||||
return {
|
||||
currentRole: 'adminDashboard'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'roles'
|
||||
])
|
||||
},
|
||||
created() {
|
||||
if (!this.roles.includes('admin')) {
|
||||
this.currentRole = 'editorDashboard'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
0
admin/src/views/datas/datamark/index.vue
Normal file
0
admin/src/views/datas/datamark/index.vue
Normal file
15
admin/src/views/datas/index.vue
Normal file
15
admin/src/views/datas/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
13
admin/src/views/datas/transaction/goods/index.vue
Normal file
13
admin/src/views/datas/transaction/goods/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>商品数据</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/datas/transaction/index.vue
Normal file
15
admin/src/views/datas/transaction/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
13
admin/src/views/datas/transaction/order/index.vue
Normal file
13
admin/src/views/datas/transaction/order/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>订单数据</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
173
admin/src/views/distribution/config/index.vue
Normal file
173
admin/src/views/distribution/config/index.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<el-form ref="promoterForm" :model="promoterForm" :rules="rules" label-width="200px" class="demo-promoterForm">
|
||||
<el-form-item prop="brokerageFuncStatus">
|
||||
<span slot="label">
|
||||
<span>分销启用:</span>
|
||||
<el-tooltip class="item" effect="dark" content="商城分销功能开启关闭" placement="top-start">
|
||||
<i class="el-icon-warning-outline" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-radio-group v-model="promoterForm.brokerageFuncStatus">
|
||||
<el-radio label="1">开启</el-radio>
|
||||
<el-radio label="0">关闭</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item prop="storeBrokerageStatus">
|
||||
<span slot="label">
|
||||
<span>分销模式:</span>
|
||||
<el-tooltip class="item" effect="dark" content="人人分销”默认每个人都可以分销,“指定分销”仅可后台手动设置推广员,“满额分销”指用户购买商品满足消费金额后自动开启分销" placement="top-start">
|
||||
<i class="el-icon-warning-outline" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-radio-group v-model="promoterForm.storeBrokerageStatus">
|
||||
<el-radio label="1">指定分销</el-radio>
|
||||
<el-radio label="2">人人分销</el-radio>
|
||||
<el-radio label="3">满额分销</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item prop="brokerageBindind">
|
||||
<span slot="label">
|
||||
<span>分销关系绑定:</span>
|
||||
<el-tooltip class="item" effect="dark" content="所有用户”指所有没有上级推广人的用户,“新用户”指新注册的用户" placement="top-start">
|
||||
<i class="el-icon-warning-outline" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-radio-group v-model="promoterForm.brokerageBindind">
|
||||
<el-radio label="0">所有用户</el-radio>
|
||||
<el-radio label="1">新用户</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item prop="storeBrokerageRatio">
|
||||
<span slot="label">
|
||||
<span>一级返佣比例:</span>
|
||||
<el-tooltip class="item" effect="dark" content="订单交易成功后给上级返佣的比例0 - 100,例:5 = 反订单金额的5%" placement="top-start">
|
||||
<i class="el-icon-warning-outline" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-input-number v-model="promoterForm.storeBrokerageRatio" :precision="2" :step="0.1" class="selWidth" placeholder="订单交易成功后给上级返佣的比例0 - 100,例:5 = 反订单金额的5%"></el-input-number>
|
||||
<span>%</span>
|
||||
</el-form-item>
|
||||
<el-form-item prop="storeBrokerageTwo">
|
||||
<span slot="label">
|
||||
<span>二级返佣比例:</span>
|
||||
<el-tooltip class="item" effect="dark" content="订单交易成功后给上级返佣的比例0 ~ 100,例:5 = 反订单金额的5%" placement="top-start">
|
||||
<i class="el-icon-warning-outline" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-input-number v-model="promoterForm.storeBrokerageTwo" :precision="2" :step="0.1" class="selWidth" placeholder="订单交易成功后给上级返佣的比例0 ~ 100,例:5 = 反订单金额的5%"></el-input-number>
|
||||
<span>%</span>
|
||||
</el-form-item>
|
||||
<el-form-item prop="userExtractMinPrice">
|
||||
<span slot="label">
|
||||
<span>提现最低金额:</span>
|
||||
<el-tooltip class="item" effect="dark" content="用户提现最低金额" placement="top-start">
|
||||
<i class="el-icon-warning-outline" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-input-number v-model="promoterForm.userExtractMinPrice" :precision="2" :step="0.1" class="selWidth" placeholder="用户提现最低金额"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item prop="userExtractBank">
|
||||
<span slot="label">
|
||||
<span>提现银行卡:</span>
|
||||
<el-tooltip class="item" effect="dark" content="提现银行卡,每个银行换行" placement="top-start">
|
||||
<i class="el-icon-warning-outline" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
placeholder="提现银行卡,每个银行换行"
|
||||
v-model="promoterForm.userExtractBank">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="extractTime">
|
||||
<span slot="label">
|
||||
<span>冻结时间:</span>
|
||||
<el-tooltip class="item" effect="dark" content="佣金冻结时间(天)" placement="top-start">
|
||||
<i class="el-icon-warning-outline" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-input-number v-model="promoterForm.extractTime" :precision="2" :step="0.1" class="selWidth" placeholder="佣金冻结时间(天)"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item prop="extension_two_rate">
|
||||
<span slot="label">
|
||||
<span>满额分销最低金额:</span>
|
||||
<el-tooltip class="item" effect="dark" content="满额分销满足金额开通分销权限" placement="top-start">
|
||||
<i class="el-icon-warning-outline" />
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<el-input-number v-model="promoterForm.extension_two_rate" placeholder="满额分销满足金额开通分销权限" :precision="2" :step="0.1" class="selWidth"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="mini" type="primary" :loading="loading" @click="submitForm('promoterForm')">立即创建</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { configApi, configUpdateApi, productCheckApi } from '@/api/distribution'
|
||||
export default {
|
||||
name: 'Index',
|
||||
data() {
|
||||
return {
|
||||
promoterForm: {},
|
||||
loading: false,
|
||||
rules: {
|
||||
brokerageFuncStatus: [
|
||||
{ required: true, message: '请选择是否启用分销', trigger: 'change' }
|
||||
],
|
||||
storeBrokerageRatio: [
|
||||
{ required: true, message: '请输入一级返佣比例', trigger: 'blur' }
|
||||
],
|
||||
storeBrokerageTwo: [
|
||||
{ required: true, message: '请输入二级返佣比例', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getDetal()
|
||||
},
|
||||
methods: {
|
||||
getDetal() {
|
||||
configApi().then(res => {
|
||||
this.promoterForm = res
|
||||
}).catch((res) => {
|
||||
this.$message.error(res.message)
|
||||
})
|
||||
},
|
||||
submitForm(formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
configUpdateApi(this.promoterForm).then(res => {
|
||||
this.loading = false
|
||||
this.$modalSure('提交成功,是否自动下架商户低于此佣金比例的商品').then(() => {
|
||||
productCheckApi().then(({ message }) => {
|
||||
this.$message.success(message)
|
||||
}).catch(({ message }) => {
|
||||
this.$message.error(message)
|
||||
})
|
||||
})
|
||||
}).catch((res) => {
|
||||
this.$message.error(res.message)
|
||||
this.loading = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.selWidth{
|
||||
width: 300px;
|
||||
}
|
||||
</style>
|
||||
458
admin/src/views/distribution/index.vue
Normal file
458
admin/src/views/distribution/index.vue
Normal file
@@ -0,0 +1,458 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="container">
|
||||
<el-form size="small" label-width="100px">
|
||||
<el-form-item label="时间选择:" class="width100">
|
||||
<el-radio-group v-model="tableFrom.dateLimit" type="button" class="mr20" size="small" @change="selectChange(tableFrom.dateLimit)">
|
||||
<el-radio-button v-for="(item,i) in fromList.fromTxt" :key="i" :label="item.val">{{ item.text }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-date-picker v-model="timeVal" value-format="yyyy/MM/dd" format="yyyy/MM/dd" size="small" type="daterange" placement="bottom-end" placeholder="自定义时间" style="width: 250px;" @change="onchangeTime" />
|
||||
</el-form-item>
|
||||
<el-form-item label="关键字:">
|
||||
<el-input v-model="tableFrom.keyword" placeholder="请输入请输入姓名、电话、UID" class="selWidth" size="small">
|
||||
<el-button slot="append" icon="el-icon-search" size="small" @click="seachList" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<cards-data :cardLists="cardLists"></cards-data>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
class="table"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
prop="uid"
|
||||
label="ID"
|
||||
width="60"
|
||||
/>
|
||||
<el-table-column
|
||||
label="头像"
|
||||
min-width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div class="demo-image__preview">
|
||||
<el-image
|
||||
:src="scope.row.avatar"
|
||||
:preview-src-list="[scope.row.avatar]"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="nickname"
|
||||
label="用户信息"
|
||||
min-width="130"
|
||||
/>
|
||||
<el-table-column
|
||||
sortable
|
||||
prop="spreadCount"
|
||||
label="推广用户数量"
|
||||
min-width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
sortable
|
||||
label="订单数量"
|
||||
min-width="120"
|
||||
prop="payCount"
|
||||
/>
|
||||
<el-table-column
|
||||
sortable
|
||||
label="推广订单金额"
|
||||
min-width="120"
|
||||
prop="payCount"
|
||||
/>
|
||||
<el-table-column
|
||||
sortable
|
||||
label="佣金金额"
|
||||
min-width="120"
|
||||
prop="brokeragePrice"
|
||||
/>
|
||||
<el-table-column
|
||||
sortable
|
||||
label="已提现金额"
|
||||
min-width="120"
|
||||
prop="brokeragePrice"
|
||||
/>
|
||||
<el-table-column
|
||||
sortable
|
||||
label="提现金额"
|
||||
min-width="120"
|
||||
prop="brokeragePrice"
|
||||
/>
|
||||
<el-table-column
|
||||
sortable
|
||||
label="未提现金额"
|
||||
min-width="120"
|
||||
prop="brokeragePrice"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="spread.nickname"
|
||||
label="上级推广人"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column label="操作" min-width="150" fixed="right" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" class="mr10" @click="onSpread(scope.row.uid, 'man')">推广人</el-button>
|
||||
<el-dropdown>
|
||||
<span class="el-dropdown-link">
|
||||
更多<i class="el-icon-arrow-down el-icon--right" />
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native="onSpreadOrder(scope.row.uid, 'order')">推广订单</el-dropdown-item>
|
||||
<!--<el-dropdown-item @click.native="onSpreadType(scope.row.uid)">推广方式</el-dropdown-item>-->
|
||||
<el-dropdown-item @click.native="clearSpread(scope.row)">清除上级推广人</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!--推广人-->
|
||||
<el-dialog
|
||||
title="提示"
|
||||
:visible.sync="dialogVisible"
|
||||
width="900px"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<div class="container">
|
||||
<el-form size="small" label-width="100px">
|
||||
<el-form-item label="时间选择:" class="width100">
|
||||
<el-radio-group v-model="spreadFrom.dateLimit" type="button" class="mr20" size="small" @change="selectChangeSpread(spreadFrom.dateLimit)">
|
||||
<el-radio-button v-for="(item,i) in fromList.fromTxt" :key="i" :label="item.val">{{ item.text }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-date-picker v-model="timeValSpread" value-format="yyyy/MM/dd" format="yyyy/MM/dd" size="small" type="daterange" placement="bottom-end" placeholder="自定义时间" style="width: 250px;" @change="onchangeTimeSpread" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用户类型:">
|
||||
<el-radio-group v-model="spreadFrom.type" size="small" @change="onChanges">
|
||||
<el-radio-button label="null">全部</el-radio-button>
|
||||
<el-radio-button label="1">一级推广人</el-radio-button>
|
||||
<el-radio-button label="2">二级推广人</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键字:" class="width100">
|
||||
<el-input v-model="spreadFrom.nickName" placeholder="请输入请输入姓名、电话、UID" class="selWidth" size="small">
|
||||
<el-button slot="append" icon="el-icon-search" size="small" @click="onChanges" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table
|
||||
v-if="onName === 'man'"
|
||||
key="men"
|
||||
v-loading="spreadLoading"
|
||||
:data="spreadData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
class="table"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
prop="uid"
|
||||
label="ID"
|
||||
width="60"
|
||||
/>
|
||||
<el-table-column
|
||||
label="头像"
|
||||
min-width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div class="demo-image__preview">
|
||||
<el-image
|
||||
:src="scope.row.avatar"
|
||||
:preview-src-list="[scope.row.avatar]"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="nickname"
|
||||
label="用户信息"
|
||||
min-width="130"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="is_promoter"
|
||||
label="是否推广员"
|
||||
min-width="120"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.is_promoter | filterYesOrNo }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
sortable
|
||||
label="推广人数"
|
||||
min-width="120"
|
||||
prop="spread_count"
|
||||
/>
|
||||
<el-table-column
|
||||
sortable
|
||||
label="订单数"
|
||||
min-width="120"
|
||||
prop="pay_count"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="create_time"
|
||||
label="关注时间"
|
||||
min-width="150"
|
||||
/>
|
||||
</el-table>
|
||||
<el-table
|
||||
v-if="onName === 'order'"
|
||||
key="order"
|
||||
v-loading="spreadLoading"
|
||||
:data="spreadData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
class="table"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
prop="order_sn"
|
||||
label="订单ID"
|
||||
min-width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
label="用户信息"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.user.nickname }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="create_time"
|
||||
label="时间"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column
|
||||
sortable
|
||||
label="返佣金额"
|
||||
min-width="120"
|
||||
prop="brokerage"
|
||||
/>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[10, 20, 30, 40]"
|
||||
:page-size="spreadFrom.limit"
|
||||
:current-page="spreadFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="spreadData.total"
|
||||
@size-change="handleSizeChangeSpread"
|
||||
@current-change="pageChangeSpread"
|
||||
/>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { promoterListApi, spreadStatisticsApi, spreadListApi, spreadOrderListApi, spreadClearApi } from '@/api/distribution'
|
||||
import { fromList } from '@/utils/constants.js'
|
||||
import cardsData from '@/components/cards/index'
|
||||
export default {
|
||||
name: 'AccountsUser',
|
||||
components: { cardsData },
|
||||
data() {
|
||||
return {
|
||||
cardLists: [],
|
||||
timeVal: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
listLoading: true,
|
||||
tableFrom: {
|
||||
dateLimit: '',
|
||||
keyword: '',
|
||||
page: 1,
|
||||
limit: 20
|
||||
},
|
||||
fromList: fromList,
|
||||
dialogVisible: false,
|
||||
spreadData: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
spreadFrom: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
dateLimit: '',
|
||||
type: null,
|
||||
nickName: '',
|
||||
uid: ''
|
||||
},
|
||||
timeValSpread: [],
|
||||
spreadLoading: false,
|
||||
uid: '',
|
||||
onName: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.spreadStatistics()
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
seachList() {
|
||||
this.tableFrom.page = 1
|
||||
this.getList()
|
||||
},
|
||||
// 统计
|
||||
spreadStatistics() {
|
||||
spreadStatisticsApi({ dateLimit: this.tableFrom.dateLimit, nickName: this.tableFrom.nickName}).then((res) => {
|
||||
this.cardLists = res
|
||||
})
|
||||
},
|
||||
// 清除
|
||||
clearSpread(row) {
|
||||
this.$modalSure('解除【' + row.nickname + '】的上级推广人吗').then(() => {
|
||||
spreadClearApi(row.uid).then((res) => {
|
||||
this.$message.success('清除成功')
|
||||
this.getList()
|
||||
})
|
||||
})
|
||||
},
|
||||
onSpread(uid, n) {
|
||||
this.onName = n
|
||||
this.uid = uid
|
||||
this.dialogVisible = true
|
||||
this.spreadFrom = {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
dateLimit: '',
|
||||
type: null,
|
||||
nickName: '',
|
||||
uid: uid
|
||||
}
|
||||
this.getListSpread()
|
||||
},
|
||||
handleClose() {
|
||||
this.dialogVisible = false
|
||||
},
|
||||
// 选择时间
|
||||
selectChangeSpread(tab) {
|
||||
this.timeValSpread = []
|
||||
this.spreadFrom.dateLimit = tab
|
||||
this.onName === 'man' ? this.getListSpread() : this.getSpreadOrderList()
|
||||
},
|
||||
// 具体日期
|
||||
onchangeTimeSpread(e) {
|
||||
this.timeValSpread = e
|
||||
this.tableFrom.dateLimit = e ? this.timeValSpread.join('-') : ''
|
||||
this.onName === 'man' ? this.getListSpread() : this.getSpreadOrderList()
|
||||
},
|
||||
onChanges() {
|
||||
this.onName === 'man' ? this.getListSpread() : this.getSpreadOrderList()
|
||||
},
|
||||
// 推广人列表
|
||||
getListSpread() {
|
||||
this.spreadLoading = true
|
||||
spreadListApi({ page: this.spreadFrom.page, limit: this.spreadFrom.limit}, this.spreadFrom).then(res => {
|
||||
this.spreadData.data = res.list
|
||||
this.spreadData.total = res.total
|
||||
this.spreadLoading = false
|
||||
}).catch(() => {
|
||||
this.spreadLoading = false
|
||||
})
|
||||
},
|
||||
pageChangeSpread(page) {
|
||||
this.spreadFrom.page = page
|
||||
this.onName === 'man' ? this.getListSpread(this.uid) : this.getSpreadOrderList(this.uid)
|
||||
},
|
||||
handleSizeChangeSpread(val) {
|
||||
this.spreadFrom.limit = val
|
||||
this.onName === 'man' ? this.getListSpread(this.uid) : this.getSpreadOrderList(this.uid)
|
||||
},
|
||||
// 推广订单
|
||||
onSpreadOrder(uid, n) {
|
||||
this.uid = uid
|
||||
this.onName = n
|
||||
this.dialogVisible = true
|
||||
this.spreadFrom = {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
dateLimit: '',
|
||||
type: '',
|
||||
nickName: '',
|
||||
uid: uid
|
||||
}
|
||||
this.getSpreadOrderList()
|
||||
},
|
||||
getSpreadOrderList() {
|
||||
this.spreadLoading = true
|
||||
spreadOrderListApi({ page: this.spreadFrom.page, limit: this.spreadFrom.limit}, this.spreadFrom).then(res => {
|
||||
this.spreadData.data = res.list
|
||||
this.spreadData.total = res.total
|
||||
this.spreadLoading = false
|
||||
}).catch(() => {
|
||||
this.spreadLoading = false
|
||||
})
|
||||
},
|
||||
selectChange(tab) {
|
||||
this.tableFrom.dateLimit = tab
|
||||
this.tableFrom.page = 1
|
||||
this.timeVal = []
|
||||
this.getList()
|
||||
},
|
||||
// 具体日期
|
||||
onchangeTime(e) {
|
||||
this.timeVal = e
|
||||
this.tableFrom.dateLimit = e ? this.timeVal.join('-') : ''
|
||||
this.tableFrom.page = 1
|
||||
this.getList()
|
||||
},
|
||||
// 列表
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
promoterListApi(this.tableFrom).then(res => {
|
||||
this.tableData.data = res.list
|
||||
this.tableData.total = res.total
|
||||
this.listLoading = false
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
pageChange(page) {
|
||||
this.tableFrom.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.selWidth{
|
||||
width: 350px;
|
||||
}
|
||||
.el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: #409EFF;
|
||||
font-size: 12px;
|
||||
}
|
||||
.el-icon-arrow-down {
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
13
admin/src/views/error-log/components/ErrorTestA.vue
Normal file
13
admin/src/views/error-log/components/ErrorTestA.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--error code-->
|
||||
{{ a.a }}
|
||||
<!--error code-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ErrorTestA'
|
||||
}
|
||||
</script>
|
||||
11
admin/src/views/error-log/components/ErrorTestB.vue
Normal file
11
admin/src/views/error-log/components/ErrorTestB.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<div />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
created() {
|
||||
this.b = b // eslint-disable-line
|
||||
}
|
||||
}
|
||||
</script>
|
||||
32
admin/src/views/error-log/index.vue
Normal file
32
admin/src/views/error-log/index.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="errPage-container">
|
||||
<ErrorA />
|
||||
<ErrorB />
|
||||
<h3>Please click the bug icon in the upper right corner</h3>
|
||||
<aside>
|
||||
Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.
|
||||
<a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/guide/advanced/error.html">
|
||||
Document introduction
|
||||
</a>
|
||||
</aside>
|
||||
<a href="#">
|
||||
<img src="https://wpimg.wallstcn.com/360e4842-4db5-42d0-b078-f9a84a825546.gif">
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ErrorA from './components/ErrorTestA'
|
||||
import ErrorB from './components/ErrorTestB'
|
||||
|
||||
export default {
|
||||
name: 'ErrorLog',
|
||||
components: { ErrorA, ErrorB }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.errPage-container {
|
||||
padding: 30px;
|
||||
}
|
||||
</style>
|
||||
99
admin/src/views/error-page/401.vue
Normal file
99
admin/src/views/error-page/401.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div class="errPage-container">
|
||||
<el-button size="mini" icon="el-icon-arrow-left" class="pan-back-btn" @click="back">
|
||||
返回
|
||||
</el-button>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<h1 class="text-jumbo text-ginormous">
|
||||
Oops!
|
||||
</h1>
|
||||
gif来源<a href="https://zh.airbnb.com/" target="_blank">airbnb</a> 页面
|
||||
<h2>你没有权限去该页面</h2>
|
||||
<h6>如有不满请联系你领导</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li>或者你可以去:</li>
|
||||
<li class="link-type">
|
||||
<router-link to="/dashboard">
|
||||
回首页
|
||||
</router-link>
|
||||
</li>
|
||||
<li class="link-type">
|
||||
<a href="https://www.taobao.com/">随便看看</a>
|
||||
</li>
|
||||
<li><a href="#" @click.prevent="dialogVisible=true">点我看图</a></li>
|
||||
</ul>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream.">
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-dialog :visible.sync="dialogVisible" title="随便看">
|
||||
<img :src="ewizardClap" class="pan-img">
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import errGif from '@/assets/401_images/401.gif'
|
||||
|
||||
export default {
|
||||
name: 'Page401',
|
||||
data() {
|
||||
return {
|
||||
errGif: errGif + '?' + +new Date(),
|
||||
ewizardClap: 'https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646',
|
||||
dialogVisible: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
if (this.$route.query.noGoBack) {
|
||||
this.$router.push({ path: '/dashboard' })
|
||||
} else {
|
||||
this.$router.go(-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.errPage-container {
|
||||
width: 800px;
|
||||
max-width: 100%;
|
||||
margin: 100px auto;
|
||||
.pan-back-btn {
|
||||
background: #008489;
|
||||
color: #fff;
|
||||
border: none!important;
|
||||
}
|
||||
.pan-gif {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
.pan-img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
.text-jumbo {
|
||||
font-size: 60px;
|
||||
font-weight: 700;
|
||||
color: #484848;
|
||||
}
|
||||
.list-unstyled {
|
||||
font-size: 14px;
|
||||
li {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
a {
|
||||
color: #008489;
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
237
admin/src/views/error-page/404.vue
Normal file
237
admin/src/views/error-page/404.vue
Normal file
@@ -0,0 +1,237 @@
|
||||
<template>
|
||||
<div class="wscn-http404-container">
|
||||
<div class="wscn-http404">
|
||||
<div class="pic-404">
|
||||
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
|
||||
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
|
||||
</div>
|
||||
<div class="bullshit">
|
||||
<div class="bullshit__oops">OOPS!</div>
|
||||
<!--<div class="bullshit__info">All rights reserved-->
|
||||
<!--<a style="color:#20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>-->
|
||||
<!--</div>-->
|
||||
<div class="bullshit__headline">{{ message }}</div>
|
||||
<div class="bullshit__info">请检查您输入的URL是否正确,或单击下面的按钮返回主页.</div>
|
||||
<router-link :to="{path: '/dashboard'}">
|
||||
<span class="bullshit__return-home">返回控制台</span>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Page404',
|
||||
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
message() {
|
||||
return '你不能进入这个页面...'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wscn-http404-container{
|
||||
transform: translate(-50%,-50%);
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
}
|
||||
.wscn-http404 {
|
||||
position: relative;
|
||||
width: 1200px;
|
||||
padding: 0 50px;
|
||||
overflow: hidden;
|
||||
.pic-404 {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 600px;
|
||||
overflow: hidden;
|
||||
&__parent {
|
||||
width: 100%;
|
||||
}
|
||||
&__child {
|
||||
position: absolute;
|
||||
&.left {
|
||||
width: 80px;
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
animation-name: cloudLeft;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
&.mid {
|
||||
width: 46px;
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
animation-name: cloudMid;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
&.right {
|
||||
width: 62px;
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
animation-name: cloudRight;
|
||||
animation-duration: 2s;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
@keyframes cloudLeft {
|
||||
0% {
|
||||
top: 17px;
|
||||
left: 220px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 33px;
|
||||
left: 188px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 81px;
|
||||
left: 92px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 97px;
|
||||
left: 60px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudMid {
|
||||
0% {
|
||||
top: 10px;
|
||||
left: 420px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 40px;
|
||||
left: 360px;
|
||||
opacity: 1;
|
||||
}
|
||||
70% {
|
||||
top: 130px;
|
||||
left: 180px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 160px;
|
||||
left: 120px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes cloudRight {
|
||||
0% {
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
top: 120px;
|
||||
left: 460px;
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
top: 180px;
|
||||
left: 340px;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 200px;
|
||||
left: 300px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.bullshit {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 300px;
|
||||
padding: 30px 0;
|
||||
overflow: hidden;
|
||||
&__oops {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 40px;
|
||||
color: #1482f0;
|
||||
opacity: 0;
|
||||
margin-bottom: 20px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__headline {
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
color: #222;
|
||||
font-weight: bold;
|
||||
opacity: 0;
|
||||
margin-bottom: 10px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.1s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__info {
|
||||
font-size: 13px;
|
||||
line-height: 21px;
|
||||
color: grey;
|
||||
opacity: 0;
|
||||
margin-bottom: 30px;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.2s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
&__return-home {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 110px;
|
||||
height: 36px;
|
||||
background: #1482f0;
|
||||
border-radius: 100px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
opacity: 0;
|
||||
font-size: 14px;
|
||||
line-height: 36px;
|
||||
cursor: pointer;
|
||||
animation-name: slideUp;
|
||||
animation-duration: 0.5s;
|
||||
animation-delay: 0.3s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateY(60px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
13
admin/src/views/financial/brokerage/index.vue
Normal file
13
admin/src/views/financial/brokerage/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>佣金记录</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/financial/commission/index.vue
Normal file
15
admin/src/views/financial/commission/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
13
admin/src/views/financial/commission/withdrawal/index.vue
Normal file
13
admin/src/views/financial/commission/withdrawal/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>提现申请</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/financial/index.vue
Normal file
15
admin/src/views/financial/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
0
admin/src/views/financial/operating/index.vue
Normal file
0
admin/src/views/financial/operating/index.vue
Normal file
13
admin/src/views/financial/record/charge/index.vue
Normal file
13
admin/src/views/financial/record/charge/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>充值记录</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/financial/record/index.vue
Normal file
15
admin/src/views/financial/record/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
13
admin/src/views/financial/record/monitor/index.vue
Normal file
13
admin/src/views/financial/record/monitor/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>资金监控</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/login/auth-redirect.vue
Normal file
15
admin/src/views/login/auth-redirect.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'AuthRedirect',
|
||||
created() {
|
||||
const hash = window.location.search.slice(1)
|
||||
if (window.localStorage) {
|
||||
window.localStorage.setItem('x-admin-oauth-code', hash)
|
||||
window.close()
|
||||
}
|
||||
},
|
||||
render: function(h) {
|
||||
return h() // avoid warning message
|
||||
}
|
||||
}
|
||||
</script>
|
||||
508
admin/src/views/login/index.vue
Normal file
508
admin/src/views/login/index.vue
Normal file
@@ -0,0 +1,508 @@
|
||||
<template>
|
||||
<div class="page-account">
|
||||
<div class="container" :class="[ fullWidth > 768 ? 'containerSamll':'containerBig']">
|
||||
<template v-if="fullWidth>768">
|
||||
<swiper :options="swiperOption" class="swiperPross">
|
||||
<swiper-slide v-for="(item,index) in swiperList" :key="index" class="swiperPic">
|
||||
<img :src="item.pic">
|
||||
</swiper-slide>
|
||||
<div slot="pagination" class="swiper-pagination" />
|
||||
</swiper>
|
||||
</template>
|
||||
<div class="index_from page-account-container">
|
||||
<div class="page-account-top ">
|
||||
<div class="page-account-top-logo">
|
||||
<img :src="loginLogo" alt="logo">
|
||||
</div>
|
||||
</div>
|
||||
<el-form
|
||||
ref="loginForm"
|
||||
:model="loginForm"
|
||||
:rules="loginRules"
|
||||
class="login-form"
|
||||
autocomplete="on"
|
||||
label-position="left"
|
||||
@keyup.enter="handleLogin"
|
||||
>
|
||||
<el-form-item prop="account">
|
||||
<el-input
|
||||
ref="account"
|
||||
v-model="loginForm.account"
|
||||
prefix-icon="el-icon-user"
|
||||
placeholder="用户名"
|
||||
name="username"
|
||||
type="text"
|
||||
tabindex="1"
|
||||
autocomplete="on"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="pwd">
|
||||
<el-input
|
||||
:key="passwordType"
|
||||
ref="pwd"
|
||||
v-model="loginForm.pwd"
|
||||
prefix-icon="el-icon-lock"
|
||||
:type="passwordType"
|
||||
placeholder="密码"
|
||||
name="pwd"
|
||||
tabindex="2"
|
||||
auto-complete="on"
|
||||
/>
|
||||
<span class="show-pwd" @click="showPwd">
|
||||
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
|
||||
</span>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="code" class="captcha">
|
||||
<div class="captcha">
|
||||
<el-input
|
||||
ref="username"
|
||||
v-model="loginForm.code"
|
||||
style="width: 218px;"
|
||||
prefix-icon="el-icon-message"
|
||||
placeholder="验证码"
|
||||
name="username"
|
||||
type="text"
|
||||
tabindex="3"
|
||||
autocomplete="on"
|
||||
/>
|
||||
<div class="imgs" @click="getCaptcha()"><img :src="captchatImg"></div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-button
|
||||
:loading="loading"
|
||||
type="primary"
|
||||
style="width:100%;margin-bottom:30px;"
|
||||
@click.native.prevent="handleLogin"
|
||||
>登录
|
||||
</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { validUsername } from '@/utils/validate'
|
||||
import { getLoginPicApi, captchaApi, codeCheckApi } from '@/api/user'
|
||||
export default {
|
||||
name: 'Login',
|
||||
data() {
|
||||
const validateUsername = (rule, value, callback) => {
|
||||
if (!validUsername(value)) {
|
||||
callback(new Error('Please enter the correct user name'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const validatePassword = (rule, value, callback) => {
|
||||
if (value.length < 6) {
|
||||
callback(new Error('The password can not be less than 6 digits'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
captchatImg: '',
|
||||
swiperList: [],
|
||||
loginLogo: '',
|
||||
backgroundImage: '',
|
||||
fullWidth: document.body.clientWidth,
|
||||
swiperOption: {
|
||||
pagination: {
|
||||
el: '.pagination'
|
||||
},
|
||||
autoplay: {
|
||||
enabled: true,
|
||||
disableOnInteraction: false,
|
||||
delay: 3000
|
||||
}
|
||||
},
|
||||
loginForm: {
|
||||
account: 'demo', // admin
|
||||
pwd: '123456',
|
||||
key: '',
|
||||
code: ''
|
||||
},
|
||||
loginRules: {
|
||||
account: [{ required: true, trigger: 'blur' }], // validator: validateUsername
|
||||
pwd: [{ required: true, trigger: 'blur', validator: validatePassword }],
|
||||
code: [{ required: true, message: '请输入正确的验证码', trigger: 'blur' }]
|
||||
},
|
||||
passwordType: 'password',
|
||||
capsTooltip: false,
|
||||
loading: false,
|
||||
showDialog: false,
|
||||
redirect: undefined,
|
||||
otherQuery: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
fullWidth(val) {
|
||||
// 为了避免频繁触发resize函数导致页面卡顿,使用定时器
|
||||
if (!this.timer) {
|
||||
// 一旦监听到的screenWidth值改变,就将其重新赋给data里的screenWidth
|
||||
this.screenWidth = val
|
||||
this.timer = true
|
||||
const that = this
|
||||
setTimeout(function() {
|
||||
// 打印screenWidth变化的值
|
||||
that.timer = false
|
||||
}, 400)
|
||||
}
|
||||
},
|
||||
$route: {
|
||||
handler: function(route) {
|
||||
const query = route.query
|
||||
if (query) {
|
||||
this.redirect = query.redirect
|
||||
this.otherQuery = this.getOtherQuery(query)
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const _this = this
|
||||
document.onkeydown = function(e) {
|
||||
if (_this.$route.path.indexOf('login') !== -1) {
|
||||
const key = window.event.keyCode
|
||||
if (key === 13) {
|
||||
_this.handleLogin()
|
||||
}
|
||||
}
|
||||
}
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
},
|
||||
mounted() {
|
||||
this.getInfo()
|
||||
if (this.loginForm.account === '') {
|
||||
this.$refs.account.focus()
|
||||
} else if (this.loginForm.pwd === '') {
|
||||
this.$refs.pwd.focus()
|
||||
}
|
||||
this.getCaptcha()
|
||||
},
|
||||
destroyed() {
|
||||
// window.removeEventListener('storage', this.afterQRScan)
|
||||
},
|
||||
beforeDestroy: function() {
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
},
|
||||
methods: {
|
||||
handleResize(event) {
|
||||
this.fullWidth = document.body.clientWidth
|
||||
},
|
||||
getInfo() {
|
||||
getLoginPicApi().then(res => {
|
||||
this.swiperList = res.banner
|
||||
this.loginLogo = res.logo
|
||||
this.backgroundImage = res.backgroundImage
|
||||
// Cookies.set('MerInfo', JSON.stringify(data))
|
||||
})
|
||||
},
|
||||
checkCapslock(e) {
|
||||
const { key } = e
|
||||
this.capsTooltip = key && key.length === 1 && (key >= 'A' && key <= 'Z')
|
||||
},
|
||||
showPwd() {
|
||||
if (this.passwordType === 'password') {
|
||||
this.passwordType = ''
|
||||
} else {
|
||||
this.passwordType = 'password'
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.pwd.focus()
|
||||
})
|
||||
},
|
||||
handleLogin() {
|
||||
this.$refs.loginForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
this.$store.dispatch('user/login', this.loginForm)
|
||||
.then(() => {
|
||||
this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
this.getCaptcha()
|
||||
})
|
||||
} else {
|
||||
console.log('error submit!!')
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
getCaptcha() {
|
||||
captchaApi().then(( data ) => {
|
||||
this.captchatImg = data.code
|
||||
this.loginForm.key = data.key
|
||||
}).catch(({ message }) => {
|
||||
this.$message.error(message)
|
||||
})
|
||||
},
|
||||
getOtherQuery(query) {
|
||||
return Object.keys(query).reduce((acc, cur) => {
|
||||
if (cur !== 'redirect') {
|
||||
acc[cur] = query[cur]
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$screen-md: 768px;
|
||||
$font-size-base: 14px;
|
||||
$animation-time : .3s;
|
||||
$animation-time-quick : .15s;
|
||||
$transition-time : .2s;
|
||||
$ease-in-out : ease-in-out;
|
||||
$subsidiary-color : #808695;
|
||||
.page-account{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
|
||||
&-container{
|
||||
flex: 1;
|
||||
padding: 32px 0;
|
||||
text-align: center;
|
||||
width: 384px;
|
||||
margin: 0 auto;
|
||||
|
||||
&-result{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&-tabs{
|
||||
.ivu-tabs-bar{
|
||||
border-bottom: none;
|
||||
}
|
||||
.ivu-tabs-nav-scroll{
|
||||
text-align: center;
|
||||
}
|
||||
.ivu-tabs-nav{
|
||||
display: inline-block;
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
&-top{
|
||||
padding: 32px 0;
|
||||
&-logo{
|
||||
img{
|
||||
max-height: 75px;
|
||||
}
|
||||
}
|
||||
&-desc{
|
||||
font-size: $font-size-base;
|
||||
color: $subsidiary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-auto-login{
|
||||
margin-bottom: 24px;
|
||||
text-align: left;
|
||||
a{
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
&-other{
|
||||
margin: 24px 0;
|
||||
text-align: left;
|
||||
span{
|
||||
font-size: $font-size-base;
|
||||
}
|
||||
img{
|
||||
width: 24px;
|
||||
margin-left: 16px;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
opacity: 0.7;
|
||||
transition: all $transition-time $ease-in-out;
|
||||
&:hover{
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ivu-poptip, .ivu-poptip-rel{
|
||||
display: block;
|
||||
}
|
||||
|
||||
&-register{
|
||||
float: right;
|
||||
&-tip{
|
||||
text-align: left;
|
||||
&-title{
|
||||
font-size: $font-size-base;
|
||||
}
|
||||
&-desc{
|
||||
white-space: initial;
|
||||
font-size: $font-size-base;
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-to-login{
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
&-header{
|
||||
text-align: right;
|
||||
position: fixed;
|
||||
top: 16px;
|
||||
right: 24px;
|
||||
}
|
||||
}
|
||||
.labelPic{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
@media (min-width: $screen-md) {
|
||||
.page-account {
|
||||
background-image: url('../../assets/imgs/bg.jpg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
}
|
||||
.page-account-container {
|
||||
padding: 32px 0 24px 0;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
.page-account {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.page-account .code {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.page-account .code .pictrue {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.swiperPross {
|
||||
border-radius: 6px 0px 0px 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.swiperPross, .swiperPic, .swiperPic img {
|
||||
width: 286px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.swiperPic img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 400px !important;
|
||||
padding: 0 !important;
|
||||
/*overflow: hidden;*/
|
||||
border-radius: 6px;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.containerSamll {
|
||||
/*width: 56% !important;*/
|
||||
background: #fff !important;
|
||||
}
|
||||
|
||||
.containerBig {
|
||||
width: auto !important;
|
||||
background: #f7f7f7 !important;
|
||||
}
|
||||
|
||||
.index_from {
|
||||
padding: 0 40px 32px 40px;
|
||||
height: 400px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.page-account-top {
|
||||
padding: 20px 0 !important;
|
||||
box-sizing: border-box !important;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.page-account-container {
|
||||
border-radius: 0px 6px 6px 0px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background: linear-gradient(90deg, rgba(25, 180, 241, 1) 0%, rgba(14, 115, 232, 1) 100%) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.captcha{
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
$bg: #2d3a4b;
|
||||
$dark_gray: #889aa4;
|
||||
$light_gray: #eee;
|
||||
.imgs{
|
||||
img{
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
.login-form {
|
||||
position: relative;
|
||||
max-width: 100%;
|
||||
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;
|
||||
}
|
||||
.show-pwd {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 7px;
|
||||
font-size: 16px;
|
||||
color: $dark_gray;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
/deep/.svg-icon {
|
||||
vertical-align: 0.3em;
|
||||
}
|
||||
}
|
||||
.thirdparty-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 6px;
|
||||
}
|
||||
</style>
|
||||
182
admin/src/views/maintain/devconfig/combineDataList.vue
Normal file
182
admin/src/views/maintain/devconfig/combineDataList.vue
Normal file
@@ -0,0 +1,182 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<div class="container">
|
||||
<el-form inline>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="listPram.status" placeholder="状态" clearable @change="handlerSearch" class="selWidth">
|
||||
<el-option
|
||||
v-for="item in constants.roleListStatus"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="关键词">-->
|
||||
<!-- <el-input v-model="listPram.keywords" placeholder="请输入关键词" clearable></el-input>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item>-->
|
||||
<!-- <el-button type="primary" @click="handlerSearch">查询</el-button>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
</div>
|
||||
<el-button type="primary" size="mini" @click="handlerOpenEditData({},0)">添加数据</el-button>
|
||||
<el-dialog
|
||||
:title="editDataConfig.isCreate === 0?'添加数据':'编辑数据'"
|
||||
:visible.sync="editDataConfig.visible"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<edit
|
||||
v-if="editDataConfig.visible"
|
||||
:form-data="formData"
|
||||
:edit-data="editDataConfig.editData"
|
||||
:is-create="editDataConfig.isCreate"
|
||||
@hideDialog="handlerHideDia"
|
||||
/>
|
||||
</el-dialog>
|
||||
<el-table
|
||||
:data="dataList.list"
|
||||
style="width: 100%;margin-bottom: 20px;"
|
||||
>
|
||||
<el-table-column label="编号" prop="id" />
|
||||
<el-table-column
|
||||
v-for="item,index in formConf.fields"
|
||||
:key="index"
|
||||
:label="item.__config__.label"
|
||||
:prop="item.__vModel__"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="['img','image','pic'].indexOf(item.__vModel__) > -1" class="demo-image__preview">
|
||||
<el-image
|
||||
style="width: 36px; height: 36px"
|
||||
:src="scope.row[item.__vModel__]"
|
||||
:preview-src-list="[scope.row[item.__vModel__]]"
|
||||
/>
|
||||
</div>
|
||||
<span v-else>{{ scope.row[item.__vModel__] }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.status | filterShowOrHide }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="handlerOpenEditData(scope.row,1)">编辑</el-button>
|
||||
<el-button type="text" size="small" @click="handlerDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="listPram.page"
|
||||
:page-sizes="constants.page.limit"
|
||||
:layout="constants.page.layout"
|
||||
:total="dataList.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import edit from './combineEdit'
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import * as systemGroupDataApi from '@/api/systemGroupData.js'
|
||||
import * as systemFormConfigApi from '@/api/systemFormConfig.js'
|
||||
export default {
|
||||
// name: "combineDataList"
|
||||
components: { edit },
|
||||
props: {
|
||||
formData: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
constants,
|
||||
listPram: {
|
||||
gid: null,
|
||||
keywords: null,
|
||||
status: null, // 1=开启 2=关闭
|
||||
page: 1,
|
||||
pageSize: constants.page.limit[0]
|
||||
},
|
||||
editDataConfig: {
|
||||
visible: false,
|
||||
isCreate: 0, // 0=create 1=edit
|
||||
editData: {}
|
||||
},
|
||||
formConf: { fields: [] },
|
||||
dataList: { list: [], total: 0 }
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handlerGetFormConfig()
|
||||
this.listPram.gid = this.formData.id
|
||||
this.handlerGetListData(this.listPram)
|
||||
},
|
||||
methods: {
|
||||
handlerSearch() {
|
||||
this.listPram.page = 1
|
||||
this.handlerGetListData(this.listPram)
|
||||
},
|
||||
handlerGetListData(pram) { // 获取列表数据
|
||||
systemGroupDataApi.groupDataList(pram).then(data => {
|
||||
const _selfList = []
|
||||
data.list.forEach(_lItem => {
|
||||
_lItem.value = JSON.parse(_lItem.value)
|
||||
const _fields = _lItem.value.fields
|
||||
const _rowData = {}
|
||||
_fields.map((item) => {
|
||||
_rowData[item.name] = item.value
|
||||
})
|
||||
_rowData.id = _lItem.id
|
||||
_rowData.sort = _lItem.sort
|
||||
_rowData.status = _lItem.status
|
||||
_selfList.push(_rowData)
|
||||
})
|
||||
this.dataList.list = _selfList
|
||||
this.dataList.total = data.total
|
||||
})
|
||||
},
|
||||
handlerGetFormConfig() { // 获取表单配置后生成table列
|
||||
const _pram = { id: this.formData.formId }
|
||||
systemFormConfigApi.getFormConfigInfo(_pram).then(data => {
|
||||
this.formConf = JSON.parse(data.content)
|
||||
})
|
||||
},
|
||||
handlerOpenEditData(rowData, isCreate) {
|
||||
this.editDataConfig.editData = rowData
|
||||
this.editDataConfig.isCreate = isCreate
|
||||
this.editDataConfig.visible = true
|
||||
},
|
||||
handlerHideDia() {
|
||||
this.handlerGetListData(this.listPram)
|
||||
this.editDataConfig.visible = false
|
||||
},
|
||||
handlerDelete(rowData) {
|
||||
this.$confirm('确实删除当前数据', '提示').then(() => {
|
||||
systemGroupDataApi.groupDataDelete(rowData).then(data => {
|
||||
this.$message.success('删除数据成功')
|
||||
this.handlerHideDia()
|
||||
})
|
||||
})
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.listPram.limit = val
|
||||
this.handlerGetListData(this.listPram)
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.listPram.page = val
|
||||
this.handlerGetListData(this.listPram)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
118
admin/src/views/maintain/devconfig/combineEdit.vue
Normal file
118
admin/src/views/maintain/devconfig/combineEdit.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form ref="selfForm" :model="selfForm" label-width="100px">
|
||||
<el-form-item label="排序" prop="sort" :rules="[{ required: true, message:'排序不能为空', trigger:['blur','change'] }]">
|
||||
<el-input-number v-model="selfForm.sort" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="状态"
|
||||
prop="status"
|
||||
:rules="[{ required: true, message:'正确操作状态', trigger:['change'] }]"
|
||||
>
|
||||
<el-switch
|
||||
v-model="selfForm.status"
|
||||
active-color="#13ce66"
|
||||
inactive-color="#ff4949"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<parser
|
||||
v-if="formConf.fields.length > 0"
|
||||
:is-edit="isCreate === 1"
|
||||
:form-conf="formConf"
|
||||
:form-edit-data="editData"
|
||||
@submit="handlerSubmit"
|
||||
/>
|
||||
<!-- {{ editData }}-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import parser from '@/components/FormGenerator/components/parser/Parser'
|
||||
import * as systemGroupDataApi from '@/api/systemGroupData.js'
|
||||
import * as systemFormConfigApi from '@/api/systemFormConfig.js'
|
||||
export default {
|
||||
// name: "combineEdit"
|
||||
components: { parser },
|
||||
props: {
|
||||
formData: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
isCreate: {
|
||||
type: Number,
|
||||
default: 0 // 0=create 1=edit
|
||||
},
|
||||
editData: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formConf: { fields: [] },
|
||||
selfForm: {
|
||||
sort: 0,
|
||||
status: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handlerGetFormConfig()
|
||||
this.handlerInitEditData()
|
||||
},
|
||||
methods: {
|
||||
handlerInitEditData() {
|
||||
const { sort, status } = this.editData
|
||||
this.selfForm.sort = sort
|
||||
this.selfForm.status = status
|
||||
},
|
||||
handlerGetFormConfig() { // 获取表单配置后生成table列
|
||||
const _pram = { id: this.formData.formId }
|
||||
systemFormConfigApi.getFormConfigInfo(_pram).then(data => {
|
||||
this.formConf = JSON.parse(data.content)
|
||||
})
|
||||
},
|
||||
handlerSubmit(formValue) {
|
||||
this.isCreate === 0 ? this.handlerSave(formValue) : this.handlerEdit(formValue)
|
||||
},
|
||||
handlerSave(formValue) {
|
||||
const _pram = this.buildFormPram(formValue)
|
||||
systemGroupDataApi.groupDataSave(_pram).then(data => {
|
||||
this.$message.success('添加数据成功')
|
||||
this.$emit('hideDialog')
|
||||
})
|
||||
},
|
||||
handlerEdit(formValue) {
|
||||
const _pram = this.buildFormPram(formValue)
|
||||
systemGroupDataApi.groupDataEdit(_pram, this.editData.id).then(data => {
|
||||
this.$message.success('编辑数据成功')
|
||||
this.$emit('hideDialog')
|
||||
})
|
||||
},
|
||||
buildFormPram(formValue) {
|
||||
const _pram = {
|
||||
gid: this.formData.id,
|
||||
form: {
|
||||
fields: [],
|
||||
id: this.formData.formId,
|
||||
sort: this.selfForm.sort,
|
||||
status: this.selfForm.status
|
||||
}}
|
||||
const _fields = []
|
||||
Object.keys(formValue).forEach((key) => {
|
||||
_fields.push({
|
||||
name: key,
|
||||
title: key,
|
||||
value: formValue[key]
|
||||
})
|
||||
})
|
||||
_pram.form.fields = _fields
|
||||
return _pram
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
143
admin/src/views/maintain/devconfig/combinedData.vue
Normal file
143
admin/src/views/maintain/devconfig/combinedData.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="container">
|
||||
<el-form inline>
|
||||
<el-form-item label="数据搜索">
|
||||
<el-input v-model="listPram.keywords" placeholder="请输入ID,KEY,组合数据名称,简介" class="selWidth" size="small">
|
||||
<el-button slot="append" icon="el-icon-search" size="small" @click="handlerSearch" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-button size="mini" type="primary" @click="handlerOpenEdit({},0)">添加数据组</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="dataList.list"
|
||||
style="width: 100%;margin-bottom: 20px;"
|
||||
size="mini"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column label="数据组名称" prop="name" min-width="150"/>
|
||||
<el-table-column label="简介" prop="info" min-width="150"/>
|
||||
<el-table-column label="操作" fixed="right" min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="small" type="text" @click="handleDataList(scope.row)">数据列表</el-button>
|
||||
<el-button size="small" type="text" @click="handlerOpenEdit(scope.row, 1)">编辑</el-button>
|
||||
<el-button size="small" type="text" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="listPram.page"
|
||||
:page-sizes="constants.page.limit"
|
||||
:layout="constants.page.layout"
|
||||
:total="dataList.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-dialog
|
||||
:title="editDialogConfig.isCreate === 0?'创建数据组':'编辑数据组'"
|
||||
:visible.sync="editDialogConfig.visible"
|
||||
>
|
||||
<edit
|
||||
v-if="editDialogConfig.visible"
|
||||
:is-create="editDialogConfig.isCreate"
|
||||
:edit-data="editDialogConfig.editData"
|
||||
@hideDialog="handlerHideDialog"
|
||||
/>
|
||||
</el-dialog>
|
||||
<el-dialog title="组合数据列表" :visible.sync="comDataListConfig.visible" fullscreen>
|
||||
<cm-data-list v-if="comDataListConfig.visible" :form-data="comDataListConfig.formData" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import edit from '@/views/maintain/devconfig/combinedDataEdit'
|
||||
import * as systemGroupApi from '@/api/systemGroup'
|
||||
import cmDataList from './combineDataList'
|
||||
export default {
|
||||
// name: "combinedData"
|
||||
components: { edit, cmDataList },
|
||||
data() {
|
||||
return {
|
||||
constants,
|
||||
dataList: {
|
||||
list: [],
|
||||
total: 0
|
||||
},
|
||||
listPram: {
|
||||
keywords: null,
|
||||
page: 1,
|
||||
pageSize: constants.page.limit[0]
|
||||
},
|
||||
editDialogConfig: {
|
||||
visible: false,
|
||||
isCreate: 0, // 0=创建 1=编辑
|
||||
editData: {}
|
||||
},
|
||||
comDataListConfig: {
|
||||
visible: false,
|
||||
formData: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handlerGetList(this.listPram)
|
||||
},
|
||||
methods: {
|
||||
handlerSearch() {
|
||||
this.listPram.page = 1
|
||||
this.handlerGetList(this.listPram)
|
||||
},
|
||||
handlerOpenEdit(editData, isCreate) {
|
||||
isCreate === 0 ? this.editDialogConfig.editData = {} : this.editDialogConfig.editData = editData
|
||||
this.editDialogConfig.isCreate = isCreate
|
||||
this.editDialogConfig.visible = true
|
||||
},
|
||||
handlerGetList(pram) {
|
||||
systemGroupApi.groupList(pram).then(data => {
|
||||
this.dataList = data
|
||||
})
|
||||
},
|
||||
handleDataList(rowData) {
|
||||
if (rowData.formId <= 0) return this.$message.error('请先关联表单')
|
||||
this.comDataListConfig.formData = rowData
|
||||
this.comDataListConfig.visible = true
|
||||
},
|
||||
handleDelete(rowData) {
|
||||
this.$confirm('确定删除当前数据', '提示').then(() => {
|
||||
systemGroupApi.groupDelete(rowData).then(data => {
|
||||
this.$message.success('删除数据成功')
|
||||
setTimeout(() => {
|
||||
this.handlerGetList(this.listPram)
|
||||
}, 800)
|
||||
})
|
||||
})
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.listPram.limit = val
|
||||
this.handlerGetList(this.listPram)
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.listPram.page = val
|
||||
this.handlerGetList(this.listPram)
|
||||
},
|
||||
handlerHideDialog() {
|
||||
setTimeout(() => {
|
||||
this.editDialogConfig.visible = false
|
||||
this.handlerGetList(this.listPram)
|
||||
}, 800)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
108
admin/src/views/maintain/devconfig/combinedDataEdit.vue
Normal file
108
admin/src/views/maintain/devconfig/combinedDataEdit.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<el-form ref="editPram" :model="editPram" label-width="100px">
|
||||
<el-form-item
|
||||
label="数据组名称"
|
||||
prop="name"
|
||||
:rules="[{ required:true, message:'填写数据组名称', trigger:['blur','change'] }]"
|
||||
>
|
||||
<el-input v-model="editPram.name" placeholder="数据组名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="数据简介"
|
||||
prop="info"
|
||||
:rules="[{ required:true, message:'填写数据简介', trigger:['blur','change'] }]"
|
||||
>
|
||||
<el-input v-model="editPram.info" placeholder="数据简介" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="表单数据ID"
|
||||
prop="formId"
|
||||
:rules="[{ required:true, message:'请选择表单数据', trigger:['change'] }]"
|
||||
>
|
||||
<span>{{ editPram.formId }}</span>
|
||||
<el-button type="primary" @click="selectFormDialogConfig.visible = true">选择模板数据</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" class="btn-width100" @click="handlerSubmit('editPram')">确定</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-dialog title="选择表单模板" :visible.sync="selectFormDialogConfig.visible" append-to-body>
|
||||
<form-config-list select-model @selectedRowData="handlerSelectedRowData" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import formConfigList from '@/views/maintain/formConfig'
|
||||
import * as systemGroupApi from '@/api/systemGroup'
|
||||
export default {
|
||||
// name: "combinedDataEdit"
|
||||
components: { formConfigList },
|
||||
props: {
|
||||
isCreate: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
editData: {
|
||||
type: Object,
|
||||
default: {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editPram: {
|
||||
formId: null,
|
||||
info: null,
|
||||
name: null,
|
||||
id: null
|
||||
},
|
||||
selectedFormConfigData: {},
|
||||
selectFormDialogConfig: {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handlerInitEditData()
|
||||
},
|
||||
methods: {
|
||||
handlerInitEditData() {
|
||||
if (this.isCreate !== 1) return
|
||||
const { id, name, info, formId, createTime, updateTime } = this.editData
|
||||
this.editPram.id = id
|
||||
this.editPram.name = name
|
||||
this.editPram.info = info
|
||||
this.editPram.formId = formId
|
||||
},
|
||||
handlerSelectedRowData(rowData) {
|
||||
this.selectedFormConfigData = rowData
|
||||
this.editPram.formId = this.selectedFormConfigData.id
|
||||
this.selectFormDialogConfig.visible = false
|
||||
},
|
||||
handlerSubmit(form) {
|
||||
this.$refs[form].validate(result => {
|
||||
if (!result) return
|
||||
this.isCreate === 0 ? this.handlerSave(this.editPram) : this.handlerEdit(this.editPram)
|
||||
})
|
||||
},
|
||||
handlerSave(pram) {
|
||||
systemGroupApi.groupSave(pram).then(data => {
|
||||
this.$message.success('添加组合数据成功')
|
||||
this.$emit('hideDialog')
|
||||
})
|
||||
},
|
||||
handlerEdit(pram) {
|
||||
systemGroupApi.groupEdit(pram).then(data => {
|
||||
this.$message.success('编辑组合数据成功')
|
||||
this.$emit('hideDialog')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
151
admin/src/views/maintain/devconfig/configCategotyEdit.vue
Normal file
151
admin/src/views/maintain/devconfig/configCategotyEdit.vue
Normal file
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<el-form ref="editPram" :model="editPram" label-width="100px">
|
||||
<el-form-item label="父级">
|
||||
<!-- <span>{{ prent.name}}</span>-->
|
||||
<el-cascader
|
||||
v-model="editPram.pid"
|
||||
:options="allTreeList"
|
||||
:props="categoryProps"
|
||||
disabled
|
||||
style="width:100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="分类名称"
|
||||
prop="name"
|
||||
:rules="[{ required:true,message:'请输入分类名称',trigger:['blur','change'] }]"
|
||||
>
|
||||
<el-input v-model="editPram.name" placeholder="分类名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="英文名称" prop="url" :rules="[{required:true,message:'英文名称不能为空',trigger:['blur','change']}]">
|
||||
<el-input v-model="editPram.url" placeholder="URL" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="editPram.sort" :min="1" :max="10" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-switch v-model="editPram.status" :active-value="true" :inactive-value="false" />
|
||||
</el-form-item>
|
||||
<!-- 这里的类型是无限极分类的类型不能当做配置分类的类型,使用下面的扩展字段实现原有业务中的类型-->
|
||||
<!-- <el-form-item label="类型" prop="type" :rules="[{required:true,message:'请选择类型',trigger:['blur']}]">-->
|
||||
<!-- <el-select v-model="editPram.type" disabled>-->
|
||||
<!-- <el-option v-for="item in constants.categoryType" :key="item.value"-->
|
||||
<!-- :label="item.name" :value="item.value"></el-option>-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="类型">-->
|
||||
<!-- <el-radio-group v-model="editPram.extra">-->
|
||||
<!-- <el-radio v-for="item,index in constants.configCategory" :label="item.value">-->
|
||||
<!-- {{ item.label }}-->
|
||||
<!-- </el-radio>-->
|
||||
<!-- </el-radio-group>-->
|
||||
<!-- <!– <el-input type="textarea" v-model="editPram.extra" placeholder="扩展字段"/>–>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item>
|
||||
<el-button size="mini" type="primary" @click="handlerSubmit('editPram')">确定</el-button>
|
||||
<el-button size="mini" @click="close">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import * as categoryApi from '@/api/categoryApi.js'
|
||||
import * as selfUtil from '@/utils/ZBKJIutil.js'
|
||||
export default {
|
||||
// name: "configCategotyEdit"
|
||||
props: {
|
||||
prent: {
|
||||
type: Object,
|
||||
default: 0
|
||||
},
|
||||
isCreate: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
editData: {
|
||||
type: Object
|
||||
},
|
||||
allTreeList: {
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
constants,
|
||||
editPram: {
|
||||
extra: null, // 关联表单id
|
||||
name: null,
|
||||
pid: null,
|
||||
sort: 0,
|
||||
status: true,
|
||||
type: constants.categoryType[5].value,
|
||||
url: null,
|
||||
id: 0
|
||||
},
|
||||
categoryProps: {
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
children: 'child',
|
||||
expandTrigger: 'hover',
|
||||
checkStrictly: true,
|
||||
emitPath: false
|
||||
},
|
||||
parentOptions: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initEditData()
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.$emit('hideEditDialog')
|
||||
},
|
||||
initEditData() {
|
||||
this.parentOptions = selfUtil.addTreeListLabelForCasCard(this.allTreeList)
|
||||
if (this.isCreate !== 1) {
|
||||
const { id } = this.prent
|
||||
this.editPram.pid = id
|
||||
} else {
|
||||
const { extra, name, pid, sort, status, type, url, id } = this.editData
|
||||
// this.editPram.extra = extra
|
||||
this.editPram.name = name
|
||||
this.editPram.pid = pid
|
||||
this.editPram.sort = sort
|
||||
this.editPram.status = status
|
||||
this.editPram.type = type
|
||||
this.editPram.url = url
|
||||
this.editPram.id = id
|
||||
this.editPram.extra = extra
|
||||
}
|
||||
},
|
||||
handlerSubmit(formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (!valid) return
|
||||
this.handlerSaveOrUpdate(this.isCreate === 0)
|
||||
})
|
||||
},
|
||||
handlerSaveOrUpdate(isSave) {
|
||||
if (isSave) {
|
||||
this.editPram.pid = this.prent.id
|
||||
categoryApi.addCategroy(this.editPram).then(data => {
|
||||
this.$emit('hideEditDialog')
|
||||
this.$message.success('创建分类成功')
|
||||
})
|
||||
} else {
|
||||
this.editPram.pid = Array.isArray(this.editPram.pid) ? this.editPram.pid[0] : this.editPram.pid
|
||||
categoryApi.updateCategroy(this.editPram).then(data => {
|
||||
this.$emit('hideEditDialog')
|
||||
this.$message.success('更新分类成功')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
203
admin/src/views/maintain/devconfig/configCategroy.vue
Normal file
203
admin/src/views/maintain/devconfig/configCategroy.vue
Normal file
@@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header">
|
||||
<el-form inline>
|
||||
<el-form-item>
|
||||
<el-button size="mini" type="primary" @click="handlerOpenAdd({id:0,name:'顶层目录'})">添加分类</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table
|
||||
ref="treeList"
|
||||
:data="treeList"
|
||||
style="width: 100%;"
|
||||
row-key="id"
|
||||
size="mini"
|
||||
class="table"
|
||||
highlight-current-row
|
||||
:tree-props="{children: 'child', hasChildren: 'hasChildren'}"
|
||||
>
|
||||
<el-table-column prop="name" label="分类昵称" min-width="300">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.name }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="英文名称" show-overflow-tooltip min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.url }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已关联的表单" show-overflow-tooltip min-width="130">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.extra }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="排序" prop="sort" width="150"></el-table-column>-->
|
||||
<el-table-column label="启用状态" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.status | filterYesOrNo }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="250" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
:disabled="scope.row.pid > 0"
|
||||
@click="handlerOpenAdd(scope.row)"
|
||||
>添加子目录</el-button>
|
||||
<el-button type="text" size="small" @click="handleEditMenu(scope.row)">编辑</el-button>
|
||||
<el-button type="text" size="small" @click="handlerOpenFormConfig(scope.row)">配置列表</el-button>
|
||||
<el-button type="text" size="small" @click="handleDelMenu(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
<el-dialog
|
||||
:title="editDialogConfig.isCreate === 0?'添加分类':'编辑分类'"
|
||||
:visible.sync="editDialogConfig.visible"
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<edit
|
||||
v-if="editDialogConfig.visible"
|
||||
:prent="editDialogConfig.prent"
|
||||
:is-create="editDialogConfig.isCreate"
|
||||
:edit-data="editDialogConfig.data"
|
||||
:biztype="editDialogConfig.biztype"
|
||||
:all-tree-list="treeList"
|
||||
@hideEditDialog="hideEditDialog"
|
||||
/>
|
||||
</el-dialog>
|
||||
<el-dialog title="选择已配置的表单" :visible.sync="configFormSelectedDialog.visible">
|
||||
<span class="color-red">注意:表单不能重复关联</span>
|
||||
<form-config-list
|
||||
v-if="configFormSelectedDialog.visible"
|
||||
select-model
|
||||
@selectedRowData="handlerSelectedRowData"
|
||||
/>
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
<el-button type="primary" style="width:100%;" @click="handlerAddFormExtra">关联</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import * as categoryApi from '@/api/categoryApi.js'
|
||||
import edit from '@/views/maintain/devconfig/configCategotyEdit.vue'
|
||||
import * as selfUtil from '@/utils/ZBKJIutil.js'
|
||||
import configList from './configList'
|
||||
import formConfigList from '@/views/maintain/formConfig'
|
||||
export default {
|
||||
// name: "configCategroy"
|
||||
components: { edit, configList, formConfigList },
|
||||
props: {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
constants,
|
||||
searchPram: {
|
||||
status: null,
|
||||
type: null
|
||||
},
|
||||
editDialogConfig: {
|
||||
visible: false,
|
||||
isCreate: 0, // 0=创建,1=编辑
|
||||
prent: {}, // 父级对象
|
||||
data: {}
|
||||
},
|
||||
treeList: [],
|
||||
listPram: {
|
||||
pid: 0,
|
||||
type: constants.categoryType[5].value,
|
||||
status: null,
|
||||
name: null,
|
||||
page: constants.page.page,
|
||||
limit: constants.page.limit[1]
|
||||
},
|
||||
configFormSelectedDialog: {
|
||||
visible: false,
|
||||
currentData: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handlerGetTreeList()
|
||||
},
|
||||
methods: {
|
||||
handlerOpenFormConfig(rowData) {
|
||||
this.configFormSelectedDialog.currentData = rowData
|
||||
this.configFormSelectedDialog.visible = true
|
||||
},
|
||||
handlerGetList() {
|
||||
categoryApi.listCategroy(this.listPram).then(data => {
|
||||
// this.dataList = data
|
||||
this.treeList = data.list
|
||||
})
|
||||
},
|
||||
handlerOpenAdd(rowData) {
|
||||
this.editDialogConfig.isCreate = 0
|
||||
this.editDialogConfig.prent = rowData
|
||||
this.editDialogConfig.data = {}
|
||||
this.editDialogConfig.biztype = this.biztype
|
||||
this.editDialogConfig.visible = true
|
||||
},
|
||||
handleEditMenu(rowData) {
|
||||
this.editDialogConfig.isCreate = 1
|
||||
this.editDialogConfig.data = rowData
|
||||
this.editDialogConfig.prent = rowData
|
||||
this.editDialogConfig.visible = true
|
||||
},
|
||||
handleDelMenu(rowData) {
|
||||
this.$confirm('确定删除当前数据?').then(() => {
|
||||
categoryApi.deleteCategroy(rowData).then(data => {
|
||||
this.handlerGetTreeList()
|
||||
this.$message.success('删除成功')
|
||||
})
|
||||
})
|
||||
},
|
||||
hideEditDialog() {
|
||||
setTimeout(() => {
|
||||
this.editDialogConfig.prent = {}
|
||||
this.editDialogConfig.type = 0
|
||||
this.editDialogConfig.visible = false
|
||||
this.handlerGetTreeList()
|
||||
}, 200)
|
||||
},
|
||||
handlerGetTreeList() {
|
||||
// status: this.selectModel?1:-1
|
||||
const _pram = { type: constants.categoryType[5].value, status: -1 }
|
||||
categoryApi.treeCategroy(_pram).then(data => {
|
||||
this.treeList = this.handleAddArrt(data)
|
||||
})
|
||||
},
|
||||
handleAddArrt(treeData) {
|
||||
// let _result = this.addTreeListLabel(treeData)
|
||||
const _result = selfUtil.addTreeListLabel(treeData)
|
||||
return _result
|
||||
},
|
||||
handlerSelectedRowData(rowData) {
|
||||
this.configFormSelectedDialog.currentData.extra = rowData.id
|
||||
},
|
||||
handlerAddFormExtra() {
|
||||
categoryApi.updateCategroy(this.configFormSelectedDialog.currentData).then(data => {
|
||||
this.$message.success('关联表单成功')
|
||||
setTimeout(() => {
|
||||
this.configFormSelectedDialog.visible = false
|
||||
this.handlerGetTreeList()
|
||||
}, 800)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
23
admin/src/views/maintain/devconfig/configList.vue
Normal file
23
admin/src/views/maintain/devconfig/configList.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<config-list :prent-data="prentData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import configList from '@/components/FormGenerator/index/Home.vue'
|
||||
export default {
|
||||
components: { configList },
|
||||
// name: "configList",
|
||||
props: {
|
||||
prentData: {
|
||||
type: Object,
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
56
admin/src/views/maintain/formConfig/edit.vue
Normal file
56
admin/src/views/maintain/formConfig/edit.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div>
|
||||
<config-list
|
||||
:edit-data="editData"
|
||||
:is-create="isCreate"
|
||||
@getFormConfigDataResult="handlerGetFormConfigData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import configList from '@/components/FormGenerator/index/Home.vue'
|
||||
import * as systemFormConfigApi from '@/api/systemFormConfig.js'
|
||||
export default {
|
||||
// name: "edit"
|
||||
components: { configList },
|
||||
props: {
|
||||
editData: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
isCreate: {
|
||||
type: Number,
|
||||
default: 0 // 0=创建,1=编辑
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
handlerGetFormConfigData(formConfigData) {
|
||||
formConfigData.id ? this.handlerEdit(formConfigData) : this.handlerSave(formConfigData)
|
||||
},
|
||||
handlerSave(pram) {
|
||||
systemFormConfigApi.getFormConfigSave(pram).then(data => {
|
||||
this.$message.success('创建表单配置成功')
|
||||
setTimeout(() => {
|
||||
this.$emit('hideDialog')
|
||||
}, 800)
|
||||
})
|
||||
},
|
||||
handlerEdit(pram) {
|
||||
systemFormConfigApi.getFormConfigEdit(pram).then(data => {
|
||||
this.$message.success('编辑表单配置成功')
|
||||
setTimeout(() => {
|
||||
this.$emit('hideDialog')
|
||||
}, 800)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
142
admin/src/views/maintain/formConfig/index.vue
Normal file
142
admin/src/views/maintain/formConfig/index.vue
Normal file
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="container">
|
||||
<el-form inline size="small">
|
||||
<el-form-item label="关键字">
|
||||
<el-input v-model="listPram.keywords" placeholder="请输入id,名称,描述" clearable class="selWidth" size="small">
|
||||
<el-button slot="append" icon="el-icon-search" size="small" @click="handlerSearch" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="selectModel">
|
||||
<el-button type="primary" :disabled="!selectedConfigData.id" @click="handlerConfimSelect">确定选择</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-button size="mini" type="primary" @click="handlerEditData({},0)" v-if="!selectModel">创建表单</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="dataList.list"
|
||||
:highlight-current-row="selectModel"
|
||||
size="mini"
|
||||
class="table"
|
||||
highlight-current-row
|
||||
@current-change="handleCurrentRowChange"
|
||||
>
|
||||
<el-table-column label="ID" prop="id" width="80"/>
|
||||
<el-table-column label="名称" prop="name" min-width="180"/>
|
||||
<el-table-column label="描述" prop="info" min-width="220"/>
|
||||
<el-table-column label="更新时间" prop="updateTime" min-width="200" />
|
||||
<el-table-column v-if="!selectModel" label="操作" min-width="80" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="handlerEditData(scope.row,1)">编辑</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="listPram.page"
|
||||
:page-sizes="constants.page.limit"
|
||||
:layout="constants.page.layout"
|
||||
:total="dataList.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</el-card>
|
||||
<el-dialog
|
||||
:visible.sync="editDialogConfig.visible"
|
||||
title="title"
|
||||
fullscreen
|
||||
:title="editDialogConfig.isCreate === 0? '创建表单':'编辑表单'"
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<edit
|
||||
v-if="editDialogConfig.visible"
|
||||
:is-create="editDialogConfig.isCreate"
|
||||
:edit-data="editDialogConfig.editData"
|
||||
@hideDialog="handlerHide"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as systemFormConfigApi from '@/api/systemFormConfig.js'
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import edit from './edit'
|
||||
export default {
|
||||
// name: "index"
|
||||
components: { edit },
|
||||
props: {
|
||||
selectModel: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
constants,
|
||||
listPram: {
|
||||
keywords: null,
|
||||
page: 1,
|
||||
limit: constants.page.limit[0]
|
||||
},
|
||||
editDialogConfig: {
|
||||
visible: false,
|
||||
editData: {},
|
||||
isCreate: 0
|
||||
},
|
||||
dataList: { list: [], total: 0 },
|
||||
selectedConfigData: {}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handlerGetList(this.listPram)
|
||||
},
|
||||
methods: {
|
||||
handlerSearch() {
|
||||
this.listPram.page = 1
|
||||
this.handlerGetList(this.listPram)
|
||||
},
|
||||
handlerGetList(pram) {
|
||||
systemFormConfigApi.getFormConfigList(pram).then(data => {
|
||||
this.dataList = data
|
||||
})
|
||||
},
|
||||
handlerEditData(rowData, isCreate) {
|
||||
if (isCreate === 0) {
|
||||
this.editDialogConfig.editData = {}
|
||||
} else {
|
||||
this.editDialogConfig.editData = rowData
|
||||
}
|
||||
this.editDialogConfig.isCreate = isCreate
|
||||
this.editDialogConfig.visible = true
|
||||
},
|
||||
handlerHide() {
|
||||
this.editDialogConfig.editData = {}
|
||||
this.editDialogConfig.isCreate = 0
|
||||
this.editDialogConfig.visible = false
|
||||
this.handlerGetList(this.listPram)
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.listPram.limit = val
|
||||
this.handlerGetList(this.listPram)
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.listPram.page = val
|
||||
this.handlerGetList(this.listPram)
|
||||
},
|
||||
handleCurrentRowChange(rowData) {
|
||||
this.selectedConfigData = rowData
|
||||
},
|
||||
handlerConfimSelect() {
|
||||
this.$emit('selectedRowData', this.selectedConfigData)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/maintain/index.vue
Normal file
15
admin/src/views/maintain/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
110
admin/src/views/maintain/user/index.vue
Normal file
110
admin/src/views/maintain/user/index.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<el-form ref="pram" :model="pram" :rules="rules" label-width="100px">
|
||||
<el-form-item label="管理员账号" prop="account">
|
||||
<el-input v-model="pram.account" placeholder="管理员账号" :disabled="true"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="管理员姓名" prop="realName">
|
||||
<el-input v-model="pram.realName" placeholder="管理员姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="原始密码">
|
||||
<el-input v-model="password" placeholder="原始密码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码" prop="pwd">
|
||||
<el-input
|
||||
v-model="pram.pwd"
|
||||
placeholder="管理员密码,不更改可以不填写"
|
||||
clearable
|
||||
@input="handlerPwdInput"
|
||||
@clear="handlerPwdInput"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="pram.pwd" label="确认新密码" prop="repwd">
|
||||
<el-input v-model="pram.repwd" placeholder="确认新密码" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handlerSubmit('pram')">提交</el-button>
|
||||
<el-button @click="close('pram')">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as systemAdminApi from '@/api/systemadmin.js'
|
||||
import Cookies from 'js-cookie'
|
||||
export default {
|
||||
name: "index",
|
||||
data() {
|
||||
const validatePass = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请再次输入密码'))
|
||||
} else if (value !== this.pram.pwd) {
|
||||
callback(new Error('两次输入密码不一致!'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
password: '',
|
||||
JavaInfo: JSON.parse(Cookies.get('JavaInfo')),
|
||||
pram: {
|
||||
account: JSON.parse(Cookies.get('JavaInfo')).account,
|
||||
pwd: null,
|
||||
repwd: null,
|
||||
realName: null,
|
||||
id: JSON.parse(Cookies.get('JavaInfo')).id
|
||||
},
|
||||
roleList: [],
|
||||
rules: {
|
||||
account: [{ required: true, message: '请填管理员账号', trigger: ['blur', 'change'] }],
|
||||
pwd: [{ required: true, message: '请填管理员密码', trigger: ['blur', 'change'] }],
|
||||
repwd: [{ required: true, message: '确认密码密码', validator: validatePass, trigger: ['blur', 'change'] }],
|
||||
realName: [{ required: true, message: '管理员姓名', trigger: ['blur', 'change'] }],
|
||||
roles: [{ required: true, message: '管理员身份', trigger: ['blur', 'change'] }]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
close(formName) {
|
||||
this.$refs[formName].resetFields();
|
||||
},
|
||||
handlerSubmit(formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
systemAdminApi.adminUpdate(this.pram).then(data => {
|
||||
this.$message.success('提交成功')
|
||||
})
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
handlerPwdInput(val) {
|
||||
if (!val) {
|
||||
this.rules.pwd = []
|
||||
this.rules.repwd = []
|
||||
return
|
||||
}
|
||||
this.rules.pwd = [
|
||||
{ required: true, message: '请填管理员密码', trigger: ['blur', 'change'] },
|
||||
{ min: 6, max: 20, message: '长度6-20个字符', trigger: ['blur', 'change'] }]
|
||||
this.rules.repwd = [{ required: true, message: '两次输入密码不一致', validator: (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('两次输入密码不一致!'))
|
||||
} else if (value !== this.pram.pwd) {
|
||||
callback(new Error('两次输入密码不一致!'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}, trigger: ['blur', 'change'] }]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
13
admin/src/views/marketing/bargain/index.vue
Normal file
13
admin/src/views/marketing/bargain/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>砍价</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/marketing/coupon.vue
Normal file
15
admin/src/views/marketing/coupon.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
营销
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/marketing/coupon/couponTemplate/index.vue
Normal file
15
admin/src/views/marketing/coupon/couponTemplate/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
优惠券模板
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/marketing/coupon/index.vue
Normal file
15
admin/src/views/marketing/coupon/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
271
admin/src/views/marketing/coupon/list/creatCoupon.vue
Normal file
271
admin/src/views/marketing/coupon/list/creatCoupon.vue
Normal file
@@ -0,0 +1,271 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="150px" class="demo-ruleForm">
|
||||
<el-form-item label="优惠劵名称" prop="name">
|
||||
<el-input v-model="ruleForm.name" style="width: 350px" placeholder="请输入优惠券名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠劵类型">
|
||||
<el-radio-group v-model="ruleForm.useType">
|
||||
<el-radio :label="1">通用卷</el-radio>
|
||||
<el-radio :label="2">商品券</el-radio>
|
||||
<el-radio :label="3">品类券</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="选择品类:" prop="primaryKey" v-if="ruleForm.useType === 3">
|
||||
<el-cascader v-model="ruleForm.primaryKey" :options="merCateList" :props="props2" clearable class="selWidth" :show-all-levels="false" />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品:" v-if="ruleForm.useType === 2">
|
||||
<div class="acea-row">
|
||||
<template v-if="checked.length">
|
||||
<div class="pictrue" v-for="(item, index) in checked" :key="index">
|
||||
<img :src="item.image">
|
||||
<i class="el-icon-error btndel" @click="handleRemove(index)" />
|
||||
</div>
|
||||
</template>
|
||||
<div class="upLoadPicBox" @click="changeGood">
|
||||
<div class="upLoad">
|
||||
<i class="el-icon-camera cameraIconfont" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠券面值" prop="money">
|
||||
<el-input-number v-model="ruleForm.money" :min="1" :max="10" label="描述文字"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="使用门槛">
|
||||
<el-radio-group v-model="threshold">
|
||||
<el-radio :label="false">无门槛</el-radio>
|
||||
<el-radio :label="true">有门槛</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠券最低消费" prop="minPrice" v-if="threshold">
|
||||
<el-input-number v-model="ruleForm.minPrice" :min="1" label="描述文字"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="使用有效期">
|
||||
<el-radio-group v-model="ruleForm.isFixedTime">
|
||||
<el-radio :label="false">天数</el-radio>
|
||||
<el-radio :label="true">时间段</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="使用有效期限(天)" prop="resource" v-if="!ruleForm.isFixedTime">
|
||||
<el-input-number v-model="ruleForm.day" :min="0" label="描述文字"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="使用有效期限" prop="resource" v-if="ruleForm.isFixedTime">
|
||||
<el-date-picker
|
||||
style="width: 550px"
|
||||
v-model="termTime"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
format="yyyy - MM - dd - HH : mm : ss"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="领取是否限时" prop="isForever">
|
||||
<el-radio-group v-model="ruleForm.isForever">
|
||||
<el-radio :label="true">限时</el-radio>
|
||||
<el-radio :label="false">不限时</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="领取时间" v-if="ruleForm.isForever">
|
||||
<el-date-picker
|
||||
style="width: 550px"
|
||||
v-model="isForeverTime"
|
||||
type="datetimerange"
|
||||
range-separator="至"
|
||||
format="yyyy - MM - dd - HH : mm : ss"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="领取方式" prop="resource">
|
||||
<el-radio-group v-model="ruleForm.type">
|
||||
<el-radio :label="1">手动领取</el-radio>
|
||||
<el-radio :label="2">新人卷</el-radio>
|
||||
<el-radio :label="3">赠送卷</el-radio>
|
||||
<!--<el-radio :label="4">付费会员卷</el-radio>-->
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否限量" prop="isLimited">
|
||||
<el-radio-group v-model="ruleForm.isLimited">
|
||||
<el-radio :label="true">限量</el-radio>
|
||||
<el-radio :label="false">不限量</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="发布数量" prop="total" v-if="ruleForm.isLimited">
|
||||
<el-input-number v-model="ruleForm.total" :min="1" label="排序"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number v-model="ruleForm.sort" :min="0" label="排序"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="ruleForm.status">
|
||||
<el-radio :label="true">开启</el-radio>
|
||||
<el-radio :label="false">关闭</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="mini" type="primary" @click="submitForm('ruleForm')" :loading="loading">立即创建</el-button>
|
||||
<!--<el-button @click="resetForm('ruleForm')">重置</el-button>-->
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { couponSaveApi, couponInfoApi } from '@/api/marketing'
|
||||
import { categoryApi } from '@/api/store'
|
||||
export default {
|
||||
name: "creatCoupon",
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
threshold: false,
|
||||
termTime: [],
|
||||
isForeverTime: [],
|
||||
props2: {
|
||||
children: 'child',
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
checkStrictly: true,
|
||||
emitPath: false
|
||||
},
|
||||
couponType: 0,
|
||||
term: 'termday',
|
||||
merCateList: [], // 商户分类筛选
|
||||
ruleForm: {
|
||||
useType: 1,
|
||||
isFixedTime: false,
|
||||
name: '',
|
||||
money: 1,
|
||||
minPrice: 1,
|
||||
day: null,
|
||||
isForever: false,
|
||||
primaryKey: '',
|
||||
type: 2,
|
||||
isLimited: false,
|
||||
useStartTime: '', // 使用
|
||||
useEndTime: '', // 结束
|
||||
receiveStartTime: '', //领取
|
||||
receiveEndTime: '',
|
||||
sort: 0,
|
||||
total: 1,
|
||||
status: false
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: '请输入优惠券名称', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
checked: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getCategorySelect()
|
||||
if( this.$route.params.id ) this.getInfo()
|
||||
},
|
||||
methods: {
|
||||
// 商品分类;
|
||||
getCategorySelect() {
|
||||
categoryApi({ status: -1, type: 1 }).then(res => {
|
||||
this.merCateList = res
|
||||
this.merCateList.map(item => {
|
||||
this.$set(item , 'disabled', true)
|
||||
})
|
||||
})
|
||||
},
|
||||
getInfo(){
|
||||
this.loading = true
|
||||
couponInfoApi({id: this.$route.params.id}).then(res => {
|
||||
const info = res.coupon
|
||||
this.ruleForm = {
|
||||
useType: info.useType,
|
||||
isFixedTime: info.isFixedTime,
|
||||
isForever: info.isForever,
|
||||
name: info.name,
|
||||
money: info.money,
|
||||
minPrice: info.minPrice,
|
||||
day: info.day,
|
||||
type: info.type,
|
||||
isLimited: info.isLimited,
|
||||
sort: info.sort,
|
||||
total: info.total,
|
||||
status: info.status,
|
||||
primaryKey: Number(info.primaryKey)
|
||||
}
|
||||
this.checked = res.product
|
||||
info.minPrice === 0 ? this.threshold = false : this.threshold = true
|
||||
info.isForever ? this.isForeverTime = [info.receiveStartTime, info.receiveEndTime] : this.isForeverTime = []
|
||||
info.isFixedTime ? this.termTime = [info.useStartTime, info.useEndTime] : this.termTime = []
|
||||
this.loading = false
|
||||
}).catch(res => {
|
||||
this.loading = false
|
||||
this.$message.error(res.message)
|
||||
})
|
||||
},
|
||||
handleRemove (i) {
|
||||
this.checked.splice(i, 1)
|
||||
},
|
||||
changeGood(){
|
||||
const _this = this
|
||||
this.$modalGoodList(function(row) {
|
||||
_this.checked = row
|
||||
},'many',_this.checked)
|
||||
},
|
||||
submitForm(formName) {
|
||||
if( this.ruleForm.useType === 2 ) this.ruleForm.primaryKey = this.checked.map(item => {return item.id}).join(',')
|
||||
if( this.ruleForm.useType === 1 ) this.ruleForm.primaryKey = ''
|
||||
if( !this.threshold ) this.ruleForm.minPrice = 0
|
||||
if( !this.ruleForm.isLimited ) this.ruleForm.total = 0
|
||||
this.ruleForm.isFixedTime && this.termTime.length ? (this.ruleForm.useStartTime = this.termTime[0], this.ruleForm.day = null) : this.ruleForm.useStartTime = ''
|
||||
this.ruleForm.isFixedTime && this.termTime.length ? (this.ruleForm.useEndTime = this.termTime[1], this.ruleForm.day = null) : this.ruleForm.useEndTime = ''
|
||||
this.ruleForm.isForever && this.isForeverTime.length ? this.ruleForm.receiveStartTime = this.isForeverTime[0] : this.ruleForm.receiveStartTime = ''
|
||||
this.ruleForm.isForever && this.isForeverTime.length ? this.ruleForm.receiveEndTime = this.isForeverTime[1] : this.ruleForm.receiveEndTime = ''
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
couponSaveApi(this.ruleForm).then(() => {
|
||||
this.$message.success("新增成功")
|
||||
this.loading = false
|
||||
setTimeout(() => {
|
||||
this.$router.push({ path: `/marketing/coupon/list` })
|
||||
}, 200);
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
} else {
|
||||
this.loading = false
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.pictrue{
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px dotted rgba(0,0,0,0.1);
|
||||
margin-right: 10px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.btndel{
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width :20px !important;
|
||||
height: 20px !important;
|
||||
left: 46px;
|
||||
top: -4px;
|
||||
}
|
||||
</style>
|
||||
295
admin/src/views/marketing/coupon/list/index.vue
Normal file
295
admin/src/views/marketing/coupon/list/index.vue
Normal file
@@ -0,0 +1,295 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="filter-container">
|
||||
<div class="demo-input-suffix acea-row">
|
||||
<span class="seachTiele">状态:</span>
|
||||
<el-select v-model="tableFrom.status" placeholder="请选择" class="filter-item selWidth mr20" @change="seachList" clearable>
|
||||
<el-option label="未开启" :value="0" />
|
||||
<el-option label="开启" :value="1" />
|
||||
</el-select>
|
||||
<span class="seachTiele">优惠券名称:</span>
|
||||
<el-input v-model="tableFrom.name" placeholder="请输入优惠券名称" class="selWidth">
|
||||
<el-button slot="append" icon="el-icon-search" @click="seachList" />
|
||||
</el-input>
|
||||
</div>
|
||||
</div>
|
||||
<router-link :to=" { path: '/marketing/coupon/list/save' } ">
|
||||
<el-button size="small" type="primary">添加优惠劵</el-button>
|
||||
</router-link>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
min-width="50"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="名称"
|
||||
min-width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
label="类型"
|
||||
min-width="80"
|
||||
>
|
||||
<template slot-scope="{ row }">
|
||||
<span>{{row.useType | couponUserTypeFilter}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="money"
|
||||
label="面值"
|
||||
min-width="100"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="领取方式"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="{ row }">
|
||||
<span>{{row.useType | couponTypeFilter}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
min-width="260"
|
||||
label="领取日期"
|
||||
>
|
||||
<template slot-scope="{ row }">
|
||||
<div v-if="row.receiveEndTime">
|
||||
{{ row.receiveStartTime }} - {{ row.receiveEndTime }}
|
||||
</div>
|
||||
<span v-else>不限时</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
min-width="260"
|
||||
label="使用时间"
|
||||
>
|
||||
<template slot-scope="{ row }">
|
||||
<div v-if="row.day">
|
||||
{{ row.day }}天
|
||||
</div>
|
||||
<span v-else>
|
||||
{{ row.useStartTime }} - {{ row.useEndTime }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
min-width="100"
|
||||
label="发布数量"
|
||||
>
|
||||
<template slot-scope="{ row }">
|
||||
<span v-if=" !row.isLimited ">不限量</span>
|
||||
<div v-else>
|
||||
<span class="fa">发布:{{ row.total }}</span>
|
||||
<span class="sheng">剩余:{{ row.lastTotal }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="是否开启"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.status"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
active-text="开启"
|
||||
inactive-text="关闭"
|
||||
@click.native="onchangeIsShow(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="130" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" class="mr10" size="small" @click="receive(scope.row)">领取记录</el-button>
|
||||
<router-link :to=" { path: '/marketing/coupon/list/save/' + scope.row.id } ">
|
||||
<el-button type="text" size="small">复制</el-button>
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
<!--领取记录-->
|
||||
<el-dialog
|
||||
title="领取记录"
|
||||
:visible.sync="dialogVisible"
|
||||
width="500px"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<el-table
|
||||
v-loading="Loading"
|
||||
:data="issueData.data"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column
|
||||
prop="user.nickname"
|
||||
label="用户名"
|
||||
min-width="120"
|
||||
/>
|
||||
<el-table-column label="用户头像" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<div class="demo-image__preview">
|
||||
<el-image
|
||||
style="width: 36px; height: 36px"
|
||||
:src="scope.row.avatar"
|
||||
:preview-src-list="[scope.row.avatar]"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
label="领取时间"
|
||||
min-width="180"
|
||||
/>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[10, 20, 30, 40]"
|
||||
:page-size="tableFromIssue.limit"
|
||||
:current-page="tableFromIssue.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="issueData.total"
|
||||
@size-change="handleSizeChangeIssue"
|
||||
@current-change="pageChangeIssue"
|
||||
/>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { marketingListApi, couponIssueStatusApi, couponUserListApi } from '@/api/marketing'
|
||||
import { roterPre } from '@/settings'
|
||||
export default {
|
||||
name: 'CouponList',
|
||||
data() {
|
||||
return {
|
||||
Loading: false,
|
||||
dialogVisible: false,
|
||||
roterPre: roterPre,
|
||||
listLoading: true,
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
tableFrom: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
status: '',
|
||||
name: ''
|
||||
},
|
||||
tableFromIssue: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
couponId: ''
|
||||
},
|
||||
issueData: {
|
||||
data: [],
|
||||
total: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
seachList() {
|
||||
this.tableFrom.page = 1
|
||||
this.getList()
|
||||
},
|
||||
handleClose() {
|
||||
this.dialogVisible = false
|
||||
},
|
||||
// 领取记录
|
||||
receive(row) {
|
||||
this.dialogVisible = true
|
||||
this.getIssueList(row)
|
||||
},
|
||||
// 列表
|
||||
getIssueList(row) {
|
||||
this.Loading = true
|
||||
this.tableFromIssue.couponId = row.id
|
||||
couponUserListApi(this.tableFromIssue).then(res => {
|
||||
this.issueData.data = res.list
|
||||
this.issueData.total = res.total
|
||||
this.Loading = false
|
||||
}).catch(res => {
|
||||
this.Loading = false
|
||||
this.$message.error(res.message)
|
||||
})
|
||||
},
|
||||
pageChangeIssue(page) {
|
||||
this.tableFromIssue.page = page
|
||||
this.getIssueList()
|
||||
},
|
||||
handleSizeChangeIssue(val) {
|
||||
this.tableFromIssue.limit = val
|
||||
this.getIssueList()
|
||||
},
|
||||
// 列表
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
marketingListApi(this.tableFrom).then(res => {
|
||||
this.tableData.data = res.list
|
||||
this.tableData.total = res.total
|
||||
this.listLoading = false
|
||||
}).catch(res => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
pageChange(page) {
|
||||
this.tableFrom.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val
|
||||
this.getList()
|
||||
},
|
||||
// 修改状态
|
||||
onchangeIsShow(row) {
|
||||
couponIssueStatusApi({id:row.id, status:row.status}).then(() => {
|
||||
this.$message.success('修改成功')
|
||||
this.getList()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.selWidth{
|
||||
width: 350px !important;
|
||||
}
|
||||
.seachTiele{
|
||||
line-height: 35px;
|
||||
}
|
||||
.fa{
|
||||
color: #0a6aa1;
|
||||
display: block;
|
||||
}
|
||||
.sheng{
|
||||
color: #ff0000;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
201
admin/src/views/marketing/coupon/record/index.vue
Normal file
201
admin/src/views/marketing/coupon/record/index.vue
Normal file
@@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="filter-container">
|
||||
<el-form :inline="true">
|
||||
<el-form-item label="使用状态:" class="mr10">
|
||||
<el-select v-model="tableFromIssue.status" placeholder="请选择评价状态" clearable class="selWidth" @change="seachList">
|
||||
<el-option label="已使用" value="1" />
|
||||
<el-option label="未使用" value="0" />
|
||||
<el-option label="已过期" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="领取人:" class="mr10">
|
||||
<el-input v-model="tableFromIssue.coupon_id" placeholder="请输入领取人" class="selWidth">
|
||||
<el-button size="mini" slot="append" icon="el-icon-search" @click="seachList"/>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="优惠劵:" class="mr10">
|
||||
<el-input v-model="tableFromIssue.name" placeholder="请输入优惠劵" class="selWidth">
|
||||
<el-button slot="append" icon="el-icon-search" @click="seachList"/>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="Loading"
|
||||
:data="issueData.data"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column
|
||||
prop="couponId"
|
||||
label="优惠券ID"
|
||||
min-width="80"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="优惠券名称"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="nickname"
|
||||
label="领取人"
|
||||
min-width="130"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="money"
|
||||
label="面值"
|
||||
min-width="100"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="minPrice"
|
||||
label="最低消费额"
|
||||
min-width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="startTime"
|
||||
label="开始使用时间"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="endTime"
|
||||
label="结束使用时间"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column
|
||||
label="获取方式"
|
||||
min-width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.type | failFilter}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="is_fail"
|
||||
label="是否可用"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<i v-if="scope.row.status === 0" class="el-icon-check" style="font-size: 14px;color: #0092DC;" />
|
||||
<i v-else class="el-icon-download" style="font-size: 14px;color: #ed5565;" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="使用状态"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.status | statusFilter}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFromIssue.limit"
|
||||
:current-page="tableFromIssue.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="issueData.total"
|
||||
@size-change="handleSizeChangeIssue"
|
||||
@current-change="pageChangeIssue"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { couponUserListApi } from '@/api/marketing'
|
||||
import { roterPre } from '@/settings'
|
||||
export default {
|
||||
name: 'CouponUser',
|
||||
filters: {
|
||||
failFilter(status) {
|
||||
const statusMap = {
|
||||
'receive': '自己领取',
|
||||
'send': '后台发送',
|
||||
'give': '满赠',
|
||||
'new': '新人',
|
||||
'buy': '买赠送'
|
||||
}
|
||||
return statusMap[status]
|
||||
},
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
0: '未使用',
|
||||
1: '已使用',
|
||||
2: '已过期'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
Loading: false,
|
||||
roterPre: roterPre,
|
||||
imgList: [],
|
||||
tableFromIssue: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
name: '',
|
||||
status: ''
|
||||
},
|
||||
issueData: {
|
||||
data: [],
|
||||
total: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getIssueList()
|
||||
},
|
||||
methods: {
|
||||
seachList() {
|
||||
this.tableFromIssue.page = 1
|
||||
this.getIssueList()
|
||||
},
|
||||
// 列表
|
||||
getIssueList() {
|
||||
this.Loading = true
|
||||
couponUserListApi(this.tableFromIssue).then(res => {
|
||||
this.issueData.data = res.list
|
||||
this.issueData.total = res.total
|
||||
// this.issueData.data.map((item) => {
|
||||
// this.imgList.push(item.user.avatar)
|
||||
// })
|
||||
this.Loading = false
|
||||
}).catch(res => {
|
||||
this.Loading = false
|
||||
this.$message.error(res.message)
|
||||
})
|
||||
},
|
||||
pageChangeIssue(page) {
|
||||
this.tableFromIssue.page = page
|
||||
this.getIssueList()
|
||||
},
|
||||
handleSizeChangeIssue(val) {
|
||||
this.tableFromIssue.limit = val
|
||||
this.getIssueList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.selWidth{
|
||||
width: 350px !important;
|
||||
}
|
||||
.seachTiele{
|
||||
line-height: 35px;
|
||||
}
|
||||
.fa{
|
||||
color: #0a6aa1;
|
||||
display: block;
|
||||
}
|
||||
.sheng{
|
||||
color: #ff0000;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
13
admin/src/views/marketing/groupBuy/goods/index.vue
Normal file
13
admin/src/views/marketing/groupBuy/goods/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>拼团</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/marketing/groupBuy/index.vue
Normal file
15
admin/src/views/marketing/groupBuy/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
13
admin/src/views/marketing/groupBuy/list/list.vue
Normal file
13
admin/src/views/marketing/groupBuy/list/list.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>list222</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
39
admin/src/views/marketing/integral/config/index.vue
Normal file
39
admin/src/views/marketing/integral/config/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<zb-parser
|
||||
:form-id="109"
|
||||
:is-create="isCreate"
|
||||
:edit-data="editData"
|
||||
@submit="handlerSubmit"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import zbParser from '@/components/FormGenerator/components/parser/ZBParser'
|
||||
import { smsSaveApi } from '@/api/sms'
|
||||
export default {
|
||||
name: "integralconfig",
|
||||
components: { zbParser },
|
||||
data() {
|
||||
return {
|
||||
isCreate: 0,
|
||||
editData: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handlerSubmit(formValue) {
|
||||
smsSaveApi(formValue).then(data => {
|
||||
this.$message.success('新增成功')
|
||||
this.editData = {}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/marketing/integral/index.vue
Normal file
15
admin/src/views/marketing/integral/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
104
admin/src/views/marketing/spike/config/edit.vue
Normal file
104
admin/src/views/marketing/spike/config/edit.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<div>
|
||||
<zb-parser
|
||||
v-if="formConf.fields.length > 0"
|
||||
:form-id="formid"
|
||||
:is-create="isCreate"
|
||||
:edit-data="editData"
|
||||
@submit="handlerSubmit"
|
||||
/>
|
||||
<!-- {{ editData }}-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import zbParser from '@/components/FormGenerator/components/parser/ZBParser'
|
||||
import * as systemGroupDataApi from '@/api/systemGroupData.js'
|
||||
import * as systemFormConfigApi from '@/api/systemFormConfig.js'
|
||||
export default {
|
||||
// name: "combineEdit"
|
||||
components: { zbParser },
|
||||
props: {
|
||||
formid: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
isCreate: {
|
||||
type: Number,
|
||||
default: 0 // 0=create 1=edit
|
||||
},
|
||||
editData: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
constants,
|
||||
formConf: { fields: [] },
|
||||
selfForm: {
|
||||
sort: 0,
|
||||
status: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handlerGetFormConfig()
|
||||
this.handlerInitEditData()
|
||||
},
|
||||
methods: {
|
||||
handlerInitEditData() {
|
||||
const { sort, status } = this.editData
|
||||
this.selfForm.sort = sort
|
||||
this.selfForm.status = status
|
||||
},
|
||||
handlerGetFormConfig() { // 获取表单配置后生成table列
|
||||
const _pram = { id: this.formid }
|
||||
systemFormConfigApi.getFormConfigInfo(_pram).then(data => {
|
||||
this.formConf = JSON.parse(data.content)
|
||||
})
|
||||
},
|
||||
handlerSubmit(formValue) {
|
||||
this.isCreate === 0 ? this.handlerSave(formValue) : this.handlerEdit(formValue)
|
||||
},
|
||||
handlerSave(formValue) {
|
||||
const _pram = this.buildFormPram(formValue)
|
||||
systemGroupDataApi.groupDataSave(_pram).then(data => {
|
||||
this.$message.success('添加数据成功')
|
||||
this.$emit('hideDialog')
|
||||
})
|
||||
},
|
||||
handlerEdit(formValue) {
|
||||
const _pram = this.buildFormPram(formValue)
|
||||
systemGroupDataApi.groupDataEdit(_pram, this.editData.id).then(data => {
|
||||
this.$message.success('编辑数据成功')
|
||||
this.$emit('hideDialog')
|
||||
})
|
||||
},
|
||||
buildFormPram(formValue) {
|
||||
const _pram = {
|
||||
gid: this.formid,
|
||||
form: {
|
||||
fields: [],
|
||||
id: this.formid
|
||||
// sort: this.selfForm.sort,
|
||||
// status: this.selfForm.status
|
||||
}}
|
||||
const _fields = []
|
||||
Object.keys(formValue).forEach((key) => {
|
||||
_fields.push({
|
||||
name: key,
|
||||
title: key,
|
||||
value: formValue[key]
|
||||
})
|
||||
})
|
||||
_pram.form.fields = _fields
|
||||
return _pram
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
167
admin/src/views/marketing/spike/config/index.vue
Normal file
167
admin/src/views/marketing/spike/config/index.vue
Normal file
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<el-form inline>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handlerOpenEditData({},0)">添加数据</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="listPram.status" placeholder="状态" clearable @change="handlerSearch">
|
||||
<el-option
|
||||
v-for="item in constants.showHiddenStatus"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="关键词">-->
|
||||
<!-- <el-input v-model="listPram.keywords" placeholder="请输入关键词" clearable></el-input>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item>-->
|
||||
<!-- <el-button type="primary" @click="handlerSearch">查询</el-button>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
<el-dialog
|
||||
:title="editDataConfig.isCreate === 0?'添加数据':'编辑数据'"
|
||||
:visible.sync="editDataConfig.visible"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<edit
|
||||
v-if="editDataConfig.visible"
|
||||
:formid="formId"
|
||||
:edit-data="editDataConfig.editData"
|
||||
:is-create="editDataConfig.isCreate"
|
||||
@hideDialog="handlerHideDia"
|
||||
/>
|
||||
</el-dialog>
|
||||
<el-table
|
||||
:data="dataList.list"
|
||||
style="width: 100%;margin-bottom: 20px;"
|
||||
>
|
||||
<el-table-column label="编号" prop="id" />
|
||||
<el-table-column
|
||||
v-for="item,index in formConf.fields"
|
||||
:key="index"
|
||||
:label="item.__config__.label"
|
||||
:prop="item.__vModel__"
|
||||
>
|
||||
<template slot-scope="scope"><!-- 自定义维护特殊列展示 -->
|
||||
<span v-if="item.__config__.label === '状态'">
|
||||
{{ scope.row[item.__vModel__] | filterShowOrHideForFormConfig }}</span>
|
||||
<span v-else>{{ scope.row[item.__vModel__] }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="primary" @click="handlerOpenEditData(scope.row,1)">编辑</el-button>
|
||||
<el-button type="danger" @click="handlerDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="listPram.page"
|
||||
:page-sizes="constants.page.limit"
|
||||
:layout="constants.page.layout"
|
||||
:total="dataList.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import edit from './edit'
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import * as systemGroupDataApi from '@/api/systemGroupData.js'
|
||||
import * as systemFormConfigApi from '@/api/systemFormConfig.js'
|
||||
export default {
|
||||
// name: "combineDataList"
|
||||
components: { edit },
|
||||
data() {
|
||||
return {
|
||||
constants,
|
||||
listPram: {
|
||||
gid: null,
|
||||
keywords: null,
|
||||
status: null, // 1=开启 2=关闭
|
||||
page: 1,
|
||||
limit: constants.page.limit[0]
|
||||
},
|
||||
editDataConfig: {
|
||||
visible: false,
|
||||
isCreate: 0, // 0=create 1=edit
|
||||
editData: {}
|
||||
},
|
||||
formConf: { fields: [] },
|
||||
dataList: { list: [], total: 0 },
|
||||
formId: constants.formConfigIds[1].id
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.handlerGetFormConfig()
|
||||
this.listPram.gid = this.formId
|
||||
this.handlerGetListData(this.listPram)
|
||||
},
|
||||
methods: {
|
||||
handlerSearch() {
|
||||
this.listPram.page = 1
|
||||
this.handlerGetListData(this.listPram)
|
||||
},
|
||||
handlerGetListData(pram) { // 获取列表数据
|
||||
systemGroupDataApi.groupDataList(pram).then(data => {
|
||||
const _selfList = []
|
||||
data.list.forEach(_lItem => {
|
||||
_lItem.value = JSON.parse(_lItem.value)
|
||||
const _fields = _lItem.value.fields
|
||||
const _rowData = {}
|
||||
_fields.map((item) => {
|
||||
_rowData[item.name] = item.value
|
||||
})
|
||||
_rowData.id = _lItem.id
|
||||
_rowData.sort = _lItem.sort
|
||||
_rowData.status = _lItem.status
|
||||
_selfList.push(_rowData)
|
||||
})
|
||||
this.dataList.list = _selfList
|
||||
this.dataList.total = data.total
|
||||
})
|
||||
},
|
||||
handlerGetFormConfig() { // 获取表单配置后生成table列
|
||||
const _pram = { id: this.formId }
|
||||
systemFormConfigApi.getFormConfigInfo(_pram).then(data => {
|
||||
this.formConf = JSON.parse(data.content)
|
||||
})
|
||||
},
|
||||
handlerOpenEditData(rowData, isCreate) {
|
||||
this.editDataConfig.editData = rowData
|
||||
this.editDataConfig.isCreate = isCreate
|
||||
this.editDataConfig.visible = true
|
||||
},
|
||||
handlerHideDia() {
|
||||
this.handlerGetListData(this.listPram)
|
||||
this.editDataConfig.visible = false
|
||||
},
|
||||
handlerDelete(rowData) {
|
||||
this.$confirm('确实删除当前数据', '提示').then(() => {
|
||||
systemGroupDataApi.groupDataDelete(rowData).then(data => {
|
||||
this.$message.success('删除数据成功')
|
||||
this.handlerHideDia()
|
||||
})
|
||||
})
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.listPram.limit = val
|
||||
this.handlerGetListData(this.listPram)
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.listPram.page = val
|
||||
this.handlerGetListData(this.listPram)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
13
admin/src/views/marketing/spike/googs/index.vue
Normal file
13
admin/src/views/marketing/spike/googs/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>秒杀商品</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
15
admin/src/views/marketing/spike/index.vue
Normal file
15
admin/src/views/marketing/spike/index.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
|
||||
</style>
|
||||
565
admin/src/views/order/index.vue
Normal file
565
admin/src/views/order/index.vue
Normal file
@@ -0,0 +1,565 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<!--<el-tabs v-model="tableFrom.type" @tab-click="getList">-->
|
||||
<!--<el-tab-pane label="全部订单" name="" />-->
|
||||
<!--<el-tab-pane label="普通订单" name="1" />-->
|
||||
<!--<el-tab-pane label="拼团订单" name="2" />-->
|
||||
<!--<el-tab-pane label="秒杀订单" name="3" />-->
|
||||
<!--<el-tab-pane label="砍价订单" name="4" />-->
|
||||
<!--</el-tabs>-->
|
||||
<div class="container">
|
||||
<el-form size="small" label-width="100px">
|
||||
<el-form-item label="订单状态:">
|
||||
<el-radio-group v-model="tableFrom.status" type="button" @change="seachList">
|
||||
<el-radio-button label="all">全部 {{ '(' +orderChartType.all?orderChartType.all:0 + ')' }}</el-radio-button>
|
||||
<el-radio-button label="unPaid">未支付 {{ '(' +orderChartType.unPaid?orderChartType.unPaid:0+ ')' }}</el-radio-button>
|
||||
<el-radio-button label="notShipped">未发货 {{ '(' +orderChartType.notShipped?orderChartType.notShipped:0+ ')' }}</el-radio-button>
|
||||
<el-radio-button label="spike">待收货 {{ '(' +orderChartType.spike?orderChartType.spike:0+ ')' }}</el-radio-button>
|
||||
<el-radio-button label="bargain">待评价 {{ '(' +orderChartType.bargain?orderChartType.bargain:0+ ')' }}</el-radio-button>
|
||||
<el-radio-button label="complete">交易完成 {{ '(' +orderChartType.complete?orderChartType.complete:0+ ')' }}</el-radio-button>
|
||||
<el-radio-button label="toBeWrittenOff">待核销 {{ '(' +orderChartType.toBeWrittenOff?orderChartType.toBeWrittenOff:0+ ')' }}</el-radio-button>
|
||||
<el-radio-button label="refunding">退款中 {{ '(' +orderChartType.refunding?orderChartType.refunding:0+ ')' }}</el-radio-button>
|
||||
<el-radio-button label="refunded">已退款 {{ '(' +orderChartType.refunded?orderChartType.refunded:0+ ')' }}</el-radio-button>
|
||||
<el-radio-button label="deleted">已删除 {{ '(' +orderChartType.deleted?orderChartType.deleted:0+ ')' }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间选择:" class="width100">
|
||||
<el-radio-group v-model="tableFrom.dateLimit" type="button" class="mr20" size="small" @change="selectChange(tableFrom.dateLimit)">
|
||||
<el-radio-button v-for="(item,i) in fromList.fromTxt" :key="i" :label="item.val">{{ item.text }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-date-picker v-model="timeVal" value-format="yyyy-MM-dd" format="yyyy-MM-dd" size="small" type="daterange" placement="bottom-end" placeholder="自定义时间" style="width: 220px;" @change="onchangeTime" />
|
||||
</el-form-item>
|
||||
<el-form-item label="订单号:" class="width100">
|
||||
<el-input v-model="tableFrom.orderId" placeholder="请输入订单号" class="selWidth" size="small">
|
||||
<el-button slot="append" icon="el-icon-search" size="small" @click="seachList" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<cards-data :cardLists="cardLists"></cards-data>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
class="table"
|
||||
highlight-current-row
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="expand">
|
||||
<template slot-scope="props">
|
||||
<el-form label-position="left" inline class="demo-table-expand">
|
||||
<el-form-item label="商品总价:">
|
||||
<span>{{ props.row.totalPrice }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="推广人:">
|
||||
<span>{{ props.row.spreadInfo.id + ' / ' + props.row.spreadInfo.name }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户备注:">
|
||||
<span>{{ props.row.mark }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="商家备注:">
|
||||
<span>{{ props.row.remark }}</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55"
|
||||
/>
|
||||
<el-table-column
|
||||
label="订单号"
|
||||
min-width="170"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span style="display: block;" v-text="scope.row.orderId" />
|
||||
<span v-show="scope.row.isDel" style="color: #ED4014;display: block;">用户已删除</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--<el-table-column-->
|
||||
<!--prop="id"-->
|
||||
<!--label="订单类型"-->
|
||||
<!--min-width="150"-->
|
||||
<!--/>-->
|
||||
<el-table-column
|
||||
prop="realName"
|
||||
label="用户信息"
|
||||
min-width="130"
|
||||
/>
|
||||
<el-table-column
|
||||
label="商品信息"
|
||||
min-width="330"
|
||||
>
|
||||
<!--<template slot-scope="scope">-->
|
||||
<!--<div v-if="scope.row.productList.length">-->
|
||||
<!--<div v-for="(val, i ) in scope.row.productList" :key="i" class="tabBox acea-row row-middle">-->
|
||||
<!--<div class="demo-image__preview">-->
|
||||
<!--<el-image-->
|
||||
<!--:src="val.info.productInfo.image"-->
|
||||
<!--:preview-src-list="imgList"-->
|
||||
<!--/>-->
|
||||
<!--</div>-->
|
||||
<!--<!–<span class="tabBox_tit">{{ val.info.productInfo.store_name + ' | ' }}{{ val.info.productInfo.attrInfo.suk ? val.info.productInfo.attrInfo.suk:'-' }}</span>–>-->
|
||||
<!--<!–<span class="tabBox_pice">{{ '¥'+ val.info.productInfo.attrInfo.price ? val.info.productInfo.attrInfo.price:'-' + ' x '+ val.info.cart_num }}</span>–>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</template>-->
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="payPrice"
|
||||
label="实际支付"
|
||||
min-width="80"
|
||||
/>
|
||||
<el-table-column
|
||||
label="支付方式"
|
||||
min-width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.payTypeStr }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="订单状态"
|
||||
min-width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.statusStr.key === 'refunding'" class="refunding">
|
||||
<b style="color: #f124c7;">申请退款</b>
|
||||
<span>退款原因:{{scope.row.refundReasonWap}}</span>
|
||||
<span>备注说明:{{scope.row.refundReasonWapExplain}}</span>
|
||||
<span>退款时间:{{scope.row.refundReasonTime}}</span>
|
||||
<span>
|
||||
退款凭证:
|
||||
<img :src="scope.row.refundReasonWapImg" v-if="scope.row.refundReasonWapImg">
|
||||
<span v-else style="display: inline-block">无</span>
|
||||
</span>
|
||||
</div>
|
||||
<span v-else>{{ scope.row.statusStr.value }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
label="下单时间"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column label="操作" min-width="150" fixed="right" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="scope.row.paid === false" type="text" size="small" @click="edit(scope.row)" class="mr10">编辑</el-button>
|
||||
<el-button v-if="scope.row.statusStr.key === 'notShipped'" type="text" size="small" class="mr10" @click="sendOrder(scope.row)">发送货</el-button>
|
||||
<el-dropdown trigger="click">
|
||||
<span class="el-dropdown-link">
|
||||
更多<i class="el-icon-arrow-down el-icon--right" />
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native="onOrderDetails(scope.row.id)">订单详情</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="onOrderLog(scope.row.id)">订单记录</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="onOrderMark(scope.row)">订单备注</el-dropdown-item>
|
||||
<el-dropdown-item v-show="scope.row.statusStr.key === 'refunding'" @click.native="onOrderRefuse(scope.row)">拒绝退款</el-dropdown-item>
|
||||
<el-dropdown-item v-show="scope.row.statusStr.key === 'refunding'" @click.native="onOrderRefund(scope.row)">立即退款</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="handleDelete(scope.row, scope.$index)">删除订单</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!--编辑-->
|
||||
<el-dialog
|
||||
title="编辑订单"
|
||||
:visible.sync="dialogVisible"
|
||||
width="500px"
|
||||
:before-close="handleClose">
|
||||
<zb-parser
|
||||
:form-id="104"
|
||||
:is-create="isCreate"
|
||||
:edit-data="editData"
|
||||
@submit="handlerSubmit"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<!--记录-->
|
||||
<el-dialog
|
||||
title="操作记录"
|
||||
:visible.sync="dialogVisibleJI"
|
||||
width="700px"
|
||||
>
|
||||
<el-table
|
||||
v-loading="LogLoading"
|
||||
border
|
||||
:data="tableDataLog.data"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column
|
||||
prop="oid"
|
||||
align="center"
|
||||
label="ID"
|
||||
min-width="80"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="changeMessage"
|
||||
label="操作记录"
|
||||
align="center"
|
||||
min-width="280"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="createTime"
|
||||
label="操作时间"
|
||||
align="center"
|
||||
min-width="280"
|
||||
/>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[10, 20, 30, 40]"
|
||||
:page-size="tableFromLog.limit"
|
||||
:current-page="tableFromLog.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableDataLog.total"
|
||||
@size-change="handleSizeChangeLog"
|
||||
@current-change="pageChangeLog"
|
||||
/>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!--详情-->
|
||||
<details-from ref="orderDetail" :orderId="orderId"/>
|
||||
|
||||
<!-- 发送货 -->
|
||||
<order-send ref="send" :orderId="orderId" @submitFail="getList"></order-send>
|
||||
|
||||
<!--拒绝退款-->
|
||||
<el-dialog
|
||||
title="拒绝退款原因"
|
||||
:visible.sync="RefuseVisible"
|
||||
width="500px"
|
||||
:before-close="RefusehandleClose">
|
||||
<zb-parser
|
||||
:form-id="106"
|
||||
:is-create="1"
|
||||
:edit-data="RefuseData"
|
||||
@submit="RefusehandlerSubmit"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<!--立即拒绝-->
|
||||
<el-dialog
|
||||
title="退款处理"
|
||||
:visible.sync="refundVisible"
|
||||
width="500px"
|
||||
:before-close="refundhandleClose">
|
||||
<zb-parser
|
||||
:form-id="107"
|
||||
:is-create="1"
|
||||
:edit-data="refundData"
|
||||
@submit="refundhandlerSubmit"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { orderListApi, orderUpdateApi, orderLogApi, orderMarkApi, orderDeleteApi, orderRefuseApi, orderRefundApi } from '@/api/order'
|
||||
import cardsData from '@/components/cards/index'
|
||||
import zbParser from '@/components/FormGenerator/components/parser/ZBParser'
|
||||
import detailsFrom from './orderDetail'
|
||||
import orderSend from './orderSend'
|
||||
export default {
|
||||
name: 'orderlistDetails',
|
||||
components: {
|
||||
cardsData,
|
||||
zbParser,
|
||||
detailsFrom,
|
||||
orderSend
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
RefuseVisible: false,
|
||||
RefuseData:{},
|
||||
orderId: 0,
|
||||
refundVisible: false,
|
||||
refundData: {},
|
||||
dialogVisibleJI: false,
|
||||
tableDataLog: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
tableFromLog: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
oid: null
|
||||
},
|
||||
LogLoading: false,
|
||||
isCreate: 1,
|
||||
editData: null,
|
||||
dialogVisible: false,
|
||||
imgList: [],
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
listLoading: true,
|
||||
tableFrom: {
|
||||
status: 'all',
|
||||
dateLimit: '',
|
||||
orderId: '',
|
||||
page: 1,
|
||||
limit: 20
|
||||
},
|
||||
orderChartType: {},
|
||||
timeVal: [],
|
||||
fromList: {
|
||||
title: '选择时间',
|
||||
custom: true,
|
||||
fromTxt: [
|
||||
{ text: '全部', val: '' },
|
||||
{ text: '今天', val: 'today' },
|
||||
{ text: '昨天', val: 'yesterday' },
|
||||
{ text: '最近7天', val: 'lately7' },
|
||||
{ text: '最近30天', val: 'lately30' },
|
||||
{ text: '本月', val: 'month' },
|
||||
{ text: '本年', val: 'year' }
|
||||
]
|
||||
},
|
||||
selectionList: [],
|
||||
ids: '',
|
||||
orderids: '',
|
||||
cardLists: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
seachList() {
|
||||
this.tableFrom.page = 1
|
||||
this.getList()
|
||||
},
|
||||
// 拒绝退款
|
||||
RefusehandleClose() {
|
||||
this.RefuseVisible = false
|
||||
},
|
||||
onOrderRefuse(row) {
|
||||
this.orderids = row.id
|
||||
this.RefuseData = {
|
||||
orderId: row.orderId,
|
||||
reason: ''
|
||||
}
|
||||
this.RefuseVisible = true
|
||||
},
|
||||
RefusehandlerSubmit(formValue) {
|
||||
orderRefuseApi({ id: this.orderids, reason: formValue.reason}).then(data => {
|
||||
this.$message.success('操作成功')
|
||||
this.RefuseVisible = false
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
// 立即退款
|
||||
refundhandleClose() {
|
||||
this.refundVisible = false
|
||||
},
|
||||
onOrderRefund(row) {
|
||||
this.refundData = {
|
||||
orderId: row.orderId,
|
||||
amount: row.payPrice,
|
||||
type: ''
|
||||
}
|
||||
this.orderids = row.id
|
||||
this.refundVisible = true
|
||||
},
|
||||
refundhandlerSubmit(formValue) {
|
||||
orderRefundApi({ amount: formValue.amount, orderId: this.orderids, type: formValue.type}).then(data => {
|
||||
this.$message.success('操作成功')
|
||||
this.refundVisible = false
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
// 发送
|
||||
sendOrder(row) {
|
||||
this.$refs.send.modals = true;
|
||||
this.$refs.send.getList();
|
||||
this.orderId = row.id;
|
||||
},
|
||||
// 订单删除
|
||||
handleDelete(row, idx) {
|
||||
if (row.isDel) {
|
||||
this.$modalSure().then(() => {
|
||||
orderDeleteApi({ id: row.id }).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.tableData.data.splice(idx, 1)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.$confirm('您选择的的订单存在用户未删除的订单,无法删除用户未删除的订单!', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
},
|
||||
// 详情
|
||||
onOrderDetails(id) {
|
||||
this.orderId = id
|
||||
this.$refs.orderDetail.getDetail(id)
|
||||
this.$refs.orderDetail.dialogVisible = true
|
||||
},
|
||||
// 订单记录
|
||||
onOrderLog(id) {
|
||||
this.dialogVisibleJI = true
|
||||
this.LogLoading = true
|
||||
this.tableFromLog.oid = id
|
||||
orderLogApi( this.tableFromLog ).then(res => {
|
||||
this.tableDataLog.data = res.list
|
||||
this.tableDataLog.total = res.total
|
||||
this.LogLoading = false
|
||||
}).catch(() => {
|
||||
this.LogLoading = false
|
||||
})
|
||||
},
|
||||
pageChangeLog(page) {
|
||||
this.tableFromLog.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChangeLog(val) {
|
||||
this.tableFromLog.limit = val
|
||||
this.getList()
|
||||
},
|
||||
handleClose() {
|
||||
this.dialogVisible = false
|
||||
},
|
||||
// 备注
|
||||
onOrderMark(row) {
|
||||
this.$prompt('订单备注', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputErrorMessage: '请输入订单备注',
|
||||
inputType: 'textarea',
|
||||
inputValue: row.mark,
|
||||
inputPlaceholder: '请输入订单备注',
|
||||
inputValidator: (value) => { if(!value) return '输入不能为空'}
|
||||
}).then(({value}) => {
|
||||
orderMarkApi({ mark : value, id: row.id}).then(() => {
|
||||
this.$message.success('操作成功')
|
||||
this.getList();
|
||||
})
|
||||
}).catch(() => {
|
||||
this.$message.info('取消输入')
|
||||
})
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
this.selectionList = val
|
||||
const data = []
|
||||
this.selectionList.map((item) => {
|
||||
data.push(item.id)
|
||||
})
|
||||
this.ids = data.join(',')
|
||||
},
|
||||
// 选择时间
|
||||
selectChange (tab) {
|
||||
this.timeVal = [];
|
||||
this.tableFrom.page = 1
|
||||
this.getList();
|
||||
},
|
||||
// 具体日期
|
||||
onchangeTime (e) {
|
||||
this.timeVal = e;
|
||||
this.tableFrom.dateLimit = e ? this.timeVal.join(',') : ''
|
||||
this.tableFrom.page = 1
|
||||
this.getList();
|
||||
},
|
||||
// 编辑
|
||||
edit(row) {
|
||||
this.dialogVisible = true
|
||||
this.orderId = row.id
|
||||
this.editData = {
|
||||
orderId: row.orderId,
|
||||
totalPrice: row.totalPrice,
|
||||
totalPostage: row.totalPostage,
|
||||
payPrice: row.payPrice,
|
||||
payPostage: row.payPostage,
|
||||
gainIntegral: row.gainIntegral,
|
||||
}
|
||||
},
|
||||
handlerSubmit(formValue) {
|
||||
orderUpdateApi(formValue, {id: this.orderId}).then(data => {
|
||||
this.$message.success('编辑数据成功')
|
||||
this.dialogVisible = false
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
// 列表
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
orderListApi(this.tableFrom).then(res => {
|
||||
this.tableData.data = res.list.list || []
|
||||
this.tableData.total = res.list.total
|
||||
this.orderChartType = res.status
|
||||
this.tableData.data.map((item) => {
|
||||
item.productList.map((i) => {
|
||||
this.imgList.push(i.info.productInfo.image)
|
||||
})
|
||||
})
|
||||
const stat = res.top
|
||||
this.cardLists = [
|
||||
{ name: '订单数量', count: stat.count },
|
||||
{ name: '订单金额', count: stat.amount },
|
||||
{ name: '微信支付金额', count: stat.weChatAmount },
|
||||
{ name: '余额支付金额', count: stat.yueAmount }
|
||||
]
|
||||
this.listLoading = false
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
pageChange(page) {
|
||||
this.tableFrom.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val
|
||||
this.getList()
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.refunding{
|
||||
span{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.selWidth{
|
||||
width: 300px;
|
||||
}
|
||||
.el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: #409EFF;
|
||||
font-size: 12px;
|
||||
}
|
||||
.el-icon-arrow-down {
|
||||
font-size: 12px;
|
||||
}
|
||||
.tabBox_tit {
|
||||
width: 60%;
|
||||
font-size: 12px !important;
|
||||
margin: 0 2px 0 10px;
|
||||
letter-spacing: 1px;
|
||||
padding: 5px 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
113
admin/src/views/order/orderDetail.vue
Normal file
113
admin/src/views/order/orderDetail.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="订单信息"
|
||||
:visible.sync="dialogVisible"
|
||||
width="700px"
|
||||
v-if="orderDatalist"
|
||||
>
|
||||
<div class="description" v-loading="loading">
|
||||
<div class="title">用户信息</div>
|
||||
<div class="acea-row">
|
||||
<div class="description-term">用户昵称:{{orderDatalist.realName}}</div>
|
||||
<div class="description-term">收货人:{{orderDatalist.realName}}</div>
|
||||
<div class="description-term">联系电话:{{orderDatalist.userPhone}}</div>
|
||||
<div class="description-term">收货地址:{{orderDatalist.userAddress}}</div>
|
||||
</div>
|
||||
<el-divider></el-divider>
|
||||
<div class="title">收货信息</div>
|
||||
<div class="acea-row">
|
||||
<div class="description-term">订单编号:{{orderDatalist.orderId}}</div>
|
||||
<div class="description-term">订单状态:{{orderDatalist.status | orderStatusFilter}}</div>
|
||||
<div class="description-term">商品总数:{{orderDatalist.totalNum}}</div>
|
||||
<div class="description-term">商品总价:{{orderDatalist.totalPrice}}</div>
|
||||
<div class="description-term">交付邮费:{{orderDatalist.payPostage}}</div>
|
||||
<div class="description-term">优惠券金额:{{orderDatalist.couponPrice}}</div>
|
||||
<div class="description-term">实际支付:{{orderDatalist.payPrice}}</div>
|
||||
<div class="description-term" v-if="orderDatalist.refundPrice">退款金额:{{orderDatalist.refundPrice}}</div>
|
||||
<div class="description-term" v-if="orderDatalist.useIntegral">使用积分:{{orderDatalist.useIntegral}}</div>
|
||||
<div class="description-term" v-if="orderDatalist.backIntegral">退回积分:{{orderDatalist.backIntegral}}</div>
|
||||
<div class="description-term">创建时间:{{orderDatalist.createTime}}</div>
|
||||
<div class="description-term">支付方式:{{orderDatalist.payTypeStr}}</div>
|
||||
<div class="description-term">推广人:{{orderDatalist.spreadInfo.id + ' / ' +orderDatalist.spreadInfo.name}}</div>
|
||||
<div class="description-term" v-if="orderDatalist.shippingType === 2 && orderDatalist.statusStr.key === 'notShipped'">门店名称:{{orderDatalist.storeName}}</div>
|
||||
<div class="description-term" v-if="orderDatalist.shippingType === 2 && orderDatalist.statusStr.key === 'notShipped'">核销码:{{orderDatalist.user_phone}}</div>
|
||||
<div class="description-term">商家备注:{{orderDatalist.remark}}</div>
|
||||
</div>
|
||||
<template v-if="orderDatalist.deliveryType === 'express'">
|
||||
<el-divider></el-divider>
|
||||
<div class="title">物流信息</div>
|
||||
<div class="acea-row">
|
||||
<div class="description-term">快递公司:{{orderDatalist.deliveryName}}</div>
|
||||
<div class="description-term">快递单号:{{orderDatalist.deliveryId}}</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="orderDatalist.deliveryType === 'send'">
|
||||
<el-divider></el-divider>
|
||||
<div class="title">配送信息</div>
|
||||
<div class="acea-row">
|
||||
<div class="description-term">送货人姓名:{{orderDatalist.deliveryName}}</div>
|
||||
<div class="description-term">送货人电话:{{orderDatalist.deliveryId}}</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="orderDatalist.mark">
|
||||
<el-divider></el-divider>
|
||||
<div class="title">用户备注</div>
|
||||
<div class="acea-row">
|
||||
<div class="description-term">{{orderDatalist.mark}}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { orderDetailApi } from '@/api/order'
|
||||
export default {
|
||||
name: 'OrderDetail',
|
||||
props: {
|
||||
orderId: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
orderDatalist: null,
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
getDetail(id) {
|
||||
this.loading = true
|
||||
orderDetailApi({id: id}).then(res => {
|
||||
this.orderDatalist = res
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.title{
|
||||
margin-bottom: 16px;
|
||||
color: #17233d;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
.description{
|
||||
&-term {
|
||||
display: table-cell;
|
||||
padding-bottom: 10px;
|
||||
line-height: 20px;
|
||||
width: 50%;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
103
admin/src/views/order/orderSend.vue
Normal file
103
admin/src/views/order/orderSend.vue
Normal file
@@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<el-dialog :visible.sync="modals" title="订单记录" class="order_box">
|
||||
<el-form ref="formItem" :model="formItem" label-width="110px" @submit.native.prevent>
|
||||
<el-form-item label="选择类型:">
|
||||
<el-radio-group v-model="formItem.type" @change="changeRadio(formItem.type)">
|
||||
<el-radio label="1">发货</el-radio>
|
||||
<el-radio label="2">送货</el-radio>
|
||||
<el-radio label="3">虚拟</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<div v-if="formItem.type==='1'">
|
||||
<el-form-item label="快递公司:" prop="expressId"
|
||||
:rules="[{ required: true, message: '请选择快递公司', trigger: 'change' }]">
|
||||
<el-select v-model="formItem.expressId" style="width:80%;">
|
||||
<el-option v-for="(item,i) in express" :value="item.id" :key="i">{{ item.name }}</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="快递单号:" prop="expressCode"
|
||||
:rules="[{ required: true, message: '请输入快递单号', trigger: 'blur' }]">
|
||||
<el-input v-model="formItem.expressCode" placeholder="请输入快递单号" style="width:80%;"></el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="formItem.type==='2'">
|
||||
<el-form-item label="送货人姓名:" prop="expressId"
|
||||
:rules="[{ required: true, message: '请输入送货人姓名', trigger: 'blur' }]">
|
||||
<el-input v-model="formItem.expressId" placeholder="请输入送货人姓名" style="width:80%;"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="送货人电话:" prop="expressCode"
|
||||
:rules="[{ required: true, message: '请输入送货人电话', trigger: 'blur' }]">
|
||||
<el-input v-model="formItem.expressCode" placeholder="请输入送货人电话" style="width:80%;"></el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button size="mini" type="primary" @click="putSend('formItem')">提交</el-button>
|
||||
<el-button size="mini" @click="cancel('formItem')">取消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { orderSendApi } from '@/api/order'
|
||||
import { expressList } from '@/api/logistics';
|
||||
export default {
|
||||
name: 'orderSend',
|
||||
props: {
|
||||
orderId: Number
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
formItem: {
|
||||
type: '1',
|
||||
expressId: '',
|
||||
expressCode: '',
|
||||
id: ''
|
||||
},
|
||||
modals: false,
|
||||
express: []
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
methods: {
|
||||
changeRadio (o) {
|
||||
if( o === '3'){
|
||||
this.formItem.expressId = ''
|
||||
this.formItem.expressCode = ''
|
||||
}
|
||||
},
|
||||
// 物流公司列表
|
||||
getList () {
|
||||
expressList({ page: 1, limit: 999}).then(async res => {
|
||||
this.express = res.list
|
||||
})
|
||||
},
|
||||
// 提交
|
||||
putSend(name) {
|
||||
this.formItem.id = this.orderId
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
orderSendApi(this.formItem).then(async => {
|
||||
this.$message.success('发送货成功');
|
||||
this.modals = false;
|
||||
this.$refs[name].resetFields();
|
||||
this.$emit('submitFail')
|
||||
})
|
||||
} else {
|
||||
this.$message.error('请填写信息');
|
||||
}
|
||||
})
|
||||
},
|
||||
cancel (name) {
|
||||
this.modals = false;
|
||||
this.$refs[name].resetFields();
|
||||
this.formItem.type = '1';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
12
admin/src/views/redirect/index.vue
Normal file
12
admin/src/views/redirect/index.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<script>
|
||||
export default {
|
||||
created() {
|
||||
const { params, query } = this.$route
|
||||
const { path } = params
|
||||
this.$router.replace({ path: '/' + path, query })
|
||||
},
|
||||
render: function(h) {
|
||||
return h() // avoid warning message
|
||||
}
|
||||
}
|
||||
</script>
|
||||
13
admin/src/views/sms/index.vue
Normal file
13
admin/src/views/sms/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
174
admin/src/views/sms/smsConfig/components/loginFrom.vue
Normal file
174
admin/src/views/sms/smsConfig/components/loginFrom.vue
Normal file
@@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<el-row type="flex">
|
||||
<el-col :span="24">
|
||||
<el-form ref="formInline" size="small" :model="formInline" :rules="ruleInline" class="login-form"
|
||||
autocomplete="on" label-position="left">
|
||||
<div class="title-container">
|
||||
<h3 class="title">短信账户登录</h3>
|
||||
</div>
|
||||
<el-form-item prop="account">
|
||||
<el-input
|
||||
ref="account"
|
||||
v-model="formInline.account"
|
||||
placeholder="用户名"
|
||||
prefix-icon="el-icon-user"
|
||||
name="username"
|
||||
type="text"
|
||||
tabindex="1"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="token">
|
||||
<el-input
|
||||
:key="passwordType"
|
||||
ref="token"
|
||||
v-model="formInline.token"
|
||||
:type="passwordType"
|
||||
placeholder="密码"
|
||||
name="token"
|
||||
tabindex="2"
|
||||
auto-complete="off"
|
||||
prefix-icon="el-icon-lock"
|
||||
/>
|
||||
<span class="show-pwd" @click="showPwd">
|
||||
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"/>
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-button size="mini" :loading="loading" type="primary" style="width:100%;margin-bottom:20px;"
|
||||
@click="handleSubmit('formInline')">登录
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" style="width: 100%;" @click="changeReg">注册账户</el-button>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { configApi } from '@/api/sms'
|
||||
export default {
|
||||
name: 'Login',
|
||||
data() {
|
||||
return {
|
||||
formInline: {
|
||||
account: '',
|
||||
token: ''
|
||||
},
|
||||
ruleInline: {
|
||||
account: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' }
|
||||
],
|
||||
token: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
passwordType: 'password',
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
var _this = this
|
||||
document.onkeydown = function(e) {
|
||||
const key = window.event.keyCode
|
||||
if (key === 13) {
|
||||
_this.handleSubmit('formInline')
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showPwd() {
|
||||
if (this.passwordType === 'password') {
|
||||
this.passwordType = ''
|
||||
} else {
|
||||
this.passwordType = 'password'
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.token.focus()
|
||||
})
|
||||
},
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
configApi(this.formInline).then(async res => {
|
||||
this.$message.success('登录成功!')
|
||||
this.$store.dispatch('user/isLogin')
|
||||
this.$emit('on-Login')
|
||||
}).catch(res => {
|
||||
this.$message.error(res.message)
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
// 休息密码
|
||||
changePassword() {
|
||||
this.$emit('on-change')
|
||||
},
|
||||
changeReg() {
|
||||
this.$emit('on-changes')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.title{
|
||||
text-align: center;
|
||||
}
|
||||
.captcha{
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
$bg: #2d3a4b;
|
||||
$dark_gray: #889aa4;
|
||||
$light_gray: #eee;
|
||||
.imgs{
|
||||
img{
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
.login-form {
|
||||
flex: 1;
|
||||
padding: 32px 0;
|
||||
text-align: center;
|
||||
width: 384px;
|
||||
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;
|
||||
}
|
||||
.show-pwd {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 7px;
|
||||
font-size: 16px;
|
||||
color: $dark_gray;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
/deep/.svg-icon {
|
||||
vertical-align: 0.3em;
|
||||
}
|
||||
}
|
||||
.thirdparty-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 6px;
|
||||
}
|
||||
</style>
|
||||
254
admin/src/views/sms/smsConfig/components/register.vue
Normal file
254
admin/src/views/sms/smsConfig/components/register.vue
Normal file
@@ -0,0 +1,254 @@
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<el-form ref="formInline" size="small" :model="formInline" :rules="ruleInline" class="login-form" autocomplete="on" label-position="left">
|
||||
<div class="title-container">
|
||||
<h3 class="title">短信账户注册</h3>
|
||||
</div>
|
||||
<el-form-item prop="account">
|
||||
<el-input
|
||||
ref="account"
|
||||
v-model="formInline.account"
|
||||
placeholder="请输入短信平台账号"
|
||||
prefix-icon="el-icon-user"
|
||||
name="username"
|
||||
type="text"
|
||||
tabindex="1"
|
||||
auto-complete="off"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
:key="passwordType"
|
||||
ref="password"
|
||||
v-model="formInline.password"
|
||||
:type="passwordType"
|
||||
placeholder="请输入短信平台密码/token"
|
||||
name="password"
|
||||
tabindex="2"
|
||||
auto-complete="off"
|
||||
prefix-icon="el-icon-lock"
|
||||
/>
|
||||
<span class="show-pwd" @click="showPwd">
|
||||
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item prop="domain">
|
||||
<el-input
|
||||
ref="password"
|
||||
v-model="formInline.domain"
|
||||
placeholder="请输入网址域名"
|
||||
name="password"
|
||||
prefix-icon="el-icon-position"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="phone">
|
||||
<el-input
|
||||
ref="password"
|
||||
v-model="formInline.phone"
|
||||
placeholder="请输入您的手机号"
|
||||
prefix-icon="el-icon-phone-outline"
|
||||
name="password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="sign">
|
||||
<el-input
|
||||
ref="password"
|
||||
v-model="formInline.sign"
|
||||
placeholder="请输入短信签名,例如:CRMEB"
|
||||
name="password"
|
||||
prefix-icon="el-icon-price-tag"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="code" class="captcha">
|
||||
<div class="acea-row" style="flex-wrap: nowrap;">
|
||||
<el-input
|
||||
ref="username"
|
||||
v-model="formInline.code"
|
||||
placeholder="验证码"
|
||||
name="username"
|
||||
type="text"
|
||||
tabindex="1"
|
||||
autocomplete="off"
|
||||
prefix-icon="el-icon-message"
|
||||
style="width: 90%"
|
||||
/>
|
||||
<el-button size="mini" :disabled=!this.canClick @click="cutDown">{{cutNUm}}</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-button size="mini" :loading="loading" type="primary" style="width:100%;margin-bottom:20px;" @click="handleSubmit('formInline')">注册</el-button>
|
||||
<el-button size="mini" type="primary" style="width:100%;margin-bottom:20px;" @click="changelogo">立即登录</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { captchaApi, registerApi } from '@/api/sms'
|
||||
export default {
|
||||
name: 'Register',
|
||||
data() {
|
||||
const validatePhone = (rule, value, callback) => {
|
||||
if (!value) {
|
||||
return callback(new Error('请填写手机号'))
|
||||
} else if (!/^1[3456789]\d{9}$/.test(value)) {
|
||||
callback(new Error('手机号格式不正确!'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
loading: false,
|
||||
passwordType: 'password',
|
||||
captchatImg: '',
|
||||
cutNUm: '获取验证码',
|
||||
canClick: true,
|
||||
formInline: {
|
||||
account: '',
|
||||
code: '',
|
||||
domain: '',
|
||||
phone: '',
|
||||
sign: '',
|
||||
password: ''
|
||||
},
|
||||
ruleInline: {
|
||||
account: [
|
||||
{ required: true, message: '请输入短信平台账号', trigger: 'blur' }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入短信平台密码/token', trigger: 'blur' }
|
||||
],
|
||||
domain: [
|
||||
{ required: true, message: '请输入网址域名', trigger: 'blur' }
|
||||
],
|
||||
phone: [
|
||||
{ required: true, validator: validatePhone, trigger: 'blur' }
|
||||
],
|
||||
sign: [
|
||||
{ required: true, message: '请输入短信签名', trigger: 'blur' }
|
||||
],
|
||||
code: [
|
||||
{ required: true, message: '请输入验证码', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showPwd() {
|
||||
if (this.passwordType === 'password') {
|
||||
this.passwordType = ''
|
||||
} else {
|
||||
this.passwordType = 'password'
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.password.focus()
|
||||
})
|
||||
},
|
||||
// 短信验证码
|
||||
cutDown() {
|
||||
if (this.formInline.phone) {
|
||||
if (!this.canClick) return
|
||||
this.canClick = false
|
||||
this.cutNUm = 60
|
||||
captchaApi(this.formInline.phone).then(async res => {
|
||||
this.$message.success(res.data.message)
|
||||
})
|
||||
const time = setInterval(() => {
|
||||
this.cutNUm--
|
||||
if (this.cutNUm === 0) {
|
||||
this.cutNUm = '获取验证码'
|
||||
this.canClick = true
|
||||
clearInterval(time)
|
||||
}
|
||||
}, 1000)
|
||||
} else {
|
||||
this.$message.warning('请填写手机号!')
|
||||
}
|
||||
},
|
||||
// 注册
|
||||
handleSubmit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
registerApi(this.formInline).then(async res => {
|
||||
console.log(res)
|
||||
this.$message.success('注册成功')
|
||||
setTimeout(() => {
|
||||
this.changelogo()
|
||||
}, 1000)
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
// 立即登录
|
||||
changelogo() {
|
||||
this.$emit('on-change')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.el-button+.el-button{
|
||||
margin-left: 0px !important;
|
||||
}
|
||||
.title{
|
||||
text-align: center;
|
||||
}
|
||||
.captcha{
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
/deep/.el-form-item__content{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
$bg: #2d3a4b;
|
||||
$dark_gray: #889aa4;
|
||||
$light_gray: #eee;
|
||||
.imgs{
|
||||
img{
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
.login-form {
|
||||
flex: 1;
|
||||
padding: 32px 0;
|
||||
text-align: center;
|
||||
width: 384px;
|
||||
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;
|
||||
}
|
||||
.show-pwd {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 7px;
|
||||
font-size: 16px;
|
||||
color: $dark_gray;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
/deep/.svg-icon {
|
||||
vertical-align: 0.3em;
|
||||
}
|
||||
}
|
||||
.thirdparty-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 6px;
|
||||
}
|
||||
</style>
|
||||
129
admin/src/views/sms/smsConfig/components/tableList.vue
Normal file
129
admin/src/views/sms/smsConfig/components/tableList.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div class="filter-container mb20">
|
||||
<div class="demo-input-suffix">
|
||||
<span class="seachTiele">短信状态:</span>
|
||||
<el-radio-group v-model="tableFrom.resultCode" size="small" @change="getList">
|
||||
<el-radio-button label="">全部</el-radio-button>
|
||||
<el-radio-button label="100">成功</el-radio-button>
|
||||
<el-radio-button label="130">失败</el-radio-button>
|
||||
<el-radio-button label="131">空号</el-radio-button>
|
||||
<el-radio-button label="132">停机</el-radio-button>
|
||||
<el-radio-button label="133">关机</el-radio-button>
|
||||
<el-radio-button label="134">无状态</el-radio-button>
|
||||
<el-radio-button label="400">黑名单</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
min-width="50"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="phone"
|
||||
label="手机号"
|
||||
min-width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="content"
|
||||
label="模板内容"
|
||||
min-width="450"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="template"
|
||||
label="模板ID"
|
||||
min-width="100"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="memo"
|
||||
label="备注"
|
||||
min-width="200"
|
||||
/>
|
||||
<el-table-column
|
||||
label="发送时间"
|
||||
min-width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.creatTime}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="resultcode"
|
||||
label="状态码"
|
||||
min-width="100"
|
||||
/>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { smsLstApi } from '@/api/sms'
|
||||
import Template from "../../../appSetting/wxAccount/wxTemplate/index";
|
||||
export default {
|
||||
name: 'TableList',
|
||||
components: {Template},
|
||||
data() {
|
||||
return {
|
||||
listLoading: false,
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
tableFrom: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
resultCode: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 列表
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
smsLstApi(this.tableFrom).then(res => {
|
||||
this.tableData.data = res.list
|
||||
this.tableData.total = res.total
|
||||
this.listLoading = false
|
||||
}).catch(res => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
pageChange(page) {
|
||||
this.tableFrom.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
190
admin/src/views/sms/smsConfig/index.vue
Normal file
190
admin/src/views/sms/smsConfig/index.vue
Normal file
@@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card v-if="isShowList" v-loading="fullscreenLoading" class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="content acea-row row-middle">
|
||||
<div class="demo-basic--circle acea-row row-middle">
|
||||
<el-avatar :size="50" :src="circleUrl" class="mr20" />
|
||||
<div class="dashboard-workplace-header-tip">
|
||||
<div class="dashboard-workplace-header-tip-title">{{ smsAccount }},祝您每一天开心!</div>
|
||||
<div class="dashboard-workplace-header-tip-desc">
|
||||
<span class="mr10">修改密码</span>
|
||||
<span @click="signOut">退出登录</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dashboard-workplace-header-extra">
|
||||
<el-row type="flex" justify="center" align="middle" :gutter="12">
|
||||
<el-col :span="8">
|
||||
<span class="pfont acea-row row-middle">
|
||||
<el-avatar icon="el-icon-user-solid" size="small" class="mr10" />
|
||||
<span>剩余条数</span>
|
||||
</span>
|
||||
<span class="rR" v-text="numbers" />
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<span class="pfont acea-row row-middle">
|
||||
<el-avatar icon="el-icon-user-solid" size="small" class="mr10" />
|
||||
<span>已发送</span>
|
||||
</span>
|
||||
<span class="rR" v-text="sendTotal" />
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<span class="pfont acea-row row-middle">
|
||||
<el-avatar icon="el-icon-user-solid" size="small" class="mr10" />
|
||||
<span>总条数</span>
|
||||
</span>
|
||||
<span class="rR" v-text="amount" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<table-list v-if="isShowList" />
|
||||
<login-from v-if="isShowLogn" @on-changes="onChangeReg" @on-Login="onLogin" />
|
||||
<register-from v-if="isShowReg" @on-change="logoup" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import tableList from './components/tableList'
|
||||
import loginFrom from './components/loginFrom'
|
||||
import registerFrom from './components/register'
|
||||
import { logoutApi, smsNumberApi, smsInfoApi } from '@/api/sms'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'SmsConfig',
|
||||
components: { tableList, loginFrom, registerFrom },
|
||||
data() {
|
||||
return {
|
||||
fullscreenLoading: false,
|
||||
smsAccount: '',
|
||||
circleUrl: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
||||
spinShow: false,
|
||||
isShowLogn: false,
|
||||
isShow: false,
|
||||
isShowReg: false,
|
||||
isShowList: false,
|
||||
amount: 0,
|
||||
numbers: 0,
|
||||
sendTotal: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'isLogin'
|
||||
])
|
||||
},
|
||||
mounted() {
|
||||
this.onIsLogin()
|
||||
// if (!this.isLogin) {
|
||||
// this.onIsLogin()
|
||||
// } else {
|
||||
// this.isShowList = true
|
||||
// }
|
||||
},
|
||||
methods: {
|
||||
// 剩余条数
|
||||
getNumber() {
|
||||
smsInfoApi().then(async res => {
|
||||
const data = res
|
||||
this.numbers = data.number
|
||||
this.sendTotal = data.send_total
|
||||
this.amount = data.number + data.send_total
|
||||
this.smsAccount = data.account
|
||||
})
|
||||
},
|
||||
// 登录跳转
|
||||
onLogin() {
|
||||
const url = this.$route.query.url
|
||||
if (url) {
|
||||
this.$router.replace(url)
|
||||
} else {
|
||||
this.isShowLogn = false
|
||||
this.isShow = false
|
||||
this.isShowReg = false
|
||||
this.isShowList = true
|
||||
}
|
||||
},
|
||||
// 查看是否登录
|
||||
onIsLogin() {
|
||||
this.fullscreenLoading = true
|
||||
this.$store.dispatch('user/isLogin').then(async res => {
|
||||
const data = res
|
||||
this.isShowLogn = !data.status
|
||||
this.isShowList = data.status
|
||||
if (data.status) {
|
||||
this.smsAccount = data.info
|
||||
}
|
||||
this.getNumber()
|
||||
this.fullscreenLoading = false
|
||||
}).catch(res => {
|
||||
this.fullscreenLoading = false
|
||||
this.isShowLogn = true
|
||||
})
|
||||
},
|
||||
// 退出登录
|
||||
signOut() {
|
||||
logoutApi().then(async res => {
|
||||
this.isShowLogn = true
|
||||
this.isShowList = false
|
||||
this.$store.dispatch('user/isLogin')
|
||||
}).catch(res => {
|
||||
this.$message.error(res.message)
|
||||
})
|
||||
},
|
||||
// 立即注册
|
||||
onChangeReg() {
|
||||
this.isShowLogn = false
|
||||
this.isShow = false
|
||||
this.isShowReg = true
|
||||
},
|
||||
// 立即登录
|
||||
logoup() {
|
||||
this.isShowLogn = true
|
||||
this.isShow = false
|
||||
this.isShowReg = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$cursor: #1890ff;
|
||||
.content{
|
||||
justify-content: space-between;
|
||||
}
|
||||
.rR{
|
||||
text-align: center;
|
||||
font-size: 22px;
|
||||
display: block;
|
||||
}
|
||||
.dashboard-workplace-header-tip {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.dashboard-workplace-header-tip-title {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.dashboard-workplace-header-tip-desc{
|
||||
/*line-height: 0 !important;*/
|
||||
display: block;
|
||||
span{
|
||||
font-size: 12px;
|
||||
color: $cursor;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
.dashboard-workplace-header-extra{
|
||||
width: auto!important;
|
||||
min-width: 400px;
|
||||
}
|
||||
.pfont{
|
||||
font-size: 12px;
|
||||
color: #808695;
|
||||
}
|
||||
</style>
|
||||
39
admin/src/views/sms/smsMessage/index.vue
Normal file
39
admin/src/views/sms/smsMessage/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<zb-parser
|
||||
:form-id="111"
|
||||
:is-create="isCreate"
|
||||
:edit-data="editData"
|
||||
@submit="handlerSubmit"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import zbParser from '@/components/FormGenerator/components/parser/ZBParser'
|
||||
import { smsSaveApi } from '@/api/sms'
|
||||
export default {
|
||||
name: "SmsMessage",
|
||||
components: { zbParser },
|
||||
data() {
|
||||
return {
|
||||
isCreate: 0,
|
||||
editData: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handlerSubmit(formValue) {
|
||||
smsSaveApi(formValue).then(data => {
|
||||
this.$message.success('新增成功')
|
||||
this.editData = {}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
256
admin/src/views/sms/smsPay/index.vue
Normal file
256
admin/src/views/sms/smsPay/index.vue
Normal file
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<el-row v-loading="fullscreenLoading" :gutter="16">
|
||||
<el-col :span="24" class="ivu-text-left mb20">
|
||||
<el-col :xs="12" :sm="6" :md="4" :lg="3" class="mr20">
|
||||
<span class="ivu-text-right ivu-block">短信账户名称:</span>
|
||||
</el-col>
|
||||
<el-col :xs="11" :sm="13" :md="19" :lg="20">
|
||||
<span>{{ account }}</span>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-col :span="24" class="ivu-text-left mb20">
|
||||
<el-col :xs="12" :sm="6" :md="4" :lg="3" class="mr20">
|
||||
<span class="ivu-text-right ivu-block">当前剩余条数:</span>
|
||||
</el-col>
|
||||
<el-col :xs="11" :sm="13" :md="19" :lg="20">
|
||||
<span>{{ numbers }}</span>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-col :span="24" class="ivu-text-left mb20">
|
||||
<el-col :xs="12" :sm="6" :md="4" :lg="3" class="mr20">
|
||||
<span class="ivu-text-right ivu-block">选择套餐:</span>
|
||||
</el-col>
|
||||
<el-col :xs="11" :sm="13" :md="19" :lg="20">
|
||||
<el-row :gutter="20">
|
||||
<el-col
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
:xxl="4"
|
||||
:xl="8"
|
||||
:lg="8"
|
||||
:md="12"
|
||||
:sm="24"
|
||||
:xs="24"
|
||||
>
|
||||
<div
|
||||
class="list-goods-list-item mb15"
|
||||
:class="{active:index === current}"
|
||||
@click="check(item,index)"
|
||||
>
|
||||
<div class="list-goods-list-item-title" :class="{active:index === current}">¥ <i>{{ item.price }}</i></div>
|
||||
<div class="list-goods-list-item-price" :class="{active:index === current}">
|
||||
<span>短信条数: {{ item.num }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-col v-if="checkList" :span="24" class="ivu-text-left mb20">
|
||||
<el-col :xs="12" :sm="6" :md="4" :lg="3" class="mr20">
|
||||
<span class="ivu-text-right ivu-block">充值条数:</span>
|
||||
</el-col>
|
||||
<el-col :xs="11" :sm="13" :md="19" :lg="20">
|
||||
<span>{{ checkList.num }}</span>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-col v-if="checkList" :span="24" class="ivu-text-left mb20">
|
||||
<el-col :xs="12" :sm="6" :md="4" :lg="3" class="mr20">
|
||||
<span class="ivu-text-right ivu-block">支付金额:</span>
|
||||
</el-col>
|
||||
<el-col :xs="11" :sm="13" :md="19" :lg="20">
|
||||
<span class="list-goods-list-item-number">¥{{ checkList.price }}</span>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-col :span="24" class="ivu-text-left mb20">
|
||||
<el-col :xs="12" :sm="6" :md="4" :lg="3" class="mr20">
|
||||
<span class="ivu-text-right ivu-block">付款方式:</span>
|
||||
</el-col>
|
||||
<el-col :xs="11" :sm="13" :md="19" :lg="20">
|
||||
<span class="list-goods-list-item-pay">微信支付<i v-if="code.invalid">{{ ' ( 支付码过期时间:' + code.invalid + ' )' }}</i></span>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-col :xs="12" :sm="6" :md="4" :lg="3" class="mr20"> </el-col>
|
||||
<el-col :xs="11" :sm="13" :md="19" :lg="20">
|
||||
<div class="list-goods-list-item-code mr20"><img :src="code.code_url"></div>
|
||||
</el-col>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { smsNumberApi, smsPriceApi, payCodeApi, smsInfoApi } from '@/api/sms'
|
||||
import { isLogin } from '@/libs/public'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'SmsPay',
|
||||
data() {
|
||||
return {
|
||||
numbers: '',
|
||||
account: '',
|
||||
list: [],
|
||||
current: 0,
|
||||
checkList: {},
|
||||
fullscreenLoading: false,
|
||||
code: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'isLogin'
|
||||
])
|
||||
},
|
||||
mounted() {
|
||||
this.getNumber()
|
||||
this.getPrice()
|
||||
return
|
||||
|
||||
if (!this.isLogin) {
|
||||
this.$router.push('/operation/systemSms/config?url=' + this.$route.path)
|
||||
} else {
|
||||
this.getNumber()
|
||||
this.getPrice()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 查看是否登录
|
||||
onIsLogin() {
|
||||
this.fullscreenLoading = true
|
||||
this.$store.dispatch('user/isLogin').then(async res => {
|
||||
const data = res
|
||||
if (!data.status) {
|
||||
this.$message.warning('请先登录')
|
||||
this.$router.push('/operation/systemSms/config?url=' + this.$route.path)
|
||||
} else {
|
||||
this.getNumber()
|
||||
this.getPrice()
|
||||
}
|
||||
this.fullscreenLoading = false
|
||||
}).catch(res => {
|
||||
this.$router.push('/operation/systemSms/config?url=' + this.$route.path)
|
||||
this.fullscreenLoading = false
|
||||
})
|
||||
},
|
||||
// 剩余条数
|
||||
getNumber() {
|
||||
smsInfoApi().then(async res => {
|
||||
const data = res
|
||||
this.numbers = data.number
|
||||
this.account = data.account
|
||||
})
|
||||
},
|
||||
// 支付套餐
|
||||
getPrice() {
|
||||
this.fullscreenLoading = true
|
||||
smsPriceApi({ page: 1, limit: 9999}).then(async res => {
|
||||
setTimeout(() => {
|
||||
this.fullscreenLoading = false
|
||||
}, 800)
|
||||
const data = res
|
||||
this.list = data.data
|
||||
this.checkList = this.list[0]
|
||||
this.getCode(this.checkList)
|
||||
}).catch(() => {
|
||||
this.fullscreenLoading = false
|
||||
})
|
||||
},
|
||||
// 选中
|
||||
check(item, index) {
|
||||
this.fullscreenLoading = true
|
||||
this.current = index
|
||||
setTimeout(() => {
|
||||
this.getCode(item)
|
||||
this.checkList = item
|
||||
this.fullscreenLoading = false
|
||||
}, 800)
|
||||
},
|
||||
// 支付码
|
||||
getCode(item) {
|
||||
const data = {
|
||||
payType: 'weixin',
|
||||
mealId: item.id,
|
||||
price: item.price
|
||||
}
|
||||
payCodeApi(data).then(async res => {
|
||||
this.code = res
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.active{
|
||||
background: #0091FF;
|
||||
box-shadow:0px 6px 20px 0px rgba(0, 145, 255, 0.3);
|
||||
color: #fff !important;
|
||||
}
|
||||
.list-goods-list-item{
|
||||
border: 1px solid #DADFE6;
|
||||
padding: 20px 10px;
|
||||
box-sizing: border-box;
|
||||
border-radius:3px;
|
||||
}
|
||||
.list-goods-list{
|
||||
&-item{
|
||||
text-align: center;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
img{
|
||||
width: 60%;
|
||||
}
|
||||
.ivu-tag{
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
&-title{
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #0091FF;
|
||||
margin-bottom: 3px;
|
||||
i{
|
||||
font-size: 30px;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
&-desc{
|
||||
font-size: 14px;
|
||||
color: #808695;
|
||||
}
|
||||
&-price{
|
||||
font-size: 14px;
|
||||
color: #000000;
|
||||
s{
|
||||
color: #c5c8ce;
|
||||
}
|
||||
}
|
||||
&-number{
|
||||
font-size: 14px;
|
||||
color: #ED4014;
|
||||
}
|
||||
&-pay{
|
||||
font-size: 14px;
|
||||
color: #00C050;
|
||||
i{
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
color: #6D7278;
|
||||
}
|
||||
}
|
||||
&-code{
|
||||
width: 130px;
|
||||
height: 130px;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
218
admin/src/views/sms/smsTemplate/index.vue
Normal file
218
admin/src/views/sms/smsTemplate/index.vue
Normal file
@@ -0,0 +1,218 @@
|
||||
<template>
|
||||
<!--v-if="isLogin"-->
|
||||
<div class="divBox" v-if="isLogin">
|
||||
<el-card v-loading="fullscreenLoading" class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="filter-container">
|
||||
<div class="demo-input-suffix acea-row">
|
||||
<span class="seachTiele">模板状态:</span>
|
||||
<el-select v-model="tableFrom.status" placeholder="请选择" clearable class="filter-item selWidth mr20" @change="userSearchs">
|
||||
<el-option value="1">可用</el-option>
|
||||
<el-option value="0">不可用</el-option>
|
||||
</el-select>
|
||||
<span class="seachTiele">模板名称:</span>
|
||||
<el-input v-model="tableFrom.title" placeholder="请输入商品名称,关键字,产品编号" class="selWidth">
|
||||
<el-button slot="append" icon="el-icon-search" @change="userSearchs" />
|
||||
</el-input>
|
||||
</div>
|
||||
</div>
|
||||
<el-button size="mini" type="primary" @click="add">添加短信模板</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
min-width="50"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="templateid"
|
||||
label="模板ID"
|
||||
min-width="80"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="title"
|
||||
label="模板名称"
|
||||
min-width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="content"
|
||||
label="模板内容"
|
||||
min-width="500"
|
||||
/>
|
||||
<el-table-column
|
||||
label="模板类型"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="{row}">
|
||||
<span>{{ row.type | typesFilter }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="模板状态">
|
||||
<template slot-scope="{row}">
|
||||
<span>{{ row.status | statusFilter }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="add_time"
|
||||
label="添加时间"
|
||||
min-width="150"
|
||||
/>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!--编辑-->
|
||||
<el-dialog
|
||||
title="添加模板"
|
||||
:visible.sync="dialogVisible"
|
||||
width="500px"
|
||||
:before-close="handleClose">
|
||||
<zb-parser
|
||||
v-if="dialogVisible"
|
||||
:form-id="110"
|
||||
:is-create="isCreate"
|
||||
:edit-data="editData"
|
||||
@submit="handlerSubmit"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { smsTempLstApi, tempCreateApi } from '@/api/sms'
|
||||
import { roterPre } from '@/settings'
|
||||
import { mapGetters } from 'vuex'
|
||||
import zbParser from '@/components/FormGenerator/components/parser/ZBParser'
|
||||
export default {
|
||||
name: 'SmsTemplate',
|
||||
components: { zbParser },
|
||||
filters: {
|
||||
statusFilter(status) {
|
||||
const statusMap = {
|
||||
0: '没有',
|
||||
1: '有'
|
||||
}
|
||||
return statusMap[status]
|
||||
},
|
||||
typesFilter(status) {
|
||||
const statusMap = {
|
||||
1: '验证码',
|
||||
2: '通知',
|
||||
3: '推广'
|
||||
}
|
||||
return statusMap[status]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isCreate: 0,
|
||||
editData: {},
|
||||
dialogVisible: false,
|
||||
fullscreenLoading: false,
|
||||
listLoading: false,
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
tableFrom: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
status: '',
|
||||
title: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'isLogin'
|
||||
])
|
||||
},
|
||||
mounted() {
|
||||
if (!this.isLogin) {
|
||||
this.$router.push('/operation/systemSms/config?url=' + this.$route.path)
|
||||
} else {
|
||||
this.getList()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClose() {
|
||||
this.dialogVisible = false
|
||||
this.editData = {}
|
||||
},
|
||||
handlerSubmit(formValue) {
|
||||
tempCreateApi(formValue).then(data => {
|
||||
this.$message.success('新增成功')
|
||||
this.dialogVisible = false
|
||||
this.editData = {}
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
add() {
|
||||
this.dialogVisible = true
|
||||
},
|
||||
// 查看是否登录
|
||||
onIsLogin() {
|
||||
this.fullscreenLoading = true
|
||||
this.$store.dispatch('user/isLogin').then(async res => {
|
||||
const data = res
|
||||
if (!data.status) {
|
||||
this.$message.warning('请先登录')
|
||||
this.$router.push( '/operation/systemSms/config?url=' + this.$route.path)
|
||||
} else {
|
||||
this.getList()
|
||||
}
|
||||
this.fullscreenLoading = false
|
||||
}).catch(res => {
|
||||
this.$router.push( '/operation/systemSms/config?url=' + this.$route.path)
|
||||
this.fullscreenLoading = false
|
||||
})
|
||||
},
|
||||
// 列表
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
smsTempLstApi(this.tableFrom).then(res => {
|
||||
this.tableData.data = res.data
|
||||
this.tableData.total = res.count
|
||||
this.listLoading = false
|
||||
}).catch(res => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
pageChange(page) {
|
||||
this.tableFrom.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val
|
||||
this.getList()
|
||||
},
|
||||
// 表格搜索
|
||||
userSearchs() {
|
||||
this.tableFrom.page = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.selWidth{
|
||||
width: 350px !important;
|
||||
}
|
||||
</style>
|
||||
1105
admin/src/views/store/creatStore/index.vue
Normal file
1105
admin/src/views/store/creatStore/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
1055
admin/src/views/store/creatStore/index2.vue
Normal file
1055
admin/src/views/store/creatStore/index2.vue
Normal file
File diff suppressed because it is too large
Load Diff
274
admin/src/views/store/index.vue
Normal file
274
admin/src/views/store/index.vue
Normal file
@@ -0,0 +1,274 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<el-tabs v-model="tableFrom.type" @tab-click="seachList">
|
||||
<el-tab-pane :label="item.name +'('+item.count +')' " :name="item.type.toString()" v-for="(item,index) in headeNum" :key="index"/>
|
||||
</el-tabs>
|
||||
<div class="container">
|
||||
<el-form inline size="small">
|
||||
<el-form-item label="商品分类:">
|
||||
<el-cascader v-model="tableFrom.cateId" :options="merCateList" :props="props" clearable class="selWidth mr20" @change="seachList" size="small"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品搜索:">
|
||||
<el-input v-model="tableFrom.keywords" placeholder="请输入商品名称,关键字,商品ID" class="selWidth" size="small">
|
||||
<el-button slot="append" icon="el-icon-search" @click="seachList" size="small"/>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<router-link :to=" { path:'/store/list/creatProduct' } ">
|
||||
<el-button size="small" type="primary" class="mr10">添加商品</el-button>
|
||||
</router-link>
|
||||
<el-button size="small" type="success" class="mr10" @click="onCopy">复制淘宝、天猫、拼多多、京东、苏宁</el-button>
|
||||
<el-button size="small" @click="exports">导出</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column type="expand">
|
||||
<template slot-scope="props">
|
||||
<el-form label-position="left" inline class="demo-table-expand">
|
||||
<el-form-item label="商品分类:">
|
||||
<span v-for="(item, index) in props.row.cateValues.split(',')" :key="index" class="mr10">{{ item }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="市场价:">
|
||||
<span>{{ props.row.otPrice }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="成本价:">
|
||||
<span>{{ props.row.cost }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="收藏:">
|
||||
<span>{{ props.row.collectCount }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="虚拟销量:">
|
||||
<span>{{ props.row.ficti }}</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
min-width="50"
|
||||
/>
|
||||
<el-table-column label="商品图" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<div class="demo-image__preview">
|
||||
<el-image
|
||||
style="width: 36px; height: 36px"
|
||||
:src="scope.row.image"
|
||||
:preview-src-list="[scope.row.image]"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="storeName"
|
||||
label="商品名称"
|
||||
min-width="200"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="price"
|
||||
label="商品售价"
|
||||
min-width="90"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="sales"
|
||||
label="销量"
|
||||
min-width="90"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="stock"
|
||||
label="库存"
|
||||
min-width="90"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="sort"
|
||||
label="排序"
|
||||
min-width="70"
|
||||
/>
|
||||
<el-table-column
|
||||
label="状态"
|
||||
min-width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.isShow"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
active-text="上架"
|
||||
inactive-text="下架"
|
||||
@change="onchangeIsShow(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作时间"
|
||||
min-width="120"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.addTime | formatDate}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="120" fixed="right" align="center">
|
||||
<template slot-scope="scope">
|
||||
<router-link :to="{path: '/store/list/creatProduct/' + scope.row.id}">
|
||||
<el-button type="text" size="small" class="mr10">编辑</el-button>
|
||||
</router-link>
|
||||
<el-button type="text" size="small" @click="handleDelete(scope.row.id, scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-dialog
|
||||
title="复制淘宝、天猫、拼多多、京东、苏宁"
|
||||
:visible.sync="dialogVisible"
|
||||
width="1200px"
|
||||
:before-close="handleClose">
|
||||
<tao-bao v-if="dialogVisible"></tao-bao>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { productLstApi, productDeleteApi, categoryApi, putOnShellApi, offShellApi, productHeadersApi, productExportApi } from '@/api/store'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import taoBao from './taoBao'
|
||||
export default {
|
||||
name: 'ProductList',
|
||||
components: { taoBao },
|
||||
data() {
|
||||
return {
|
||||
props: {
|
||||
children: 'child',
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
emitPath: false
|
||||
},
|
||||
// roterPre: roterPre,
|
||||
headeNum: [],
|
||||
listLoading: true,
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
tableFrom: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
cateId: '',
|
||||
keywords: '',
|
||||
type: '1'
|
||||
},
|
||||
categoryList: [],
|
||||
merCateList: [],
|
||||
objectUrl: process.env.VUE_APP_BASE_API,
|
||||
dialogVisible: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.goodHeade()
|
||||
this.getList()
|
||||
this.getCategorySelect()
|
||||
},
|
||||
methods: {
|
||||
seachList() {
|
||||
this.tableFrom.page = 1
|
||||
this.getList()
|
||||
},
|
||||
handleClose() {
|
||||
this.dialogVisible = false
|
||||
},
|
||||
// 复制
|
||||
onCopy(){
|
||||
this.dialogVisible = true
|
||||
},
|
||||
// 导出
|
||||
exports () {
|
||||
window.open(this.objectUrl + 'admin/export/excel/product?type=1&Authori-zation=' + getToken())
|
||||
},
|
||||
// 获取商品表单头数量
|
||||
goodHeade () {
|
||||
productHeadersApi().then(res => {
|
||||
console.log(res)
|
||||
this.headeNum = res
|
||||
}).catch(res => {
|
||||
this.$message.error(res.message);
|
||||
})
|
||||
},
|
||||
// 商户分类;
|
||||
getCategorySelect() {
|
||||
categoryApi({ status: -1, type: 1 }).then(res => {
|
||||
console.log(res)
|
||||
this.merCateList = res
|
||||
}).catch(res => {
|
||||
this.$message.error(res.message)
|
||||
})
|
||||
},
|
||||
// 列表
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
productLstApi(this.tableFrom).then(res => {
|
||||
this.tableData.data = res.list
|
||||
this.tableData.total = res.total
|
||||
this.listLoading = false
|
||||
}).catch(res => {
|
||||
this.listLoading = false
|
||||
this.$message.error(res.message)
|
||||
})
|
||||
},
|
||||
pageChange(page) {
|
||||
this.tableFrom.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val
|
||||
this.getList()
|
||||
},
|
||||
// 删除
|
||||
handleDelete(id, idx) {
|
||||
this.$modalSure().then(() => {
|
||||
productDeleteApi(id).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.getList()
|
||||
})
|
||||
})
|
||||
},
|
||||
onchangeIsShow(row) {
|
||||
row.isShow
|
||||
? putOnShellApi( row.id ).then(() => {
|
||||
this.$message.success('上架成功')
|
||||
this.getList()
|
||||
}) : offShellApi(row.id).then(() => {
|
||||
this.$message.success('下架成功')
|
||||
this.getList()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.selWidth{
|
||||
width: 350px !important;
|
||||
}
|
||||
.seachTiele{
|
||||
line-height: 30px;
|
||||
}
|
||||
</style>
|
||||
23
admin/src/views/store/sort/index.vue
Normal file
23
admin/src/views/store/sort/index.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<category-list :biztype="constants.categoryType[0]" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import categoryList from '@/components/Category/list'
|
||||
import * as constants from '@/utils/constants.js'
|
||||
export default {
|
||||
// name: "list",
|
||||
components: { categoryList },
|
||||
data() {
|
||||
return {
|
||||
constants
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
188
admin/src/views/store/storeAttr/index.vue
Normal file
188
admin/src/views/store/storeAttr/index.vue
Normal file
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="container">
|
||||
<el-form inline size="small">
|
||||
<el-form-item label="规格搜索:">
|
||||
<el-input v-model="tableFrom.keywords" placeholder="请输入商品规格" class="selWidth">
|
||||
<el-button slot="append" icon="el-icon-search" @click="seachList" />
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="acea-row">
|
||||
<el-button size="small" type="primary" @click="add">添加商品规格</el-button>
|
||||
<el-button size="small" @click="handleDeleteAll">批量删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
highlight-current-row
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
min-width="60"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="ruleName"
|
||||
label="规格名称"
|
||||
min-width="150"
|
||||
/>
|
||||
<el-table-column
|
||||
label="商品规格"
|
||||
min-width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-for="(item, index) in scope.row.ruleValue" :key="index" class="mr10" v-text="item.value" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="商品属性"
|
||||
min-width="300"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-for="(item, index) in scope.row.ruleValue" :key="index" v-text="item.detail.join(',')" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="120" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="onEdit(scope.row)" class="mr10">编辑</el-button>
|
||||
<el-button type="text" size="small" @click="handleDelete(scope.row.id, scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { templateListApi, attrDeleteApi } from '@/api/store'
|
||||
export default {
|
||||
name: 'StoreAttr',
|
||||
data() {
|
||||
return {
|
||||
formDynamic: {
|
||||
ruleName: '',
|
||||
ruleValue: []
|
||||
},
|
||||
tableFrom: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
keywords: ''
|
||||
},
|
||||
tableData: {
|
||||
data: [],
|
||||
loading: false,
|
||||
total: 0
|
||||
},
|
||||
listLoading: true,
|
||||
selectionList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
seachList() {
|
||||
this.tableFrom.page = 1
|
||||
this.getList()
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
this.selectionList = val
|
||||
const data = []
|
||||
this.selectionList.map((item) => {
|
||||
data.push(item.id)
|
||||
})
|
||||
this.ids = data.join(',')
|
||||
},
|
||||
add() {
|
||||
const _this = this
|
||||
this.$modalAttr(Object.assign({}, this.formDynamic), function() {
|
||||
_this.getList()
|
||||
})
|
||||
},
|
||||
// 列表
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
templateListApi(this.tableFrom).then(res => {
|
||||
const list = res.list
|
||||
this.tableData.data = list
|
||||
this.tableData.total = res.total
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
list[i].ruleValue = JSON.parse(list[i].ruleValue)
|
||||
}
|
||||
this.listLoading = false
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
pageChange(page) {
|
||||
this.tableFrom.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val
|
||||
this.getList()
|
||||
},
|
||||
// 删除
|
||||
handleDelete(id, idx) {
|
||||
this.$modalSure().then(() => {
|
||||
attrDeleteApi( id ).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.tableData.data.splice(idx, 1)
|
||||
})
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
handleDeleteAll(){
|
||||
if(!this.selectionList.length) return this.$message.warning('请选择商品规格')
|
||||
this.$modalSure().then(() => {
|
||||
attrDeleteApi( this.ids ).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.getList()
|
||||
})
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
onEdit(val) {
|
||||
const _this = this
|
||||
this.$modalAttr(JSON.parse(JSON.stringify(val)), function() {
|
||||
_this.getList()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.selWidth{
|
||||
width: 350px !important;
|
||||
}
|
||||
.seachTiele{
|
||||
line-height: 35px;
|
||||
}
|
||||
.fr{
|
||||
float: right;
|
||||
}
|
||||
</style>
|
||||
240
admin/src/views/store/storeComment/creatComment.vue
Normal file
240
admin/src/views/store/storeComment/creatComment.vue
Normal file
@@ -0,0 +1,240 @@
|
||||
<template>
|
||||
<el-form :model="formValidate" :rules="rules" ref="formValidate" label-width="100px" class="demo-formValidate" v-loading="loading">
|
||||
<el-form-item label="商品:" prop="productId">
|
||||
<div class="upLoadPicBox" @click="changeGood">
|
||||
<div v-if="formValidate.productId" class="pictrue"><img :src="image"></div>
|
||||
<div v-else class="upLoad">
|
||||
<i class="el-icon-camera cameraIconfont"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户名称:" prop="nickname">
|
||||
<el-input type="text" v-model="formValidate.nickname "></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="评价文字:" prop="comment">
|
||||
<el-input type="textarea" v-model="formValidate.comment "></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品分数:" prop="productScore" class="productScore">
|
||||
<el-rate v-model="formValidate.productScore"></el-rate>
|
||||
<!--<el-input-number type="textarea" v-model="formValidate.productScore "></el-input-number>-->
|
||||
</el-form-item>
|
||||
<el-form-item label="服务分数:" prop="serviceScore" class="productScore">
|
||||
<el-rate v-model="formValidate.serviceScore"></el-rate>
|
||||
<!--<el-input-number type="textarea" v-model="formValidate.serviceScore "></el-input-number>-->
|
||||
</el-form-item>
|
||||
<el-form-item label="用户头像:" prop="avatar">
|
||||
<div class="upLoadPicBox" @click="modalPicTap('1')">
|
||||
<div v-if="formValidate.avatar" class="pictrue"><img :src="formValidate.avatar"></div>
|
||||
<div v-else class="upLoad">
|
||||
<i class="el-icon-camera cameraIconfont"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="评价图片:">
|
||||
<div class="acea-row">
|
||||
<div
|
||||
v-for="(item,index) in pics"
|
||||
:key="index"
|
||||
class="pictrue"
|
||||
draggable="false"
|
||||
@dragstart="handleDragStart($event, item)"
|
||||
@dragover.prevent="handleDragOver($event, item)"
|
||||
@dragenter="handleDragEnter($event, item)"
|
||||
@dragend="handleDragEnd($event, item)"
|
||||
>
|
||||
<img :src="item">
|
||||
<i class="el-icon-error btndel" @click="handleRemove(index)" />
|
||||
<!--<Button shape="circle" icon="md-close" class="btndel" @click.native="handleRemove(index)" />-->
|
||||
</div>
|
||||
<div class="upLoadPicBox" @click="modalPicTap('2')">
|
||||
<div class="upLoad">
|
||||
<i class="el-icon-camera cameraIconfont" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="mini" type="primary" @click="submitForm('formValidate')">立即创建</el-button>
|
||||
<el-button size="mini" @click="resetForm('formValidate')">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { replyCreatApi, replyEditApi, replyInfoApi } from '@/api/store'
|
||||
const defaultObj= {
|
||||
avatar: '',
|
||||
comment: '',
|
||||
nickname: '',
|
||||
pics: '',
|
||||
productId: '',
|
||||
productScore: null,
|
||||
serviceScore: null
|
||||
}
|
||||
export default {
|
||||
name: "creatComment",
|
||||
props:{
|
||||
num: {
|
||||
type: Number,
|
||||
required: 0
|
||||
},
|
||||
},
|
||||
data() {
|
||||
var checkProductScore = (rule, value, callback) => {
|
||||
if (!value) {
|
||||
return callback(new Error('商品分数不能为空'));
|
||||
}else{
|
||||
callback();
|
||||
}
|
||||
};
|
||||
var checkServiceScore = (rule, value, callback) => {
|
||||
if (!value) {
|
||||
return callback(new Error('服务分数不能为空'));
|
||||
}else{
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
loading: false,
|
||||
pics: [],
|
||||
image: '',
|
||||
formValidate: Object.assign({}, defaultObj),
|
||||
rules: {
|
||||
avatar: [
|
||||
{required: true, message: '请选择用户头像', trigger: 'change'},
|
||||
],
|
||||
productId: [
|
||||
{required: true, message: '请选择商品', trigger: 'change'},
|
||||
],
|
||||
comment: [
|
||||
{required: true, message: '请填写评价内容', trigger: 'blur'},
|
||||
],
|
||||
nickname: [
|
||||
{required: true, message: '请填写用户名称', trigger: 'blur'},
|
||||
],
|
||||
pics: [
|
||||
{required: true, message: '请选择评价图片', trigger: 'change'},
|
||||
],
|
||||
productScore: [
|
||||
{required: true, validator: checkProductScore, trigger: 'blur'},
|
||||
],
|
||||
serviceScore: [
|
||||
{required: true, validator: checkServiceScore, trigger: 'change'},
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
num: {
|
||||
handler: function(val) {
|
||||
this.resetForm('formValidate')
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeGood(){
|
||||
const _this = this
|
||||
this.$modalGoodList(function(row) {
|
||||
_this.image = row.image
|
||||
_this.formValidate.productId = row.id
|
||||
})
|
||||
},
|
||||
// 点击商品图
|
||||
modalPicTap (tit) {
|
||||
const _this = this
|
||||
_this.$modalUpload(function(img) {
|
||||
console.log(img)
|
||||
tit==='1' ? _this.formValidate.avatar = img[0].sattDir : img.map((item) => {
|
||||
_this.pics.push( item.sattDir)
|
||||
})
|
||||
},tit, 'store')
|
||||
},
|
||||
handleRemove (i) {
|
||||
this.pics.splice(i, 1)
|
||||
},
|
||||
submitForm(formName) {
|
||||
this.formValidate.pics = JSON.stringify(this.pics)
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
replyCreatApi(this.formValidate).then(() => {
|
||||
this.$message.success("新增成功")
|
||||
this.$msgbox.close()
|
||||
setTimeout(() => {
|
||||
// this.clear();
|
||||
this.$emit('getList');
|
||||
}, 600);
|
||||
})
|
||||
} else {
|
||||
console.log('error submit!!');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
resetForm(formName) {
|
||||
this.$refs[formName].resetFields()
|
||||
this.$msgbox.close()
|
||||
this.pics=[]
|
||||
this.formValidate.pics=''
|
||||
},
|
||||
info(){
|
||||
this.loading = true
|
||||
replyInfoApi(this.formValidate).then(() => {
|
||||
this.formValidate = res
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 移动
|
||||
handleDragStart (e, item) {
|
||||
this.dragging = item;
|
||||
},
|
||||
handleDragEnd (e, item) {
|
||||
this.dragging = null
|
||||
},
|
||||
handleDragOver (e) {
|
||||
e.dataTransfer.dropEffect = 'move'
|
||||
},
|
||||
handleDragEnter (e, item) {
|
||||
e.dataTransfer.effectAllowed = 'move'
|
||||
if (item === this.dragging) {
|
||||
return
|
||||
}
|
||||
const newItems = [...this.pics]
|
||||
const src = newItems.indexOf(this.dragging)
|
||||
const dst = newItems.indexOf(item)
|
||||
newItems.splice(dst, 0, ...newItems.splice(src, 1))
|
||||
this.pics = newItems;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.productScore{
|
||||
/deep/.el-rate{
|
||||
line-height: 2.4;
|
||||
}
|
||||
}
|
||||
.pictrue{
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px dotted rgba(0,0,0,0.1);
|
||||
margin-right: 10px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.btndel{
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width :20px !important;
|
||||
height: 20px !important;
|
||||
left: 46px;
|
||||
top: -4px;
|
||||
}
|
||||
</style>
|
||||
318
admin/src/views/store/storeComment/index.vue
Normal file
318
admin/src/views/store/storeComment/index.vue
Normal file
@@ -0,0 +1,318 @@
|
||||
<template>
|
||||
<div class="divBox">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<div class="container">
|
||||
<el-form :inline="true">
|
||||
<el-form-item label="时间选择:" class="width100">
|
||||
<el-radio-group v-model="tableFrom.dateLimit" type="button" @change="selectChange(tableFrom.dateLimit)" class="mr20" size="small">
|
||||
<el-radio-button :label=item.val v-for="(item,i) in fromList.fromTxt" :key="i">{{item.text}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-date-picker @change="onchangeTime" v-model="timeVal" value-format="yyyy-MM-dd" format="yyyy-MM-dd" size="small" type="daterange" placement="bottom-end" placeholder="自定义时间" style="width: 220px;"></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="评价状态:" class="mr10">
|
||||
<el-select v-model="tableFrom.isReply" placeholder="请选择评价状态" @change="seachList" size="small" class="selWidth" clearable>
|
||||
<el-option label="已回复" value="1"></el-option>
|
||||
<el-option label="未回复" value="0"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品搜索:" class="mr10">
|
||||
<el-input v-model="tableFrom.productId" placeholder="请输入商品名称,关键字,产品编号" class="selWidth" size="small">
|
||||
<el-button slot="append" icon="el-icon-search" @click="seachList" size="small"/>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户名称:">
|
||||
<el-input v-model="tableFrom.nickname" placeholder="请输入用户名称" class="selWidth" size="small">
|
||||
<el-button slot="append" icon="el-icon-search" @click="seachList" size="small"/>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-button size="small" type="primary" @click="add">添加虚拟评论</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="tableData.data"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
class="table"
|
||||
>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="ID"
|
||||
width="50"
|
||||
/>
|
||||
<el-table-column label="商品信息" min-width="300">
|
||||
<template slot-scope="scope">
|
||||
<div class="demo-image__preview acea-row row-middle" v-if="scope.row.storeProduct">
|
||||
<el-image
|
||||
style="width:30px;height: 30px;"
|
||||
:src="scope.row.storeProduct.image"
|
||||
:preview-src-list="[scope.row.storeProduct.image]"
|
||||
class="mr10"
|
||||
/>
|
||||
<div class="info">{{scope.row.storeProduct.storeName}}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="nickname"
|
||||
label="用户名称"
|
||||
min-width="200"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="serviceScore"
|
||||
label="评分"
|
||||
min-width="90"
|
||||
/>
|
||||
<el-table-column
|
||||
label="评价内容"
|
||||
min-width="210"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div class="mb5 content_font">{{scope.row.comment}}</div>
|
||||
<div class="demo-image__preview">
|
||||
<el-image
|
||||
:src="item"
|
||||
class='mr5'
|
||||
:preview-src-list="[item]"
|
||||
v-for="(item,index) in scope.row.pics" :key="index"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="merchantReplyContent"
|
||||
label="回复内容"
|
||||
min-width="250"
|
||||
/>
|
||||
<el-table-column
|
||||
label="评价时间"
|
||||
min-width="120"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span> {{scope.row.createTime}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="120" fixed="right" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="reply(scope.row.id)" class="mr10">回复</el-button>
|
||||
<el-button type="text" size="small" @click="handleDelete(scope.row.id, scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="block">
|
||||
<el-pagination
|
||||
:page-sizes="[20, 40, 60, 80]"
|
||||
:page-size="tableFrom.limit"
|
||||
:current-page="tableFrom.page"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="tableData.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import creatComment from './creatComment.vue'
|
||||
import { categoryApi, replyListApi, replyDeleteApi, replyCommentApi } from '@/api/store'
|
||||
import { formatDates } from '@/utils/index';
|
||||
export default {
|
||||
name: 'StoreComment',
|
||||
filters: {
|
||||
formatDate (time) {
|
||||
if (time !== 0) {
|
||||
const date = new Date(time * 1000);
|
||||
return formatDates(date, 'yyyy-MM-dd hh:mm');
|
||||
}
|
||||
}
|
||||
},
|
||||
components: { creatComment },
|
||||
data() {
|
||||
return {
|
||||
merCateList: [],
|
||||
props: {
|
||||
children: 'child',
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
emitPath: false
|
||||
},
|
||||
fromList: {
|
||||
title: '选择时间',
|
||||
custom: true,
|
||||
fromTxt: [
|
||||
{ text: '全部', val: '' },
|
||||
{ text: '今天', val: 'today' },
|
||||
{ text: '昨天', val: 'yesterday' },
|
||||
{ text: '最近7天', val: 'lately7' },
|
||||
{ text: '最近30天', val: 'lately30' },
|
||||
{ text: '本月', val: 'month' },
|
||||
{ text: '本年', val: 'year' }
|
||||
]
|
||||
},
|
||||
tableData: {
|
||||
data: [],
|
||||
total: 0
|
||||
},
|
||||
listLoading: true,
|
||||
tableFrom: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
isReply: '',
|
||||
dateLimit: '',
|
||||
nickname: '',
|
||||
productId:'',
|
||||
isDel: false
|
||||
},
|
||||
timeVal: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// this.getLstFilterApi()
|
||||
this.getList()
|
||||
this.getCategorySelect()
|
||||
},
|
||||
methods:{
|
||||
seachList() {
|
||||
this.tableFrom.page = 1
|
||||
this.getList()
|
||||
},
|
||||
// 回复
|
||||
reply(id) {
|
||||
this.$prompt('回复内容', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputErrorMessage: '请输入回复内容',
|
||||
inputType: 'textarea',
|
||||
inputPlaceholder: '请输入回复内容',
|
||||
inputValidator: (value) => {
|
||||
if (!value) {
|
||||
return '输入不能为空';
|
||||
}
|
||||
}
|
||||
}).then(({value}) => {
|
||||
replyCommentApi({
|
||||
ids: id,
|
||||
merchantReplyContent: value
|
||||
}).then(res => {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '回复成功'
|
||||
});
|
||||
this.getList();
|
||||
})
|
||||
}).catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '取消输入'
|
||||
})
|
||||
})
|
||||
},
|
||||
// 选择时间
|
||||
selectChange (tab) {
|
||||
this.timeVal = [];
|
||||
this.tableFrom.page = 1
|
||||
this.getList();
|
||||
},
|
||||
// 商户分类;
|
||||
getCategorySelect() {
|
||||
categoryApi({ status: -1, type: 1 }).then(res => {
|
||||
this.merCateList = res
|
||||
}).catch(res => {
|
||||
this.$message.error(res.message)
|
||||
})
|
||||
},
|
||||
add() {
|
||||
const timer = new Date().getTime()
|
||||
const _this = this
|
||||
this.modalFrom(timer,null,function() {
|
||||
_this.getList()
|
||||
})
|
||||
},
|
||||
modalFrom(timer, callback){
|
||||
const h = this.$createElement
|
||||
this.$msgbox({
|
||||
title: '虚拟评论',
|
||||
customClass: 'creatformModel',
|
||||
message: h('div', { class: 'common-form-upload' }, [
|
||||
h('creatComment', {
|
||||
props: {
|
||||
num: timer
|
||||
},
|
||||
on: {
|
||||
getList() {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
})
|
||||
]),
|
||||
showCancelButton: false,
|
||||
showConfirmButton: false
|
||||
}).then(() => {
|
||||
}).catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '已取消'
|
||||
})
|
||||
})
|
||||
},
|
||||
// 具体日期
|
||||
onchangeTime (e) {
|
||||
this.timeVal = e;
|
||||
this.tableFrom.dateLimit = e ? this.timeVal.join(',') : ''
|
||||
this.tableFrom.page = 1
|
||||
this.getList();
|
||||
},
|
||||
// 删除
|
||||
handleDelete(id, idx) {
|
||||
this.$modalSure().then(() => {
|
||||
replyDeleteApi(id).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.tableData.data.splice(idx, 1)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 列表
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
replyListApi(this.tableFrom).then(res => {
|
||||
this.tableData.data = res.list
|
||||
this.tableData.total = res.total
|
||||
this.listLoading = false
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
pageChange(page) {
|
||||
this.tableFrom.page = page
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.tableFrom.limit = val
|
||||
this.getList()
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.selWidth{
|
||||
width: 350px !important;
|
||||
}
|
||||
.table{
|
||||
.el-image{
|
||||
width: auto !important;
|
||||
height: 30px !important;
|
||||
}
|
||||
/deep/.el-image__inner, .el-image__placeholder, .el-image__error {
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
.info{
|
||||
width:63%;
|
||||
}
|
||||
|
||||
</style>
|
||||
593
admin/src/views/store/taoBao.vue
Normal file
593
admin/src/views/store/taoBao.vue
Normal file
@@ -0,0 +1,593 @@
|
||||
<template>
|
||||
<div class="Box">
|
||||
<el-card>
|
||||
<div>生成的商品默认是没有上架的,请手动上架商品!</div>
|
||||
</el-card>
|
||||
<el-form class="formValidate mt20" ref="formValidate" :model="formValidate" :rules="ruleInline" label-width="120px"
|
||||
@submit.native.prevent v-loading="loading">
|
||||
<el-form-item>
|
||||
<el-radio-group v-model="form">
|
||||
<el-radio :label="1">淘宝</el-radio>
|
||||
<el-radio :label="2">京东</el-radio>
|
||||
<el-radio :label="3">苏宁</el-radio>
|
||||
<el-radio :label="4">拼多多</el-radio>
|
||||
<el-radio :label="5">天猫</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="链接地址:">
|
||||
<el-input v-model="url" placeholder="请输入链接地址" class="selWidth" size="small">
|
||||
<el-button slot="append" icon="el-icon-search" @click="add" size="small"/>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="formValidate">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="商品名称:" prop="storeName">
|
||||
<el-input v-model="formValidate.storeName" placeholder="请输入商品名称"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="商品简介:">
|
||||
<el-input v-model="formValidate.storeInfo" type="textarea" :rows="3" placeholder="请输入商品简介"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="商品分类:" prop="cateIds">
|
||||
<el-cascader v-model="formValidate.cateIds" :options="merCateList" :props="props2" clearable
|
||||
class="selWidth" :show-all-levels="false"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="grid">
|
||||
<el-form-item label="商品关键字:" prop="keyword">
|
||||
<el-input v-model="formValidate.keyword" placeholder="请输入商品关键字"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="grid">
|
||||
<el-form-item label="单位:" prop="unitName">
|
||||
<el-input v-model="formValidate.unitName" placeholder="请输入单位"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="grid">
|
||||
<el-form-item label="积分:">
|
||||
<el-input-number v-model="formValidate.giveIntegral" placeholder="请输入排序" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="grid">
|
||||
<el-form-item label="虚拟销量:">
|
||||
<el-input-number v-model="formValidate.ficti" placeholder="请输入排序" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-bind="grid">
|
||||
<el-form-item label="运费模板:" prop="tempId">
|
||||
<el-select v-model="formValidate.tempId" placeholder="请选择" class="selWidthd mr20">
|
||||
<el-option
|
||||
v-for="item in shippingList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="商品封面图:" prop="image">
|
||||
<div class="upLoadPicBox" @click="modalPicTap('1')">
|
||||
<div v-if="formValidate.image" class="pictrue"><img :src="formValidate.image"></div>
|
||||
<div v-else class="upLoad">
|
||||
<i class="el-icon-camera cameraIconfont"/>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="商品轮播图:">
|
||||
<div class="acea-row">
|
||||
<div
|
||||
v-for="(item,index) in formValidate.sliderImages"
|
||||
:key="index"
|
||||
class="lunBox mr5"
|
||||
draggable="false"
|
||||
@dragstart="handleDragStart($event, item)"
|
||||
@dragover.prevent="handleDragOver($event, item)"
|
||||
@dragenter="handleDragEnter($event, item)"
|
||||
@dragend="handleDragEnd($event, item)"
|
||||
>
|
||||
<div class="pictrue"><img :src="item"></div>
|
||||
<el-button-group>
|
||||
<el-button size="mini" @click.native="checked(item,index)">主图</el-button>
|
||||
<el-button size="mini" @click.native="handleRemove(index)">移除</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="formValidate.specType" :span="24" class="noForm">
|
||||
<el-form-item label="批量设置:" class="labeltop">
|
||||
<el-table :data="oneFormBatch" border class="tabNumWidth" size="mini">
|
||||
<el-table-column align="center" label="图片" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<div class="upLoadPicBox" @click="modalPicTap('1','pi')">
|
||||
<div v-if="scope.row.image" class="pictrue pictrueTab"><img :src="scope.row.image"></div>
|
||||
<div v-else class="upLoad pictrueTab">
|
||||
<i class="el-icon-camera cameraIconfont"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-for="(item,iii) in attrValue" :key="iii" :label="formThead[iii].title"
|
||||
align="center" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row[iii]" :type="formThead[iii].title==='商品编号'?'text':'number'" :min="0"
|
||||
class="priceBox"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作" min-width="80">
|
||||
<template>
|
||||
<el-button type="text" class="submission" @click="batchAdd">批量添加</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" v-if="formValidate.specType">
|
||||
<el-form-item label="商品规格:" props="spec_type" label-for="spec_type">
|
||||
<el-table :data="ManyAttrValue" border class="tabNumWidth" size="mini">
|
||||
<template v-if="manyTabDate">
|
||||
<el-table-column v-for="(item,iii) in manyTabDate" :key="iii" align="center"
|
||||
:label="manyTabTit[iii].title" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<span class="priceBox" v-text="scope.row[iii]"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column align="center" label="图片" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<div class="upLoadPicBox" @click="modalPicTap('1','duo',scope.$index)">
|
||||
<div v-if="scope.row.image" class="pictrue pictrueTab"><img :src="scope.row.image"></div>
|
||||
<div v-else class="upLoad pictrueTab">
|
||||
<i class="el-icon-camera cameraIconfont"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-for="(item,iii) in attrValue" :key="iii" :label="formThead[iii].title"
|
||||
align="center" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row[iii]" :type="formThead[iii].title==='商品编号'?'text':'number'"
|
||||
class="priceBox"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" class="submission" @click="delAttrTable(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="商品详情:">
|
||||
<ueditor-from v-model="formValidate.content" :content="formValidate.content"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<el-button type="primary" :loading="modal_loading" class="submission"
|
||||
@click="handleSubmit('formValidate')">提交
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {crawlFromApi, treeListApi, crawlSaveApi, categoryApi, importProductApi, productCreateApi} from '@/api/store';
|
||||
import { shippingTemplatesList } from '@/api/logistics'
|
||||
const defaultObj = [{
|
||||
image: '',
|
||||
price: null,
|
||||
cost: null,
|
||||
ot_price: null,
|
||||
stock: null,
|
||||
barCode: '',
|
||||
weight: null,
|
||||
volume: null
|
||||
}]
|
||||
const objTitle = {
|
||||
price: {
|
||||
title: '售价'
|
||||
},
|
||||
cost: {
|
||||
title: '成本价'
|
||||
},
|
||||
ot_price: {
|
||||
title: '原价'
|
||||
},
|
||||
stock: {
|
||||
title: '库存'
|
||||
},
|
||||
barCode: {
|
||||
title: '商品编号'
|
||||
},
|
||||
weight: {
|
||||
title: '重量(KG)'
|
||||
},
|
||||
volume: {
|
||||
title: '体积(m³)'
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'taoBao',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
formThead: Object.assign({}, objTitle),
|
||||
manyTabTit: {},
|
||||
manyTabDate: {},
|
||||
formValidate: null,
|
||||
form: 1,
|
||||
props2: {
|
||||
children: 'child',
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
multiple: true,
|
||||
emitPath: false
|
||||
},
|
||||
modal_loading: false,
|
||||
ManyAttrValue: [Object.assign({}, defaultObj[0])], // 多规格
|
||||
imgList: [],
|
||||
tempData: {
|
||||
page: 1,
|
||||
limit: 9999
|
||||
},
|
||||
shippingList:[],
|
||||
merCateList:[],
|
||||
images: '',
|
||||
url: '',
|
||||
modalPic: false,
|
||||
isChoice: '',
|
||||
ruleInline: {
|
||||
storeName: [
|
||||
{ required: true, message: '请输入商品名称', trigger: 'blur' }
|
||||
],
|
||||
cateIds: [
|
||||
{ required: true, message: '请选择商品分类', trigger: 'change', type: 'array', min: '1' }
|
||||
],
|
||||
unitName: [
|
||||
{ required: true, message: '请输入单位', trigger: 'blur' }
|
||||
],
|
||||
tempId: [
|
||||
{required: true, message: '请选择运费模板', trigger: 'change', type: 'number'}
|
||||
],
|
||||
keyword: [
|
||||
{ required: true, message: '请输入商品关键字', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
grid: {
|
||||
xl: 8,
|
||||
lg: 8,
|
||||
md: 12,
|
||||
sm: 24,
|
||||
xs: 24
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.goodsCategory();
|
||||
},
|
||||
computed: {
|
||||
attrValue() {
|
||||
const obj = Object.assign({}, defaultObj[0])
|
||||
delete obj.image
|
||||
return obj
|
||||
},
|
||||
oneFormBatch() {
|
||||
const obj = [Object.assign({}, defaultObj[0])]
|
||||
delete obj[0].barCode
|
||||
return obj
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'formValidate.attr': {
|
||||
handler: function(val) {
|
||||
this.watCh(val)
|
||||
},
|
||||
immediate: false,
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.productGetTemplate();
|
||||
},
|
||||
methods: {
|
||||
// 批量添加
|
||||
batchAdd() {
|
||||
// if (!this.oneFormBatch[0].pic || !this.oneFormBatch[0].price || !this.oneFormBatch[0].cost || !this.oneFormBatch[0].ot_price ||
|
||||
// !this.oneFormBatch[0].stock || !this.oneFormBatch[0].bar_code) return this.$Message.warning('请填写完整的批量设置内容!');
|
||||
for (const val of this.ManyAttrValue) {
|
||||
this.$set(val, 'image', this.oneFormBatch[0].image)
|
||||
this.$set(val, 'price', this.oneFormBatch[0].price)
|
||||
this.$set(val, 'cost', this.oneFormBatch[0].cost)
|
||||
this.$set(val, 'ot_price', this.oneFormBatch[0].ot_price)
|
||||
this.$set(val, 'stock', this.oneFormBatch[0].stock)
|
||||
this.$set(val, 'barCode', this.oneFormBatch[0].barCode)
|
||||
this.$set(val, 'weight', this.oneFormBatch[0].weight)
|
||||
this.$set(val, 'volume', this.oneFormBatch[0].volume)
|
||||
}
|
||||
},
|
||||
watCh(val) {
|
||||
const tmp = {}
|
||||
const tmpTab = {}
|
||||
this.formValidate.attr.forEach((o, i) => {
|
||||
tmp['value' + i] = { title: o.attrName }
|
||||
tmpTab['value' + i] = ''
|
||||
})
|
||||
this.ManyAttrValue = this.attrFormat(val)
|
||||
this.manyTabTit = tmp
|
||||
this.manyTabDate = tmpTab
|
||||
this.formThead = Object.assign({}, this.formThead, tmp)
|
||||
},
|
||||
attrFormat(arr) {
|
||||
let data = []
|
||||
const res = []
|
||||
return format(arr)
|
||||
function format(arr) {
|
||||
if (arr.length > 1) {
|
||||
arr.forEach((v, i) => {
|
||||
if (i === 0) data = arr[i]['attrValue']
|
||||
const tmp = []
|
||||
data.forEach(function(vv) {
|
||||
arr[i + 1] && arr[i + 1]['attrValue'] && arr[i + 1]['attrValue'].forEach(g => {
|
||||
const rep2 = (i !== 0 ? '' : arr[i]['attrName'] + '_') + vv + '$&' + arr[i + 1]['attrName'] + '_' + g
|
||||
tmp.push(rep2)
|
||||
if (i === (arr.length - 2)) {
|
||||
const rep4 = {
|
||||
image: '',
|
||||
price: 0,
|
||||
cost: 0,
|
||||
ot_price: 0,
|
||||
stock: 0,
|
||||
barCode: '',
|
||||
weight: 0,
|
||||
volume: 0,
|
||||
brokerage: 0,
|
||||
brokerage_two: 0
|
||||
}
|
||||
rep2.split('$&').forEach((h, k) => {
|
||||
const rep3 = h.split('_')
|
||||
if (!rep4['attrValue']) rep4['attrValue'] = {}
|
||||
rep4['attrValue'][rep3[0]] = rep3.length > 1 ? rep3[1] : ''
|
||||
})
|
||||
Object.values(rep4.attrValue).forEach((v, i) => {
|
||||
rep4['value' + i] = v
|
||||
})
|
||||
res.push(rep4)
|
||||
}
|
||||
})
|
||||
})
|
||||
data = tmp.length ? tmp : []
|
||||
})
|
||||
} else {
|
||||
const dataArr = []
|
||||
arr.forEach((v, k) => {
|
||||
v['attrValue'].forEach((vv, kk) => {
|
||||
dataArr[kk] = v['attrName'] + '_' + vv
|
||||
res[kk] = {
|
||||
image: '',
|
||||
price: 0,
|
||||
cost: 0,
|
||||
ot_price: 0,
|
||||
stock: 0,
|
||||
barCode: '',
|
||||
weight: 0,
|
||||
volume: 0,
|
||||
brokerage: 0,
|
||||
brokerage_two: 0,
|
||||
attrValue: { [v['attrName']]: vv }
|
||||
}
|
||||
Object.values(res[kk].attrValue).forEach((v, i) => {
|
||||
res[kk]['value' + i] = v
|
||||
})
|
||||
})
|
||||
})
|
||||
data.push(dataArr.join('$&'))
|
||||
}
|
||||
return res
|
||||
}
|
||||
},
|
||||
// 获取运费模板;
|
||||
productGetTemplate() {
|
||||
shippingTemplatesList(this.tempData).then(res => {
|
||||
this.shippingList = res.list
|
||||
})
|
||||
},
|
||||
// 删除图片
|
||||
handleRemove(i) {
|
||||
this.formValidate.sliderImages.splice(i, 1);
|
||||
},
|
||||
// 选择主图
|
||||
checked(item, index) {
|
||||
this.formValidate.image = item;
|
||||
},
|
||||
// 商品分类;
|
||||
goodsCategory() {
|
||||
categoryApi({ status: -1, type: 1 }).then(res => {
|
||||
this.merCateList = res
|
||||
})
|
||||
},
|
||||
// 生成表单
|
||||
add() {
|
||||
if (this.url) {
|
||||
// var reg = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/;
|
||||
// if (!reg.test(this.soure_link)) {
|
||||
// return this.$message.warning('请输入以http开头的地址!');
|
||||
// }
|
||||
this.loading = true;
|
||||
importProductApi({ url: this.url, form: this.form}).then(res => {
|
||||
let info = res
|
||||
this.formValidate = {
|
||||
image: info.image,
|
||||
sliderImages: JSON.parse(info.sliderImage),
|
||||
sliderImage: info.sliderImage,
|
||||
storeName: info.storeName,
|
||||
storeInfo: info.storeInfo,
|
||||
keyword: info.keyword,
|
||||
cateIds: info.cateId ? info.cateId.split(',') : [], // 商品分类id
|
||||
cateId: info.cateId,// 商品分类id传值
|
||||
unitName: info.unitName,
|
||||
sort: 0,
|
||||
isShow: 0,
|
||||
isBenefit: 0,
|
||||
isNew: 0,
|
||||
isGood: 0,
|
||||
isHot: 0,
|
||||
isBest: 0,
|
||||
tempId: info.tempId,
|
||||
attrValue: info.attrValue,
|
||||
attr: info.attr,
|
||||
selectRule: info.selectRule,
|
||||
isSub: false,
|
||||
content: info.content,
|
||||
specType: info.specType,
|
||||
id: info.id,
|
||||
giveIntegral: info.giveIntegral,
|
||||
ficti: info.ficti
|
||||
}
|
||||
for (var i = 0; i < this.formValidate.attr.length; i++) {
|
||||
this.formValidate.attr[i].attrValue = JSON.parse(info.attr[i].attrValues)
|
||||
}
|
||||
this.loading = false;
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
})
|
||||
} else {
|
||||
this.$message.warning('请输入链接地址!');
|
||||
}
|
||||
},
|
||||
// 提交
|
||||
handleSubmit (name) {
|
||||
this.formValidate.attr.length ? this.formValidate.attrValue=JSON.stringify(this.ManyAttrValue):this.formValidate.attrValue=[]
|
||||
this.formValidate.cateId = this.formValidate.cateIds.join(',')
|
||||
this.formValidate.sliderImage = JSON.stringify(this.formValidate.sliderImages)
|
||||
if(!this.formValidate.specType){
|
||||
this.formValidate.attr = []
|
||||
this.formValidate.attrValue = ''
|
||||
}
|
||||
for (var i = 0; i < this.formValidate.attr.length; i++) {
|
||||
this.formValidate.attr[i].attrValues = JSON.stringify(this.formValidate.attr[i].attrValue)
|
||||
}
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.modal_loading = true
|
||||
productCreateApi(this.formValidate).then(async res => {
|
||||
this.$message.success('新增成功');
|
||||
this.$parent.dialogVisible = false
|
||||
this.modal_loading = false
|
||||
}).catch(() => {
|
||||
this.modal_loading = false
|
||||
})
|
||||
} else {
|
||||
if(!this.formValidate.storeName || !this.formValidate.cateId || !this.formValidate.keyword
|
||||
|| !this.formValidate.unitName || !this.formValidate.image){
|
||||
this.$message.warning("请填写完整商品信息!");
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 点击商品图
|
||||
modalPicTap (tit, num, i) {
|
||||
const _this = this
|
||||
this.$modalUpload(function(img) {
|
||||
if(tit==='1'&& !num){
|
||||
_this.formValidate.image = img[0].sattDir
|
||||
_this.OneattrValue[0].image = img[0].sattDir
|
||||
}
|
||||
if(tit==='2'&& !num){
|
||||
img.map((item) => {
|
||||
_this.formValidate.sliderImages.push(item.sattDir)
|
||||
});
|
||||
}
|
||||
if(tit==='1'&& num === 'dan' ){
|
||||
_this.OneattrValue[0].image = img[0].sattDir
|
||||
}
|
||||
if(tit==='1'&& num === 'duo' ){
|
||||
_this.ManyAttrValue[i].image = img[0].sattDir
|
||||
}
|
||||
if(tit==='1'&& num === 'pi' ){
|
||||
_this.oneFormBatch[0].image = img[0].sattDir
|
||||
}
|
||||
},tit, 'store')
|
||||
},
|
||||
handleDragStart(e, item) {
|
||||
this.dragging = item;
|
||||
},
|
||||
handleDragEnd(e, item) {
|
||||
this.dragging = null
|
||||
},
|
||||
// 首先把div变成可以放置的元素,即重写dragenter/dragover
|
||||
handleDragOver(e) {
|
||||
// e.dataTransfer.dropEffect="move";//在dragenter中针对放置目标来设置!
|
||||
e.dataTransfer.dropEffect = 'move'
|
||||
},
|
||||
handleDragEnter(e, item) {
|
||||
// 为需要移动的元素设置dragstart事件
|
||||
e.dataTransfer.effectAllowed = 'move'
|
||||
if (item === this.dragging) {
|
||||
return
|
||||
}
|
||||
const newItems = [...this.formValidate.slider_image]
|
||||
const src = newItems.indexOf(this.dragging)
|
||||
const dst = newItems.indexOf(item)
|
||||
newItems.splice(dst, 0, ...newItems.splice(src, 1))
|
||||
this.formValidate.slider_image = newItems
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.selWidth{
|
||||
width: 100%;
|
||||
}
|
||||
.lunBox{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid #0bb20c;
|
||||
}
|
||||
.pictrueBox{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.pictrue{
|
||||
width:111px;
|
||||
height:111px;
|
||||
border:1px dotted rgba(0,0,0,0.1);
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.pictrueTab{
|
||||
width:40px !important;
|
||||
height:40px !important;
|
||||
}
|
||||
.upLoad {
|
||||
width: 86px;
|
||||
height: 86px;
|
||||
border: 1px dotted rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
cursor: pointer;
|
||||
}
|
||||
.ft{
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form ref="pram" :model="pram" :rules="rules" label-width="100px">
|
||||
<el-form-item label="管理员账号" prop="account">
|
||||
<el-input v-model="pram.account" placeholder="管理员账号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="管理员密码" prop="pwd">
|
||||
<el-input
|
||||
v-model="pram.pwd"
|
||||
placeholder="管理员密码,不更改可以不填写"
|
||||
clearable
|
||||
@input="handlerPwdInput"
|
||||
@clear="handlerPwdInput"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="pram.pwd" label="确认密码" prop="repwd">
|
||||
<el-input v-model="pram.repwd" placeholder="确认密码" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="管理员姓名" prop="realName">
|
||||
<el-input v-model="pram.realName" placeholder="管理员姓名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="管理员身份" prop="roles">
|
||||
<el-select v-model="pram.roles" placeholder="身份" clearable multiple>
|
||||
<el-option
|
||||
v-for="item,index in roleList.list"
|
||||
:key="index"
|
||||
:label="item.roleName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-switch v-model="pram.status" :active-value="true" :inactive-value="false" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handlerSubmit('pram')">{{ isCreate===0?'確定':'更新' }}</el-button>
|
||||
<el-button @click="close">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as constants from '@/utils/constants.js'
|
||||
import * as roleApi from '@/api/role.js'
|
||||
import * as systemAdminApi from '@/api/systemadmin.js'
|
||||
export default {
|
||||
// name: "edit"
|
||||
components: { },
|
||||
props: {
|
||||
isCreate: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
editData: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return { rules: [] }
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const validatePass = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请再次输入密码'))
|
||||
} else if (value !== this.pram.pwd) {
|
||||
callback(new Error('两次输入密码不一致!'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
return {
|
||||
constants,
|
||||
pram: {
|
||||
account: null,
|
||||
level: null,
|
||||
pwd: null,
|
||||
repwd: null,
|
||||
realName: null,
|
||||
roles: null,
|
||||
status: null,
|
||||
id: null
|
||||
},
|
||||
roleList: [],
|
||||
rules: {
|
||||
account: [{ required: true, message: '请填管理员账号', trigger: ['blur', 'change'] }],
|
||||
// level: null,
|
||||
pwd: [{ required: true, message: '请填管理员密码', trigger: ['blur', 'change'] }],
|
||||
repwd: [{ required: true, message: '确认密码密码', validator: validatePass, trigger: ['blur', 'change'] }],
|
||||
realName: [{ required: true, message: '管理员姓名', trigger: ['blur', 'change'] }],
|
||||
roles: [{ required: true, message: '管理员身份', trigger: ['blur', 'change'] }]
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initEditData()
|
||||
this.handleGetRoleList()
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.$emit('hideEditDialog')
|
||||
},
|
||||
handleGetRoleList() {
|
||||
const _pram = {
|
||||
page: 1,
|
||||
limit: constants.page.limit[4]
|
||||
}
|
||||
roleApi.getRoleList(_pram).then(data => {
|
||||
this.roleList = data
|
||||
})
|
||||
},
|
||||
initEditData() {
|
||||
if (this.isCreate !== 1) return
|
||||
const { account, realName, roles, level, status, id } = this.editData
|
||||
this.pram.account = account
|
||||
this.pram.realName = realName
|
||||
const _roles = []
|
||||
if (roles.length > 0 && !roles.includes(',')) {
|
||||
_roles.push(Number.parseInt(roles))
|
||||
} else {
|
||||
_roles.push(...roles.split(',').map(item => Number.parseInt(item)))
|
||||
}
|
||||
this.pram.roles = _roles
|
||||
this.pram.status = status
|
||||
this.pram.id = id
|
||||
this.rules.pwd = []
|
||||
this.rules.repwd = []
|
||||
},
|
||||
handlerSubmit(form) {
|
||||
this.$refs[form].validate(valid => {
|
||||
if (!valid) return
|
||||
if (this.isCreate === 0) {
|
||||
this.handlerSave()
|
||||
} else {
|
||||
this.handlerEdit()
|
||||
}
|
||||
})
|
||||
},
|
||||
handlerSave() {
|
||||
systemAdminApi.adminAdd(this.pram).then(data => {
|
||||
this.$message.success('创建管理员成功')
|
||||
this.$emit('hideEditDialog')
|
||||
})
|
||||
},
|
||||
handlerEdit() {
|
||||
this.pram.roles = this.pram.roles.join(',')
|
||||
systemAdminApi.adminUpdate(this.pram).then(data => {
|
||||
this.$message.success('更新管理员成功')
|
||||
this.$emit('hideEditDialog')
|
||||
})
|
||||
},
|
||||
rulesSelect(selectKeys) {
|
||||
this.pram.rules = selectKeys
|
||||
},
|
||||
handlerPwdInput(val) {
|
||||
if (!val) {
|
||||
this.rules.pwd = []
|
||||
this.rules.repwd = []
|
||||
return
|
||||
}
|
||||
this.rules.pwd = [
|
||||
{ required: true, message: '请填管理员密码', trigger: ['blur', 'change'] },
|
||||
{ min: 6, max: 20, message: '长度6-20个字符', trigger: ['blur', 'change'] }]
|
||||
this.rules.repwd = [{ required: true, message: '两次输入密码不一致', validator: (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('两次输入密码不一致!'))
|
||||
} else if (value !== this.pram.pwd) {
|
||||
callback(new Error('两次输入密码不一致!'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}, trigger: ['blur', 'change'] }]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user