gin-vue-admin 2.0代码重构
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<ul class="moon">
|
||||
<li class="crater"></li>
|
||||
<li class="crater"></li>
|
||||
<li class="crater"></li>
|
||||
</ul>
|
||||
<ul class="mountain-range">
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
<li class="mountain"></li>
|
||||
</ul>
|
||||
<div class="mountain-range-mask"></div>
|
||||
<ul class="forest">
|
||||
<li class="hill"></li>
|
||||
<li class="hill"></li>
|
||||
<li class="hill"></li>
|
||||
</ul>
|
||||
<ul class="sparkles">
|
||||
<li class="sparkle one"></li>
|
||||
<li class="sparkle one"></li>
|
||||
<li class="sparkle one"></li>
|
||||
<li class="sparkle one"></li>
|
||||
<li class="sparkle two"></li>
|
||||
<li class="sparkle two"></li>
|
||||
<li class="sparkle two"></li>
|
||||
<li class="sparkle two"></li>
|
||||
<li class="sparkle three"></li>
|
||||
<li class="sparkle three"></li>
|
||||
<li class="sparkle three"></li>
|
||||
<li class="sparkle three"></li>
|
||||
<li class="sparkle four"></li>
|
||||
<li class="sparkle four"></li>
|
||||
<li class="sparkle four"></li>
|
||||
<li class="sparkle four"></li>
|
||||
<li class="sparkle five"></li>
|
||||
<li class="sparkle five"></li>
|
||||
<li class="sparkle five"></li>
|
||||
<li class="sparkle five"></li>
|
||||
<li class="sparkle six"></li>
|
||||
<li class="sparkle six"></li>
|
||||
<li class="sparkle six"></li>
|
||||
<li class="sparkle six"></li>
|
||||
<li class="sparkle seven"></li>
|
||||
<li class="sparkle seven"></li>
|
||||
<li class="sparkle seven"></li>
|
||||
<li class="sparkle seven"></li>
|
||||
<li class="sparkle eight"></li>
|
||||
<li class="sparkle eight"></li>
|
||||
<li class="sparkle eight"></li>
|
||||
<li class="sparkle eight"></li>
|
||||
</ul>
|
||||
<div class="grass">
|
||||
<div class="pokemon">
|
||||
<div class="poke" id="bulbasaur">
|
||||
<div class="ear"></div>
|
||||
<div class="ear"></div>
|
||||
<div class="head"></div>
|
||||
<div class="leg"></div>
|
||||
<div class="bulba-body"></div>
|
||||
<div class="bulbs">
|
||||
<div class="bulb"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="poke" id="pikachu">
|
||||
<div class="ear"></div>
|
||||
<div class="ear"></div>
|
||||
<div class="hand"></div>
|
||||
<div class="pika-body"></div>
|
||||
<div class="head"></div>
|
||||
<div class="pika-tail"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'Animition'
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import '@/style/animition.scss';
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 style="text-align:center">gin-vue-admin by 奇淼 And krank666</h2>
|
||||
<h2 style="text-align:center;margin:15px">点击动画获取联系方式</h2>
|
||||
|
||||
<el-drawer
|
||||
:visible.sync="drawer"
|
||||
title="联系方式"
|
||||
>
|
||||
<div style="text-align:center;margin-top:30px;">
|
||||
<img src="http://qmplusimg.henrongyi.top/yx.jpg" width="180" />
|
||||
<H3>krank666微信</H3>
|
||||
</div>
|
||||
<div style="text-align:center;margin-top:30px;">
|
||||
<img src="http://qmplusimg.henrongyi.top/jjz.jpg" width="180" />
|
||||
<H3>Mr.奇淼微信</H3>
|
||||
</div>
|
||||
</el-drawer>
|
||||
<div @click="drawer = true">
|
||||
<Animition />
|
||||
</div>
|
||||
<h2 style="text-align:right;margin:40px;">
|
||||
当前版本号:v0.1.0
|
||||
</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import Animition from '@/view/dashbord/component/animition.vue'
|
||||
export default {
|
||||
name: 'Dashbord',
|
||||
data() {
|
||||
return {
|
||||
drawer: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['userInfo'])
|
||||
},
|
||||
components: {
|
||||
Animition
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="big">
|
||||
<div class="inner">
|
||||
<img src="../../assets/notFound.png">
|
||||
<p>页面被神秘力量吸走了,请联系我们修复</p>
|
||||
<p>↓</p>
|
||||
<img src="../../assets/qm.png" class="leftPic">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"Login"
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.big{
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: rgb(244,244,244);
|
||||
position: relative;
|
||||
}
|
||||
.inner{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.inner p {
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
}
|
||||
.inner .leftPic{
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-left: 44%;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<form id="fromCont" method="post">
|
||||
<input @change="choseFile" id="file" multiple="multiple" type="file" />
|
||||
</form>
|
||||
<el-button @click="getFile">上传</el-button>
|
||||
<span
|
||||
v-if="this.file"
|
||||
>{{Math.floor(((this.formDataList.length-this.waitNum)/this.formDataList.length)*100)}}%</span>
|
||||
<h2>此版本为先行体验功能测试版,样式美化和性能优化正在进行中,上传切片文件和合成的完整文件分别再QMPlusserver目录的breakpointDir文件夹和fileDir文件夹</h2>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import SparkMD5 from 'spark-md5'
|
||||
import axios from 'axios'
|
||||
import {
|
||||
findFile,
|
||||
breakpointContinueFinish,
|
||||
removeChunk
|
||||
} from '@/api/breakpoint'
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
data() {
|
||||
return {
|
||||
file: null,
|
||||
fileMd5: '',
|
||||
formDataList: [],
|
||||
waitUpLoad: [],
|
||||
waitNum: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 选中文件的函数
|
||||
async choseFile(e) {
|
||||
const fileR = new FileReader() // 创建一个reader用来读取文件流
|
||||
const file = e.target.files[0] // 获取当前文件
|
||||
this.file = file // file 丢全局方便后面用 可以改进为func传参形式
|
||||
fileR.readAsArrayBuffer(file) // 把文件读成ArrayBuffer 主要为了保持跟后端的流一致
|
||||
fileR.onload = async e => {
|
||||
// 读成arrayBuffer的回调 e 为方法自带参数 相当于 dom的e 流存在e.target.result 中
|
||||
const bolb = e.target.result
|
||||
let spark = new SparkMD5.ArrayBuffer() // 创建md5制造工具 (md5用于检测文件一致性 这里不懂就打电话问我)
|
||||
spark.append(bolb) // 文件流丢进工具
|
||||
this.fileMd5 = spark.end() // 工具结束 产生一个a 总文件的md5
|
||||
const FileSliceCap = 1 * 1024 * 1024 // 分片字节数
|
||||
let start = 0 // 定义分片开始切的地方
|
||||
let end = 0 // 每片结束切的地方a
|
||||
let i = 0 // 第几片
|
||||
this.formDataList = [] // 分片存储的一个池子 丢全局
|
||||
while (end < file.size) {
|
||||
// 当结尾数字大于文件总size的时候 结束切片
|
||||
start = i * FileSliceCap // 计算每片开始位置
|
||||
end = (i + 1) * FileSliceCap // 计算每片结束位置
|
||||
var fileSlice = this.file.slice(start, end) // 开始切 file.slice 为 h5方法 对文件切片 参数为 起止字节数
|
||||
const formData = new window.FormData() // 创建FormData用于存储传给后端的信息
|
||||
formData.append('fileMd5', this.fileMd5) // 存储总文件的Md5 让后端知道自己是谁的切片
|
||||
formData.append('file', fileSlice) //当前的切片
|
||||
formData.append('chunkNumber', i) // 当前是第几片
|
||||
formData.append('fileName', this.file.name) //当前文件的文件名 用于后端文件切片的命名 formData.appen 为 formData对象添加参数的方法
|
||||
this.formDataList.push({ key: i, formData }) // 把当前切片信息 自己是第几片 存入我们方才准备好的池子
|
||||
i++
|
||||
}
|
||||
const params = {
|
||||
fileName: this.file.name,
|
||||
fileMd5: this.fileMd5,
|
||||
chunkTotal: this.formDataList.length
|
||||
}
|
||||
const res = await findFile(params)
|
||||
// 全部切完以后 发一个请求给后端 拉当前文件后台存储的切片信息 用于检测有多少上传成功的切片
|
||||
const finishList = res.data.file.ExaFileChunk // 上传成功的切片
|
||||
const IsFinish = res.data.file.IsFinish // 是否是同文件不同命 (文件md5相同 文件名不同 则默认是同一个文件但是不同文件名 此时后台数据库只需要拷贝一下数据库文件即可 不需要上传文件 即秒传功能)
|
||||
if (!IsFinish) {
|
||||
// 当是断点续传时候
|
||||
this.waitUpLoad = this.formDataList.filter(all => {
|
||||
return !(
|
||||
finishList &&
|
||||
finishList.some(fi => fi.FileChunkNumber === all.key)
|
||||
) // 找出需要上传的切片
|
||||
})
|
||||
} else {
|
||||
this.waitUpLoad = [] // 秒传则没有需要上传的切片
|
||||
}
|
||||
this.waitNum = this.waitUpLoad.length // 记录长度用于百分比展示
|
||||
}
|
||||
},
|
||||
getFile() {
|
||||
// 确定按钮
|
||||
if (this.file == null) {
|
||||
this.$message('请先上传文件')
|
||||
return
|
||||
}
|
||||
this.sliceFile() // 上传切片
|
||||
},
|
||||
sliceFile() {
|
||||
this.waitUpLoad &&
|
||||
this.waitUpLoad.map(item => {
|
||||
//需要上传的切片
|
||||
item.formData.append('chunkTotal', this.formDataList.length) // 切片总数携带给后台 总有用的
|
||||
const fileR = new FileReader() // 功能同上
|
||||
const file = item.formData.get('file')
|
||||
fileR.readAsArrayBuffer(file)
|
||||
fileR.onload = e => {
|
||||
let spark = new SparkMD5.ArrayBuffer()
|
||||
spark.append(e.target.result)
|
||||
item.formData.append('chunkMd5', spark.end()) // 获取当前切片md5 后端用于验证切片完整性
|
||||
this.upLoadFileSlice(item)
|
||||
}
|
||||
})
|
||||
},
|
||||
async upLoadFileSlice(item) {
|
||||
// 切片上传
|
||||
await axios.post(process.env.VUE_APP_BASE_API+"/fileUploadAndDownload/breakpointContinue",item.formData)
|
||||
this.waitNum-- // 百分数增加
|
||||
if (this.waitNum == 0) {
|
||||
// 切片传完以后 合成文件
|
||||
const params = {
|
||||
fileName: this.file.name,
|
||||
fileMd5: this.fileMd5
|
||||
}
|
||||
const res = await breakpointContinueFinish(params)
|
||||
if (res.success) {
|
||||
// 合成文件过后 删除缓存切片
|
||||
const params = {
|
||||
fileName: this.file.name,
|
||||
fileMd5: this.fileMd5,
|
||||
filePath: res.data.filePath
|
||||
}
|
||||
await removeChunk(params)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="search-term">
|
||||
<el-form :inline="true" :model="searchInfo" class="demo-form-inline">
|
||||
<el-form-item>
|
||||
<el-button @click="openDialog" type="primary">新增客户</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
@selection-change="handleSelectionChange"
|
||||
border
|
||||
ref="multipleTable"
|
||||
stripe
|
||||
style="width: 100%"
|
||||
tooltip-effect="dark"
|
||||
>
|
||||
<el-table-column type="selection" width="55"></el-table-column>
|
||||
<el-table-column label="接入日期" width="180">
|
||||
<template slot-scope="scope">{{ scope.row.CreatedAt|formatDate }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="姓名" prop="customerName" width="120"></el-table-column>
|
||||
<el-table-column label="电话" prop="customerPhoneData" width="120"></el-table-column>
|
||||
<el-table-column label="接入人ID" prop="sysUserId" width="120"></el-table-column>
|
||||
<el-table-column label="按钮组">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="updateCustomer(scope.row)" size="small" type="text">变更</el-button>
|
||||
<el-popover
|
||||
placement="top"
|
||||
width="160"
|
||||
v-model="visible">
|
||||
<p>确定要删除吗?</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button size="mini" type="text" @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" size="mini" @click="deleteCustomer(scope.row)">确定</el-button>
|
||||
</div>
|
||||
<el-button type="text" size="mini" slot="reference">删除</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="[10, 30, 50, 100]"
|
||||
:style="{float:'right',padding:'20px'}"
|
||||
:total="total"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
></el-pagination>
|
||||
|
||||
<el-dialog :before-close="closeDialog" :visible.sync="dialogFormVisible" title="新增Api">
|
||||
<el-form :inline="true" :model="form" label-width="80px">
|
||||
<el-form-item label="客户名">
|
||||
<el-input autocomplete="off" v-model="form.customerName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="客户电话">
|
||||
<el-input autocomplete="off" v-model="form.customerPhoneData"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer" slot="footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button @click="enterDialog" type="primary">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
在资源权限中将此角色的资源权限清空 或者不包含创建者的角色 即可屏蔽此客户资源的显示
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {
|
||||
createExaCustomer,
|
||||
updateExaCustomer,
|
||||
deleteExaCustomer,
|
||||
getExaCustomer,
|
||||
getExaCustomerList
|
||||
} from '@/api/customer'
|
||||
import { formatTimeToStr } from '@/utils/data'
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Customer',
|
||||
mixins: [infoList],
|
||||
data(){
|
||||
return{
|
||||
listApi: getExaCustomerList,
|
||||
listKey: 'customer',
|
||||
dialogFormVisible:false,
|
||||
visible:false,
|
||||
type:"",
|
||||
form:{
|
||||
customerName:"",
|
||||
customerPhoneData:""
|
||||
}
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
...mapGetters('user', ['token'])
|
||||
},
|
||||
filters: {
|
||||
formatDate: function(time) {
|
||||
if (time != null && time != '') {
|
||||
var date = new Date(time)
|
||||
return formatTimeToStr(date, 'yyyy-MM-dd hh:mm:ss')
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
async updateCustomer(row){
|
||||
const res = await getExaCustomer(row)
|
||||
this.type = "update"
|
||||
if(res.success){
|
||||
this.form = res.data.customer
|
||||
this.dialogFormVisible = true
|
||||
}
|
||||
},
|
||||
closeDialog(){
|
||||
this.dialogFormVisible = false
|
||||
},
|
||||
async deleteCustomer(row){
|
||||
this.visible = false
|
||||
const res = await deleteExaCustomer(row)
|
||||
if (res.success){
|
||||
this.getTableData()
|
||||
}
|
||||
},
|
||||
async enterDialog(){
|
||||
let res
|
||||
switch (this.type) {
|
||||
case "create":
|
||||
res =await createExaCustomer(this.form)
|
||||
break;
|
||||
case "update":
|
||||
res =await updateExaCustomer(this.form)
|
||||
break;
|
||||
default:
|
||||
res =await createExaCustomer(this.form)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if(res.success){
|
||||
this.dialogFormVisible = false
|
||||
this.getTableData()
|
||||
}
|
||||
},
|
||||
openDialog() {
|
||||
this.type = "create"
|
||||
this.dialogFormVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-upload
|
||||
:action="`${path}/fileUploadAndDownload/upload`"
|
||||
:before-remove="beforeRemove"
|
||||
:file-list="fileList"
|
||||
:headers="{'x-token':token}"
|
||||
:limit="10"
|
||||
:on-exceed="handleExceed"
|
||||
:on-preview="handlePreview"
|
||||
:on-remove="handleRemove"
|
||||
class="upload-demo"
|
||||
multiple
|
||||
>
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
<div class="el-upload__tip" slot="tip">未对文件格式及大小做校验</div>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
const path = process.env.VUE_APP_BASE_API
|
||||
export default {
|
||||
name: 'Excel',
|
||||
data() {
|
||||
return {
|
||||
path: path,
|
||||
|
||||
fileList: [
|
||||
{
|
||||
name: 'food.jpeg',
|
||||
url:
|
||||
'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
|
||||
},
|
||||
{
|
||||
name: 'food2.jpeg',
|
||||
url:
|
||||
'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['userInfo', 'token'])
|
||||
},
|
||||
methods: {
|
||||
handleRemove(file, fileList) {
|
||||
this.$message.warning(
|
||||
`共有 ${fileList.length} 个文件,移除了${file.name}`
|
||||
)
|
||||
},
|
||||
handlePreview(file) {
|
||||
this.$message.warning(`${file.name}选择完成`)
|
||||
},
|
||||
handleExceed(files, fileList) {
|
||||
this.$message.warning(
|
||||
`当前限制选择 3 个文件,本次选择了 ${
|
||||
files.length
|
||||
} 个文件,共选择了 ${files.length + fileList.length} 个文件`
|
||||
)
|
||||
},
|
||||
beforeRemove(file, fileList) {
|
||||
return this.$confirm(
|
||||
`共有 ${fileList.length} 个文件,确定移除 ${file.name}?`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,187 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form :model="form" label-width="80px" ref="form">
|
||||
<el-row>
|
||||
<el-col :span="3"><label for="">活动名称</label></el-col>
|
||||
<el-col :span="10"><el-input v-model="form.name"></el-input></el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="3"><label for="">活动区域</label></el-col>
|
||||
<el-col :span="10">
|
||||
<el-select placeholder="请选择活动区域" v-model="form.region">
|
||||
<el-option label="上海" value="shanghai"></el-option>
|
||||
<el-option label="北京" value="beijing"></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="3"><label for="">活动时间</label></el-col>
|
||||
<el-col :span="10">
|
||||
<el-col :span="11">
|
||||
<el-date-picker placeholder="选择日期" style="width: 100%;" type="date" v-model="form.date1"></el-date-picker>
|
||||
</el-col>
|
||||
<el-col :span="2" class="line">——</el-col>
|
||||
<el-col :span="11">
|
||||
<el-time-picker placeholder="选择时间" style="width: 100%;" v-model="form.date2"></el-time-picker>
|
||||
</el-col>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="3"><label for="">即时配送</label></el-col>
|
||||
<el-col :span="10"><el-switch v-model="form.delivery"></el-switch></el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="3"><label for="">活动性质</label></el-col>
|
||||
<el-col :span="10">
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="地推活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="3"><label for="">特殊资源</label></el-col>
|
||||
<el-col :span="10">
|
||||
<el-radio-group v-model="form.resource">
|
||||
<el-radio label="线上品牌商赞助"></el-radio>
|
||||
<el-radio label="线下场地免费"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="3"><label for="">活动形式</label></el-col>
|
||||
<el-col :span="10"><el-input type="textarea" v-model="form.desc"></el-input></el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="3"><label for="">穿梭框</label></el-col>
|
||||
<el-col :span="20">
|
||||
<el-transfer
|
||||
:data="data"
|
||||
:filter-method="filterMethod"
|
||||
filter-placeholder="请输入城市拼音"
|
||||
filterable
|
||||
v-model="value"
|
||||
></el-transfer>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="3"><label for="">活动时间</label></el-col>
|
||||
<el-col :span="10"><el-input v-model="form.name"></el-input></el-col>
|
||||
</el-row>
|
||||
<el-row type="flex" justify="center">
|
||||
<el-col :span="13">
|
||||
<el-button @click="onSubmit" type="primary">立即创建</el-button>
|
||||
<el-button>取消</el-button>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
|
||||
<!-- <el-form-item label="活动名称">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select label="活动区域" placeholder="请选择活动区域" v-model="form.region">
|
||||
<el-option label="上海" value="shanghai"></el-option>
|
||||
<el-option label="北京" value="beijing"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间">
|
||||
<el-col :span="11">
|
||||
<el-date-picker placeholder="选择日期" style="width: 100%;" type="date" v-model="form.date1"></el-date-picker>
|
||||
</el-col>
|
||||
<el-col :span="2" class="line" style="text-align: center">——</el-col>
|
||||
<el-col :span="11">
|
||||
<el-time-picker placeholder="选择时间" style="width: 100%;" v-model="form.date2"></el-time-picker>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="即时配送">
|
||||
<el-switch v-model="form.delivery"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动性质">
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="地推活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="特殊资源">
|
||||
<el-radio-group v-model="form.resource">
|
||||
<el-radio label="线上品牌商赞助"></el-radio>
|
||||
<el-radio label="线下场地免费"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动形式">
|
||||
<el-input type="textarea" v-model="form.desc"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="穿梭框">
|
||||
<el-transfer
|
||||
:data="data"
|
||||
:filter-method="filterMethod"
|
||||
filter-placeholder="请输入城市拼音"
|
||||
filterable
|
||||
v-model="value"
|
||||
></el-transfer>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="onSubmit" type="primary">立即创建</el-button>
|
||||
<el-button>取消</el-button>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
const generateData = () => {
|
||||
const data = []
|
||||
const cities = ['上海', '北京', '广州', '深圳', '南京', '西安', '成都']
|
||||
const pinyin = [
|
||||
'shanghai',
|
||||
'beijing',
|
||||
'guangzhou',
|
||||
'shenzhen',
|
||||
'nanjing',
|
||||
'xian',
|
||||
'chengdu'
|
||||
]
|
||||
cities.forEach((city, index) => {
|
||||
data.push({
|
||||
label: city,
|
||||
key: index,
|
||||
pinyin: pinyin[index]
|
||||
})
|
||||
})
|
||||
return data
|
||||
}
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
region: '',
|
||||
date1: '',
|
||||
date2: '',
|
||||
delivery: false,
|
||||
type: [],
|
||||
resource: '',
|
||||
desc: ''
|
||||
},
|
||||
data: generateData(),
|
||||
value: [],
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
filterMethod(query, item) {
|
||||
return item.pinyin.indexOf(query) > -1
|
||||
},
|
||||
onSubmit() {
|
||||
this.$message({
|
||||
message: '创建成功',
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"Example",
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="edit_container">
|
||||
<quill-editor
|
||||
:options="editorOption"
|
||||
@blur="onEditorBlur($event)"
|
||||
@change="onEditorChange($event)"
|
||||
@focus="onEditorFocus($event)"
|
||||
ref="myQuillEditor"
|
||||
v-model="content"
|
||||
></quill-editor>
|
||||
<el-button plain @click="saveHtml">保存</el-button>
|
||||
</div>
|
||||
<div class="edit">
|
||||
<mavon-editor v-model="model.content"></mavon-editor>
|
||||
<el-button type="primary" size="small" @click="submit">发表</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App',
|
||||
data() {
|
||||
return {
|
||||
content: `<p>hello world</p>`,
|
||||
editorOption: {},
|
||||
model:{
|
||||
content:''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
editor() {
|
||||
return this.$refs.myQuillEditor.quill
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// onEditorReady(editor) { // 准备编辑器
|
||||
|
||||
// },
|
||||
onEditorBlur() {}, // 失去焦点事件
|
||||
onEditorFocus() {}, // 获得焦点事件
|
||||
onEditorChange() {}, // 内容改变事件
|
||||
saveHtml() {}, // 保存方法
|
||||
submit(){}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,115 @@
|
||||
// table 纯前端示例
|
||||
<template>
|
||||
<div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
@selection-change="handleSelectionChange"
|
||||
border
|
||||
ref="multipleTable"
|
||||
stripe
|
||||
style="width: 100%"
|
||||
tooltip-effect="dark"
|
||||
>
|
||||
<el-table-column type="selection" width="55"></el-table-column>
|
||||
<el-table-column label="日期" width="120">
|
||||
<template slot-scope="scope">{{ scope.row.date }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="姓名" prop="name" width="120"></el-table-column>
|
||||
<el-table-column label="年龄" prop="age" width="120"></el-table-column>
|
||||
<el-table-column label="住址" prop="address" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column label="是否禁用" prop="switch">
|
||||
<template slot-scope="scope">
|
||||
<el-switch active-text="开启" inactive-text="禁用" v-model="scope.row.switch"></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="按钮组">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="toggleSelection([scope.row])">按钮1</el-button>
|
||||
<el-button type="text" size="small" @click="toggleSelection([scope.row])">按钮2</el-button>
|
||||
<el-button type="text" size="small" @click="toggleSelection([scope.row])">按钮3</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="margin-top: 20px">
|
||||
<el-button @click="toggleSelection([tableData[1], tableData[2]])">切换第二、第三行的选中状态</el-button>
|
||||
<el-button @click="toggleSelection()">取消选择</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Table',
|
||||
data() {
|
||||
return {
|
||||
tableData: [
|
||||
{
|
||||
date: '2016-05-03',
|
||||
name: '王小虎',
|
||||
age: 12,
|
||||
address: '上海市普陀区金沙江路 1518 弄',
|
||||
switch:true
|
||||
},
|
||||
{
|
||||
date: '2016-05-02',
|
||||
name: '王小虎',
|
||||
age: 12,
|
||||
address: '上海市普陀区金沙江路 1518 弄',
|
||||
switch:true
|
||||
},
|
||||
{
|
||||
date: '2016-05-04',
|
||||
name: '王小虎',
|
||||
age: 12,
|
||||
address: '上海市普陀区金沙江路 1518 弄',
|
||||
switch:true
|
||||
},
|
||||
{
|
||||
date: '2016-05-01',
|
||||
name: '王小虎',
|
||||
age: 12,
|
||||
address: '上海市普陀区金沙江路 1518 弄',
|
||||
switch:false
|
||||
},
|
||||
{
|
||||
date: '2016-05-08',
|
||||
name: '王小虎',
|
||||
age: 12,
|
||||
address: '上海市普陀区金沙江路 1518 弄',
|
||||
switch:true
|
||||
},
|
||||
{
|
||||
date: '2016-05-06',
|
||||
name: '王小虎',
|
||||
age: 12,
|
||||
address: '上海市普陀区金沙江路 1518 弄',
|
||||
switch:true
|
||||
},
|
||||
{
|
||||
date: '2016-05-07',
|
||||
name: '王小虎',
|
||||
age: 12,
|
||||
address: '上海市普陀区金沙江路 1518 弄',
|
||||
switch:false
|
||||
}
|
||||
],
|
||||
multipleSelection: []
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleSelection(rows) {
|
||||
if (rows) {
|
||||
rows.forEach(row => {
|
||||
this.$refs.multipleTable.toggleRowSelection(row)
|
||||
})
|
||||
} else {
|
||||
this.$refs.multipleTable.clearSelection()
|
||||
}
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
this.multipleSelection = val
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,164 @@
|
||||
<template>
|
||||
<div v-loading.fullscreen.lock="fullscreenLoading">
|
||||
<div class="upload">
|
||||
<el-upload
|
||||
:action="`${path}/fileUploadAndDownload/upload`"
|
||||
:before-upload="checkFile"
|
||||
:headers="{'x-token':token}"
|
||||
:on-error="uploadError"
|
||||
:on-success="uploadSuccess"
|
||||
:show-file-list="false"
|
||||
>
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||
</el-upload>
|
||||
<el-table :data="tableData" border stripe>
|
||||
<el-table-column label="预览" width="100">
|
||||
<template slot-scope="scope">
|
||||
<img :alt="scope.row.alt" :src="scope.row.url" height="80" width="80" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="日期" prop="UpdatedAt" width="180">
|
||||
<template slot-scope="scope">
|
||||
<div>{{scope.row.UpdatedAt|formatDate}}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文件名" prop="name" width="180"></el-table-column>
|
||||
<el-table-column label="链接" prop="url"></el-table-column>
|
||||
<el-table-column label="标签" prop="tag" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag
|
||||
:type="scope.row.tag === 'jpg' ? 'primary' : 'success'"
|
||||
disable-transitions
|
||||
>{{scope.row.tag}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="downloadFile(scope.row)" size="small" type="text">下载</el-button>
|
||||
<el-button @click="deleteFile(scope.row)" size="small" type="text">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="[10, 30, 50, 100]"
|
||||
:style="{float:'right',padding:'20px'}"
|
||||
:total="total"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const path = process.env.VUE_APP_BASE_API
|
||||
import { mapGetters } from 'vuex'
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
import { getFileList, deleteFile } from '@/api/fileUploadAndDownload'
|
||||
import { downloadImage } from '@/utils/downloadImg'
|
||||
import { formatTimeToStr } from '@/utils/data'
|
||||
export default {
|
||||
name: 'Upload',
|
||||
mixins: [infoList],
|
||||
data() {
|
||||
return {
|
||||
fullscreenLoading:false,
|
||||
listApi: getFileList,
|
||||
listKey: 'list',
|
||||
path: path,
|
||||
tableData: [
|
||||
{
|
||||
UpdatedAt: '2019-10-25',
|
||||
name: '文件名.jpg',
|
||||
url: 'http://qmplusimg.henrongyi.top/1571321688timg.jpg',
|
||||
tag: 'jpg'
|
||||
},
|
||||
{
|
||||
UpdatedAt: '2019-10-25',
|
||||
name: '文件名.jpg',
|
||||
url: 'http://qmplusimg.henrongyi.top/157162774820191015140921496.gif',
|
||||
tag: 'gif'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['userInfo', 'token'])
|
||||
},
|
||||
filters: {
|
||||
formatDate: function(time) {
|
||||
if (time != null && time != '') {
|
||||
var date = new Date(time)
|
||||
return formatTimeToStr(date, 'yyyy-MM-dd hh:mm:ss')
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async deleteFile(row) {
|
||||
this.$confirm('此操作将永久文件, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await deleteFile(row)
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
})
|
||||
},
|
||||
checkFile(file) {
|
||||
this.fullscreenLoading = true
|
||||
const isJPG = file.type === 'image/jpeg'
|
||||
const isPng = file.type === 'image/png'
|
||||
const isLt2M = file.size / 1024 / 1024 < 2
|
||||
if (!isJPG && !isPng) {
|
||||
this.$message.error('上传头像图片只能是 JPG或png 格式!')
|
||||
this.fullscreenLoading = false
|
||||
}
|
||||
if (!isLt2M) {
|
||||
this.$message.error('上传头像图片大小不能超过 2MB!')
|
||||
this.fullscreenLoading = false
|
||||
}
|
||||
return (isPng || isJPG) && isLt2M
|
||||
},
|
||||
uploadSuccess(res) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '上传成功'
|
||||
})
|
||||
if (res.success) {
|
||||
this.getTableData()
|
||||
}
|
||||
this.fullscreenLoading = false
|
||||
},
|
||||
uploadError() {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '上传失败'
|
||||
})
|
||||
this.fullscreenLoading = false
|
||||
|
||||
},
|
||||
downloadFile(row) {
|
||||
downloadImage(row.url, row.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<el-submenu ref="subMenu" :index="routerInfo.name">
|
||||
<template slot="title">
|
||||
<i :class="'el-icon-'+routerInfo.meta.icon"></i>
|
||||
<span slot="title">{{routerInfo.meta.title}}</span>
|
||||
</template>
|
||||
<slot></slot>
|
||||
</el-submenu>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AsyncSubmenu',
|
||||
props: {
|
||||
routerInfo: {
|
||||
default: function() {
|
||||
return null
|
||||
},
|
||||
type: Object
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
</style>
|
||||
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<component :is="menuComponent" :routerInfo="routerInfo" v-if="!routerInfo.hidden">
|
||||
<template v-if="routerInfo.children.length">
|
||||
<AsideComponent :key="item.name" :routerInfo="item" v-for="item in routerInfo.children" />
|
||||
</template>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MenuItem from './menuItem'
|
||||
import AsyncSubmenu from './asyncSubmenu'
|
||||
|
||||
export default {
|
||||
name: 'AsideComponent',
|
||||
computed: {
|
||||
menuComponent() {
|
||||
if (this.routerInfo.children.length) {
|
||||
return 'AsyncSubmenu'
|
||||
} else {
|
||||
return 'MenuItem'
|
||||
}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
routerInfo: {
|
||||
default: function() {
|
||||
return null
|
||||
},
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
components: {
|
||||
MenuItem,
|
||||
AsyncSubmenu
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
</style>
|
||||
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<el-menu-item :index="routerInfo.name">
|
||||
<i :class="'el-icon-'+routerInfo.meta.icon"></i>
|
||||
<span slot="title">{{routerInfo.meta.title}}</span>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'MenuItem',
|
||||
props: {
|
||||
routerInfo: {
|
||||
default: function() {
|
||||
return null
|
||||
},
|
||||
type: Object
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
</style>
|
||||
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div class="router-history">
|
||||
<el-tabs v-model="activeValue" type="card" :closable="!(historys.length==1&&this.$route.name=='dashbord')" @tab-click="changeTab" @tab-remove="removeTab">
|
||||
<el-tab-pane
|
||||
v-for="item in historys"
|
||||
:key="item.name"
|
||||
:label="item.meta.title"
|
||||
:name="item.name"
|
||||
>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name:"HistoryComponent",
|
||||
data(){
|
||||
return{
|
||||
historys:[
|
||||
{
|
||||
name:"dashbord",
|
||||
meta:{
|
||||
title:"仪表盘"
|
||||
}
|
||||
}
|
||||
],
|
||||
activeValue:"dashbord"
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
changeTab(tab){
|
||||
this.$router.push({name:tab.name})
|
||||
},
|
||||
removeTab(tab){
|
||||
const index = this.historys.findIndex(item=>item.name == tab)
|
||||
if(this.$route.name == tab){
|
||||
if(this.historys.length==1){
|
||||
this.$router.push({name:"dashbord"})
|
||||
}else{
|
||||
if(index<this.historys.length-1){
|
||||
this.$router.push({name:this.historys[index+1].name})
|
||||
}else{
|
||||
this.$router.push({name:this.historys[index-1].name})
|
||||
}
|
||||
}
|
||||
}
|
||||
this.historys.splice(index,1)
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
$route( to ){
|
||||
this.historys = this.historys.filter(item=>!item.meta.hidden)
|
||||
if(!this.historys.some(item=>item.name==to.name)){
|
||||
this.historys.push(to)
|
||||
}
|
||||
this.activeValue = to.name
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-scrollbar style="height:calc(100vh)">
|
||||
<el-menu
|
||||
:class="['el-menu-vertical',!isCollapse&&'noCollapse']"
|
||||
:collapse="isCollapse"
|
||||
:collapse-transition="true"
|
||||
:default-active="active"
|
||||
@select="selectMenuItem"
|
||||
active-text-color="#fff"
|
||||
text-color="rgb(191, 203, 217)"
|
||||
unique-opened
|
||||
>
|
||||
<template v-for="item in asyncRouters[0].children">
|
||||
<aside-component :key="item.name" :routerInfo="item" v-if="!item.hidden" />
|
||||
</template>
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters,mapMutations } from 'vuex'
|
||||
import AsideComponent from '@/view/layout/aside/asideComponent'
|
||||
export default {
|
||||
name: 'Aside',
|
||||
data() {
|
||||
return {
|
||||
active: '',
|
||||
isCollapse: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations("history",["addHistory"]),
|
||||
selectMenuItem(index) {
|
||||
if (index === this.$route.name) return
|
||||
this.$router.push({ name: index })
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('router', ['asyncRouters'])
|
||||
|
||||
},
|
||||
components: {
|
||||
AsideComponent
|
||||
},
|
||||
created() {
|
||||
this.active = this.$route.name
|
||||
let screenWidth = document.body.clientWidth
|
||||
if(screenWidth<1000){
|
||||
this.isCollapse = !this.isCollapse
|
||||
}
|
||||
this.$bus.on('totalCollapse', () => {
|
||||
this.isCollapse = !this.isCollapse
|
||||
})
|
||||
this.$bus.on('collapse', (item) => {
|
||||
this.isCollapse = item
|
||||
})
|
||||
|
||||
},
|
||||
watch:{
|
||||
$route(){
|
||||
this.active = this.$route.name
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$bus.off('totalCollapse')
|
||||
this.$bus.off('collapse')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.el-scrollbar {
|
||||
.el-scrollbar__view {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.menu-info {
|
||||
.menu-contorl {
|
||||
line-height: 52px;
|
||||
font-size: 20px;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,321 @@
|
||||
<template>
|
||||
<el-container class="layout-cont">
|
||||
<el-container :class="[isSider?'openside':'hideside',isMobile ? 'mobile': '']">
|
||||
<el-row :class="[isShadowBg?'shadowBg':'']" @click.native="changeShadow()"></el-row>
|
||||
<el-aside class="main-cont main-left">
|
||||
<Aside class="aside" />
|
||||
</el-aside>
|
||||
<!-- 分块滑动功能 -->
|
||||
<el-main class="main-cont main-right">
|
||||
<el-header class="header-cont">
|
||||
<div @click="totalCollapse" class="menu-total">
|
||||
<i class="el-icon-s-unfold" v-if="isCollapse"></i>
|
||||
<i class="el-icon-s-fold" v-else></i>
|
||||
</div>
|
||||
<el-breadcrumb class="breadcrumb" separator-class="el-icon-arrow-right">
|
||||
<el-breadcrumb-item
|
||||
:key="item.path"
|
||||
v-for="item in matched.slice(1,matched.length)"
|
||||
>{{item.meta.title}}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
<div class="fl-right right-box">
|
||||
<el-dropdown>
|
||||
<span class="el-dropdown-link">
|
||||
<img :src="userInfo.headerImg" height="30" width="30" />
|
||||
{{userInfo.nickName}}
|
||||
<i class="el-icon-arrow-down"></i>
|
||||
</span>
|
||||
<el-dropdown-menu class="dropdown-group" slot="dropdown">
|
||||
<el-dropdown-item>
|
||||
<span>
|
||||
更多信息
|
||||
<el-badge is-dot />
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="showPassword=true" icon="el-icon-s-custom">修改密码</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="toPerson" icon="el-icon-s-custom">个人信息</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="LoginOut" icon="el-icon-table-lamp">登 出</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-dialog
|
||||
title="修改密码"
|
||||
:visible.sync="showPassword"
|
||||
@close="clearPassword"
|
||||
width="360px"
|
||||
>
|
||||
<el-form ref="modifyPwdForm" :model="pwdModify" :rules="rules" label-width="80px">
|
||||
<el-form-item prop="password" :minlength="6" label="原密码">
|
||||
<el-input v-model="pwdModify.password" show-password></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="newPassword" :minlength="6" label="新密码">
|
||||
<el-input v-model="pwdModify.newPassword" show-password></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="confirmPassword" :minlength="6" label="确认密码">
|
||||
<el-input v-model="pwdModify.confirmPassword" show-password></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="showPassword=false">取 消</el-button>
|
||||
<el-button type="primary" @click="savePassword">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
</el-header>
|
||||
<!-- 当前面包屑用路由自动生成可根据需求修改 -->
|
||||
<!--
|
||||
:to="{ path: item.path }" 暂时注释不用-->
|
||||
<HistoryComponent />
|
||||
<transition mode="out-in" name="el-fade-in-linear">
|
||||
<router-view class="admin-box"></router-view>
|
||||
</transition>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Aside from '@/view/layout/aside'
|
||||
import HistoryComponent from '@/view/layout/aside/historyComponent/history'
|
||||
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
import { changePassword } from '@/api/user'
|
||||
export default {
|
||||
name: 'Layout',
|
||||
data() {
|
||||
return {
|
||||
isCollapse: false,
|
||||
isSider: true,
|
||||
isMobile: false,
|
||||
isShadowBg: false,
|
||||
showPassword: false,
|
||||
pwdModify: {},
|
||||
rules: {
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ min: 6, message: '最少6个字符', trigger: 'blur' }
|
||||
],
|
||||
newPassword: [
|
||||
{ required: true, message: '请输入新密码', trigger: 'blur' },
|
||||
{ min: 6, message: '最少6个字符', trigger: 'blur' }
|
||||
],
|
||||
confirmPassword: [
|
||||
{ required: true, message: '请输入确认密码', trigger: 'blur' },
|
||||
{ min: 6, message: '最少6个字符', trigger: 'blur' },
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (value !== this.pwdModify.newPassword) {
|
||||
callback(new Error('两次密码不一致'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Aside,HistoryComponent
|
||||
},
|
||||
created() {
|
||||
let screenWidth = document.body.clientWidth
|
||||
if (screenWidth < 1000) {
|
||||
this.isMobile = true
|
||||
this.isSider = false
|
||||
this.isCollapse = !this.isCollapse
|
||||
} else {
|
||||
this.isMobile = false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('user', ['LoginOut']),
|
||||
totalCollapse() {
|
||||
this.isCollapse = !this.isCollapse
|
||||
this.isSider = !this.isCollapse
|
||||
this.isShadowBg = !this.isCollapse
|
||||
this.$bus.emit('totalCollapse')
|
||||
},
|
||||
toPerson() {
|
||||
this.$router.push({ name: 'person' })
|
||||
},
|
||||
changeShadow() {
|
||||
this.isShadowBg = !this.isShadowBg
|
||||
this.isSider = !!this.isCollapse
|
||||
this.totalCollapse()
|
||||
},
|
||||
savePassword() {
|
||||
this.$refs.modifyPwdForm.validate(valid => {
|
||||
if (valid) {
|
||||
changePassword({
|
||||
username: this.userInfo.userName,
|
||||
password: this.pwdModify.password,
|
||||
newPassword: this.pwdModify.newPassword
|
||||
}).then(() => {
|
||||
this.$message.success('修改密码成功!')
|
||||
this.showPassword = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
clearPassword() {
|
||||
this.pwdModify = {
|
||||
password: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
}
|
||||
this.$refs.modifyPwdForm.clearValidate()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['userInfo']),
|
||||
...mapGetters('history', ['historys','activeValue']),
|
||||
title() {
|
||||
return this.$route.meta.title || '当前页面'
|
||||
},
|
||||
matched() {
|
||||
return this.$route.matched
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.onresize = () => {
|
||||
return (() => {
|
||||
let screenWidth = document.body.clientWidth
|
||||
if (!this.screenWidth && this.isSider) {
|
||||
if (screenWidth < 1000) {
|
||||
this.isMobile = true
|
||||
this.isSider = false
|
||||
this.isCollapse = true
|
||||
this.$bus.emit('collapse', this.isCollapse)
|
||||
}
|
||||
} else {
|
||||
if (screenWidth < 1000) {
|
||||
this.isMobile = true
|
||||
this.isSider = false
|
||||
this.isCollapse = true
|
||||
} else {
|
||||
this.isMobile = false
|
||||
}
|
||||
}
|
||||
})()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$headerHigh: 52px;
|
||||
$mainHight: 100vh;
|
||||
.el-dropdown-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
.dropdown-group {
|
||||
min-width: 100px;
|
||||
}
|
||||
.el-scrollbar__wrap {
|
||||
padding-bottom: 17px;
|
||||
}
|
||||
.layout-cont {
|
||||
.right-box {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
.menu-contorl {
|
||||
line-height: 52px;
|
||||
font-size: 20px;
|
||||
color: #eee;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.header-cont {
|
||||
height: $headerHigh !important;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
||||
line-height: $headerHigh;
|
||||
}
|
||||
.main-cont {
|
||||
.breadcrumb {
|
||||
line-height: 48px;
|
||||
display: inline-block;
|
||||
padding: 0 24px;
|
||||
// padding: 6px;
|
||||
// border-bottom: 1px solid #eee;
|
||||
}
|
||||
.router-history{
|
||||
background: #fff;
|
||||
margin-top: 1px;
|
||||
padding: 0 6px;
|
||||
}
|
||||
&.el-main {
|
||||
overflow: auto;
|
||||
background: #fff;
|
||||
// padding: 0px 10px;
|
||||
// background: #fff;
|
||||
}
|
||||
height: $mainHight !important;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
.menu-total {
|
||||
// z-index: 5;
|
||||
// position: absolute;
|
||||
// top: 10px;
|
||||
// right: -35px;
|
||||
margin-left: -10px;
|
||||
float: left;
|
||||
margin-top: 10px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
font-size: 30px;
|
||||
// border: 0 solid #ffffff;
|
||||
// border-radius: 50%;
|
||||
// background: #fff;
|
||||
}
|
||||
.aside {
|
||||
overflow: auto;
|
||||
// background: #fff;
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.el-menu-vertical {
|
||||
height: 100vh !important;
|
||||
visibility: auto;
|
||||
&:not(.el-menu--collapse) {
|
||||
width: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
&.main-left {
|
||||
width: auto !important;
|
||||
}
|
||||
&.main-right {
|
||||
.admin-title {
|
||||
float: left;
|
||||
font-size: 16px;
|
||||
vertical-align: middle;
|
||||
margin-left: 20px;
|
||||
img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
&.collapse {
|
||||
width: 53px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<el-container class="login-register-box">
|
||||
<vue-particle-line></vue-particle-line>
|
||||
<el-main class="login-box">
|
||||
<h1 class="title-1">
|
||||
<img class="logo" :src="require('@/assets/logo.png')" alt="" srcset="">
|
||||
</h1>
|
||||
<el-form :model="loginForm" :rules="rules" ref="loginForm">
|
||||
<el-form-item prop="username">
|
||||
<el-input placeholder="请输入用户名" v-model="loginForm.username"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
:type="lock==='lock'?'password':'text'"
|
||||
placeholder="请输入密码"
|
||||
v-model="loginForm.password"
|
||||
>
|
||||
<i :class="'el-input__icon el-icon-' + lock" @click="changeLock" slot="suffix"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item style="position:relative">
|
||||
<el-input
|
||||
v-model="loginForm.captcha"
|
||||
name="logVerify"
|
||||
placeholder="请输入验证码"
|
||||
maxlength="10"
|
||||
/>
|
||||
<img :src="path + picPath" alt="请输入验证码" @click="loginVefify()" class="vPic">
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="submitForm" style="width:100%">登 录</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<h3 class="title-3 fl-right">测试用户:admin 密码:123456</h3>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
import { captcha } from '@/api/user'
|
||||
const path = process.env.VUE_APP_BASE_API
|
||||
export default {
|
||||
name: 'Login',
|
||||
data() {
|
||||
const checkUsername = (rule, value, callback) => {
|
||||
if (value.length < 5 || value.length > 12) {
|
||||
return callback(new Error('请输入正确的用户名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const checkPassword = (rule, value, callback) => {
|
||||
if (value.length < 6 || value.length > 12) {
|
||||
return callback(new Error('请输入正确的密码'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
lock: 'lock',
|
||||
loginForm: {
|
||||
username: '',
|
||||
password: '',
|
||||
captcha:'',
|
||||
captchaId: '',
|
||||
},
|
||||
rules: {
|
||||
username: [{ validator: checkUsername, trigger: 'blur' }],
|
||||
password: [{ validator: checkPassword, trigger: 'blur' }]
|
||||
},
|
||||
path:path,
|
||||
logVerify:'',
|
||||
picPath:''
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loginVefify()
|
||||
},
|
||||
methods: {
|
||||
...mapActions('user', ['LoginIn']),
|
||||
async login() {
|
||||
await this.LoginIn(this.loginForm)
|
||||
},
|
||||
async submitForm() {
|
||||
this.$refs.loginForm.validate(async v => {
|
||||
if (v) {
|
||||
await this.login()
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '请正确填写登录信息',
|
||||
showClose: true
|
||||
})
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
changeLock() {
|
||||
this.lock === 'lock' ? (this.lock = 'unlock') : (this.lock = 'lock')
|
||||
},
|
||||
loginVefify() {
|
||||
captcha({}).then(ele=>{
|
||||
this.picPath = ele.data.picPath
|
||||
this.loginForm.captchaId = ele.data.captchaId
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.login-register-box {
|
||||
background: #fff;
|
||||
height: 100vh;
|
||||
.login-box {
|
||||
width: 40vw;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -22vw;
|
||||
top:5vh;
|
||||
.logo{
|
||||
height: 35vh;
|
||||
width: 35vh;
|
||||
}
|
||||
}
|
||||
.vPic{
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 0px; // 适配ie
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<el-container class="login-register-box">
|
||||
<vue-particle-line></vue-particle-line>
|
||||
<el-main class="login-box">
|
||||
<h1 class="title-1">
|
||||
<img class="logo" :src="require('@/assets/logo.png')">
|
||||
</h1>
|
||||
<el-form :model="registerForm" :rules="rules" ref="registerForm">
|
||||
<el-form-item prop="username">
|
||||
<el-input placeholder="请输入用户名" v-model="registerForm.username"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
:type="lock==='lock'?'password':'text'"
|
||||
placeholder="请输入密码"
|
||||
v-model="registerForm.password"
|
||||
>
|
||||
<i :class="'el-input__icon el-icon-' + lock" @click="changeLock" slot="suffix"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="rePassword">
|
||||
<el-input
|
||||
:type="lock==='lock'?'password':'text'"
|
||||
placeholder="请再次输入密码"
|
||||
v-model="registerForm.rePassword"
|
||||
>
|
||||
<i :class="'el-input__icon el-icon-' + lock" @click="changeLock" slot="suffix"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="submitForm" style="width:100%">注 册</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
import { register } from '@/api/user'
|
||||
export default {
|
||||
name: 'Register',
|
||||
data() {
|
||||
const ratioPassword = (rule, value, callback) => {
|
||||
if (value != this.registerForm.password) {
|
||||
return callback(new Error('两次密码不同'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const checkUsername = (rule, value, callback) => {
|
||||
if (value.length < 5 || value.length > 12) {
|
||||
return callback(new Error('请输入正确的用户名'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const checkPassword = (rule, value, callback) => {
|
||||
if (value.length < 6 || value.length > 12) {
|
||||
return callback(new Error('请输入正确的密码'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
lock: 'lock',
|
||||
registerForm: {
|
||||
username: '',
|
||||
password: '',
|
||||
rePassword: ''
|
||||
},
|
||||
rules: {
|
||||
username: [{ validator: checkUsername, trigger: 'blur' }],
|
||||
password: [{ validator: checkPassword, trigger: 'blur' }],
|
||||
rePassword: [{ validator: ratioPassword, trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('user', ['LoginIn']),
|
||||
async submitForm() {
|
||||
this.$refs.registerForm.validate(async v => {
|
||||
if (v) {
|
||||
const res = await register(this.registerForm)
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '注册成功',
|
||||
showClose: true
|
||||
})
|
||||
this.$router.push({name:"login"})
|
||||
}
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '请正确填写注册信息',
|
||||
showClose: true
|
||||
})
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
changeLock() {
|
||||
this.lock === 'lock' ? (this.lock = 'unlock') : (this.lock = 'lock')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.login-register-box {
|
||||
background: #fff;
|
||||
height: 100vh;
|
||||
.login-box {
|
||||
width: 40vw;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -22vw;
|
||||
top:5vh;
|
||||
.logo{
|
||||
height: 35vh;
|
||||
width: 35vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="fl-left left-mg-xs">
|
||||
<el-upload
|
||||
:headers="{'x-token':token}"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:show-file-list="false"
|
||||
:action="`${path}/user/uploadHeaderImg`"
|
||||
class="avatar-uploader"
|
||||
name="headerImg"
|
||||
>
|
||||
<img :src="userInfo.headerImg" class="avatar" v-if="userInfo.headerImg" />
|
||||
<i class="el-icon-plus avatar-uploader-icon" v-else></i>
|
||||
</el-upload>
|
||||
|
||||
<!-- <el-avatar :size="120" :src="userInfo.headerImg" shape="square"></el-avatar> -->
|
||||
</div>
|
||||
<div class="fl-left left-mg-lg">
|
||||
<div>用户ID:{{userInfo.uuid}}</div>
|
||||
<div>用户昵称:{{userInfo.nickName}}</div>
|
||||
<div>用户组:{{userInfo.authority&&userInfo.authority.authorityName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
const path = process.env.VUE_APP_BASE_API
|
||||
export default {
|
||||
name: 'Person',
|
||||
data(){
|
||||
return {
|
||||
path:path
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['userInfo', 'token'])
|
||||
},
|
||||
methods:{
|
||||
...mapMutations('user',['ResetUserInfo']),
|
||||
handleAvatarSuccess(res){
|
||||
this.ResetUserInfo({headerImg:res.data.user.headerImg})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
line-height: 178px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,286 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="search-term">
|
||||
<el-form :inline="true" :model="searchInfo" class="demo-form-inline">
|
||||
<el-form-item label="路径">
|
||||
<el-input placeholder="路径" v-model="searchInfo.path"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input placeholder="描述" v-model="searchInfo.description"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求">
|
||||
<el-select placeholder="请选择" clearable v-model="searchInfo.method">
|
||||
<el-option
|
||||
:key="item.value"
|
||||
:label="`${item.label}(${item.value})`"
|
||||
:value="item.value"
|
||||
v-for="item in methodOptions"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="onSubmit" type="primary">查询</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="openDialog('addApi')" type="primary">新增api</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-table :data="tableData" border stripe>
|
||||
<el-table-column label="id" min-width="60" prop="ID"></el-table-column>
|
||||
<el-table-column label="api路径" min-width="150" prop="path"></el-table-column>
|
||||
<el-table-column label="api分组" min-width="150" prop="apiGroup"></el-table-column>
|
||||
<el-table-column label="api简介" min-width="150" prop="description"></el-table-column>
|
||||
<el-table-column label="请求" min-width="150" prop="method">
|
||||
<template slot-scope="scope">
|
||||
<div>
|
||||
{{scope.row.method}}
|
||||
<el-tag
|
||||
:key="scope.row.methodFiletr"
|
||||
:type="scope.row.method|tagTypeFiletr"
|
||||
effect="dark"
|
||||
size="mini"
|
||||
>{{scope.row.method|methodFiletr}}</el-tag>
|
||||
<!-- {{scope.row.method|methodFiletr}} -->
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column fixed="right" label="操作" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="editApi(scope.row)" size="small" type="text">编辑</el-button>
|
||||
<el-button @click="deleteApi(scope.row)" size="small" type="text">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="[10, 30, 50, 100]"
|
||||
:style="{float:'right',padding:'20px'}"
|
||||
:total="total"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
></el-pagination>
|
||||
|
||||
<el-dialog :before-close="closeDialog" :visible.sync="dialogFormVisible" title="新增Api">
|
||||
<el-form :inline="true" :model="form" :rules="rules" label-width="80px" ref="apiForm">
|
||||
<el-form-item label="路径" prop="path">
|
||||
<el-input autocomplete="off" v-model="form.path"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="请求" prop="method">
|
||||
<el-select placeholder="请选择" v-model="form.method">
|
||||
<el-option
|
||||
:key="item.value"
|
||||
:label="`${item.label}(${item.value})`"
|
||||
:value="item.value"
|
||||
v-for="item in methodOptions"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="api分组" prop="apiGroup">
|
||||
<el-input autocomplete="off" v-model="form.apiGroup"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="api简介" prop="description">
|
||||
<el-input autocomplete="off" v-model="form.description"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="warning">新增Api需要在角色管理内配置权限才可使用</div>
|
||||
<div class="dialog-footer" slot="footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button @click="enterDialog" type="primary">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
// 获取列表内容封装在mixins内部 getTableData方法 初始化已封装完成 条件搜索时候 请把条件安好后台定制的结构体字段 放到 this.searchInfo 中即可实现条件搜索
|
||||
|
||||
import {
|
||||
getApiById,
|
||||
getApiList,
|
||||
createApi,
|
||||
updateApi,
|
||||
deleteApi
|
||||
} from '@/api/api'
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
|
||||
const methodOptions = [
|
||||
{
|
||||
value: 'POST',
|
||||
label: '创建',
|
||||
type: 'success'
|
||||
},
|
||||
{
|
||||
value: 'GET',
|
||||
label: '查看',
|
||||
type: ''
|
||||
},
|
||||
{
|
||||
value: 'PUT',
|
||||
label: '更新',
|
||||
type: 'warning'
|
||||
},
|
||||
{
|
||||
value: 'DELETE',
|
||||
label: '删除',
|
||||
type: 'danger'
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'Api',
|
||||
mixins: [infoList],
|
||||
data() {
|
||||
return {
|
||||
listApi: getApiList,
|
||||
listKey: 'list',
|
||||
dialogFormVisible: false,
|
||||
form: {
|
||||
path: '',
|
||||
apiGroup: '',
|
||||
method: '',
|
||||
description: ''
|
||||
},
|
||||
methodOptions: methodOptions,
|
||||
type: '',
|
||||
rules: {
|
||||
path: [{ required: true, message: '请输入api路径', trigger: 'blur' }],
|
||||
apiGroup: [{ required: true, message: '请输入组名称', trigger: 'blur' }],
|
||||
method: [
|
||||
{ required: true, message: '请选择请求方式', trigger: 'blur' }
|
||||
],
|
||||
description: [
|
||||
{ required: true, message: '请输入api介绍', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//条件搜索前端看此方法
|
||||
onSubmit() {
|
||||
this.page = 1
|
||||
this.pageSize = 10
|
||||
this.getTableData()
|
||||
},
|
||||
initForm() {
|
||||
this.form = {
|
||||
path: '',
|
||||
apiGroup: '',
|
||||
description: '',
|
||||
method: ''
|
||||
}
|
||||
},
|
||||
closeDialog() {
|
||||
this.initForm()
|
||||
this.dialogFormVisible = false
|
||||
},
|
||||
openDialog(type) {
|
||||
this.type = type
|
||||
this.dialogFormVisible = true
|
||||
},
|
||||
async editApi(row) {
|
||||
const res = await getApiById({ id: row.ID })
|
||||
this.form = res.data.api
|
||||
this.openDialog('edit')
|
||||
},
|
||||
async deleteApi(row) {
|
||||
this.$confirm('此操作将永久删除所有角色下该菜单, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await deleteApi(row)
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
})
|
||||
},
|
||||
async enterDialog() {
|
||||
this.$refs.apiForm.validate(async valid => {
|
||||
if (valid) {
|
||||
switch (this.type) {
|
||||
case 'addApi':
|
||||
{
|
||||
const res = await createApi(this.form)
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '添加成功',
|
||||
showClose: true
|
||||
})
|
||||
}
|
||||
this.getTableData()
|
||||
this.closeDialog()
|
||||
}
|
||||
|
||||
break
|
||||
case 'edit':
|
||||
{
|
||||
const res = await updateApi(this.form)
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '添加成功',
|
||||
showClose: true
|
||||
})
|
||||
}
|
||||
this.getTableData()
|
||||
this.closeDialog()
|
||||
}
|
||||
break
|
||||
default:
|
||||
{
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '未知操作',
|
||||
showClose: true
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
methodFiletr(value) {
|
||||
const target = methodOptions.filter(item => item.value === value)[0]
|
||||
// return target && `${target.label}(${target.value})`
|
||||
return target && `${target.label}`
|
||||
},
|
||||
tagTypeFiletr(value) {
|
||||
const target = methodOptions.filter(item => item.value === value)[0]
|
||||
return target && `${target.type}`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.button-box {
|
||||
padding: 10px 20px;
|
||||
.el-button {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
.el-tag--mini {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.warning {
|
||||
color: #dc143c;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<div class="authority">
|
||||
<div class="button-box clearflex">
|
||||
<el-button @click="addAuthority('0')" type="primary">新增角色</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
||||
border
|
||||
row-key="authorityId"
|
||||
stripe
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column label="角色id" min-width="180" prop="authorityId"></el-table-column>
|
||||
<el-table-column label="角色名称" min-width="180" prop="authorityName"></el-table-column>
|
||||
<el-table-column fixed="right" label="操作" min-width="300">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="opdendrawer(scope.row)" size="small" type="text">设置权限</el-button>
|
||||
<el-button @click="deleteAuth(scope.row)" size="small" type="text">删除角色</el-button>
|
||||
<el-button @click="addAuthority(scope.row.authorityId)" size="small" type="text">新增子角色</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 新增角色弹窗 -->
|
||||
<el-dialog :visible.sync="dialogFormVisible" title="新增角色">
|
||||
<el-form :model="form" :rules="rules" ref="authorityForm">
|
||||
<el-form-item label="父级角色ID" prop="parentId">
|
||||
<el-input autocomplete="off" disabled v-model="form.parentId"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色ID" prop="authorityId">
|
||||
<el-input autocomplete="off" v-model="form.authorityId"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="角色姓名" prop="authorityName">
|
||||
<el-input autocomplete="off" v-model="form.authorityName"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer" slot="footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button @click="enterDialog" type="primary">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-drawer :visible.sync="drawer" :with-header="false" size="40%" title="角色配置" v-if="drawer">
|
||||
<el-tabs class="role-box" type="border-card">
|
||||
<el-tab-pane label="角色菜单">
|
||||
<Menus :row="activeRow" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="角色api">
|
||||
<apis :row="activeRow" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="资源权限">
|
||||
<Datas :authority="tableData" :row="activeRow" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 获取列表内容封装在mixins内部 getTableData方法 初始化已封装完成
|
||||
|
||||
import {
|
||||
getAuthorityList,
|
||||
deleteAuthority,
|
||||
createAuthority
|
||||
} from '@/api/authority'
|
||||
|
||||
import Menus from '@/view/superAdmin/authority/components/menus'
|
||||
import Apis from '@/view/superAdmin/authority/components/apis'
|
||||
import Datas from '@/view/superAdmin/authority/components/datas'
|
||||
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
export default {
|
||||
name: 'Authority',
|
||||
mixins: [infoList],
|
||||
data() {
|
||||
return {
|
||||
listApi: getAuthorityList,
|
||||
listKey: 'list',
|
||||
drawer: false,
|
||||
activeRow: {},
|
||||
activeUserId: 0,
|
||||
dialogFormVisible: false,
|
||||
apiDialogFlag: false,
|
||||
form: {
|
||||
authorityId: '',
|
||||
authorityName: '',
|
||||
parentId: '0'
|
||||
},
|
||||
rules: {
|
||||
authorityId: [
|
||||
{ required: true, message: '请输入角色ID', trigger: 'blur' }
|
||||
],
|
||||
authorityName: [
|
||||
{ required: true, message: '请输入角色名', trigger: 'blur' }
|
||||
],
|
||||
parentId: [
|
||||
{ required: true, message: '请选择请求方式', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Menus,
|
||||
Apis,
|
||||
Datas
|
||||
},
|
||||
methods: {
|
||||
opdendrawer(row) {
|
||||
this.drawer = true
|
||||
this.activeRow = row
|
||||
},
|
||||
// 删除角色
|
||||
deleteAuth(row) {
|
||||
this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await deleteAuthority({ authorityId: row.authorityId })
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
})
|
||||
},
|
||||
// 初始化表单
|
||||
initForm() {
|
||||
for (const key in this.form) {
|
||||
this.form[key] = ''
|
||||
}
|
||||
},
|
||||
// 关闭窗口
|
||||
closeDialog() {
|
||||
this.initForm()
|
||||
this.dialogFormVisible = false
|
||||
this.apiDialogFlag = false
|
||||
},
|
||||
// 确定弹窗
|
||||
|
||||
async enterDialog() {
|
||||
if (this.form.authorityId == '0') {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '角色id不能为0'
|
||||
})
|
||||
return false
|
||||
}
|
||||
this.$refs.authorityForm.validate(async valid => {
|
||||
if (valid) {
|
||||
const res = await createAuthority(this.form)
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '添加成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
this.closeDialog()
|
||||
}
|
||||
this.initForm()
|
||||
this.dialogFormVisible = false
|
||||
}
|
||||
})
|
||||
},
|
||||
// 增加角色
|
||||
addAuthority(parentId) {
|
||||
this.form.parentId = parentId
|
||||
this.dialogFormVisible = true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.pageSize = 999
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.authority {
|
||||
.button-box {
|
||||
padding: 10px 20px;
|
||||
.el-button {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
.role-box {
|
||||
.el-tabs__content {
|
||||
height: calc(100vh - 150px);
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="clearflex">
|
||||
<el-button @click="authApiEnter" class="fl-right" size="small" type="primary">确 定</el-button>
|
||||
</div>
|
||||
<el-tree
|
||||
:data="apiTreeData"
|
||||
:default-checked-keys="apiTreeIds"
|
||||
:props="apiDefaultProps"
|
||||
default-expand-all
|
||||
highlight-current
|
||||
node-key="path"
|
||||
ref="apiTree"
|
||||
show-checkbox
|
||||
></el-tree>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getAllApis } from '@/api/api'
|
||||
import { casbinPUpdate, getPolicyPathByAuthorityId } from '@/api/casbin'
|
||||
export default {
|
||||
name: 'Apis',
|
||||
props: {
|
||||
row: {
|
||||
default: function() {
|
||||
return {}
|
||||
},
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
apiTreeData: [],
|
||||
apiTreeIds: [],
|
||||
apiDefaultProps: {
|
||||
children: 'children',
|
||||
label: 'description'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 创建api树方法
|
||||
buildApiTree(apis) {
|
||||
const apiObj = new Object()
|
||||
apis &&
|
||||
apis.map(item => {
|
||||
if (apiObj.hasOwnProperty(item.group)) {
|
||||
apiObj[item.group].push(item)
|
||||
} else {
|
||||
Object.assign(apiObj, { [item.group]: [item] })
|
||||
}
|
||||
})
|
||||
const apiTree = []
|
||||
for (const key in apiObj) {
|
||||
const treeNode = {
|
||||
ID: key,
|
||||
description: key + '组',
|
||||
children: apiObj[key]
|
||||
}
|
||||
apiTree.push(treeNode)
|
||||
}
|
||||
return apiTree
|
||||
},
|
||||
// 关联关系确定
|
||||
async authApiEnter() {
|
||||
const checkArr = this.$refs.apiTree.getCheckedNodes(true)
|
||||
var casbinInfos = []
|
||||
checkArr&&checkArr.map(item=>{
|
||||
var casbinInfo = {
|
||||
path:item.path,
|
||||
method:item.method
|
||||
}
|
||||
casbinInfos.push(casbinInfo)
|
||||
})
|
||||
const res = await casbinPUpdate({
|
||||
authorityId: this.activeUserId,
|
||||
casbinInfos
|
||||
})
|
||||
if (res.success) {
|
||||
this.$message({ type: 'success', message: res.msg })
|
||||
}
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
// 获取api并整理成树结构
|
||||
const res2 = await getAllApis()
|
||||
const apis = res2.data.apis
|
||||
this.apiTreeData = this.buildApiTree(apis)
|
||||
|
||||
const res = await getPolicyPathByAuthorityId({
|
||||
authorityId: this.row.authorityId
|
||||
})
|
||||
this.activeUserId = this.row.authorityId
|
||||
this.apiTreeIds = res.data.paths || []
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
</style>
|
||||
@@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="clearflex" style="margin:18px">
|
||||
<el-button @click="authDataEnter" class="fl-right" size="small" type="primary">确 定</el-button>
|
||||
<el-button @click="all" class="fl-left" size="small" type="primary">全选</el-button>
|
||||
<el-button @click="self" class="fl-left" size="small" type="primary">本部门</el-button>
|
||||
<el-button @click="selfAndChildren" class="fl-left" size="small" type="primary">部门及以下</el-button>
|
||||
</div>
|
||||
<el-checkbox-group v-model="dataAuthorityId" @change="selectAuthority">
|
||||
<el-checkbox v-for="(item,key) in authoritys" :label="item" :key="key">{{item.authorityName}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {setDataAuthority} from '@/api/authority'
|
||||
export default {
|
||||
name: 'Datas',
|
||||
data() {
|
||||
return {
|
||||
authoritys:[],
|
||||
dataAuthorityId:[]
|
||||
}
|
||||
},
|
||||
props: {
|
||||
row: {
|
||||
default: function() {
|
||||
return {}
|
||||
},
|
||||
type: Object
|
||||
},
|
||||
authority: {
|
||||
default: function() {
|
||||
return {}
|
||||
},
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
all(){
|
||||
this.dataAuthorityId = [...this.authoritys]
|
||||
this.row.dataAuthorityId = this.dataAuthorityId
|
||||
|
||||
},
|
||||
self(){
|
||||
this.dataAuthorityId = this.authoritys.filter(item=>item.authorityId===this.row.authorityId)
|
||||
this.row.dataAuthorityId = this.dataAuthorityId
|
||||
},
|
||||
selfAndChildren(){
|
||||
const arrBox = []
|
||||
this.getChildrenId(this.row,arrBox)
|
||||
this.dataAuthorityId = this.authoritys.filter(item=>arrBox.indexOf(item.authorityId)>-1)
|
||||
this.row.dataAuthorityId = this.dataAuthorityId
|
||||
},
|
||||
getChildrenId(row,arrBox){
|
||||
arrBox.push(row.authorityId)
|
||||
row.children&&row.children.map(item=>{
|
||||
this.getChildrenId(item,arrBox)
|
||||
})
|
||||
},
|
||||
// 提交
|
||||
async authDataEnter(){
|
||||
const res = await setDataAuthority(this.row)
|
||||
if(res.success){
|
||||
this.$message({ type: 'success', message: res.msg })
|
||||
}
|
||||
},
|
||||
// 平铺角色
|
||||
roundAuthority(authoritys){
|
||||
authoritys&&authoritys.map(item=>{
|
||||
const obj = {}
|
||||
obj.authorityId = item.authorityId
|
||||
obj.authorityName = item.authorityName
|
||||
this.authoritys.push(obj)
|
||||
if(item.children.length){
|
||||
this.roundAuthority(item.children)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 选择
|
||||
selectAuthority(){
|
||||
this.row.dataAuthorityId = this.dataAuthorityId
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.authoritys = []
|
||||
this.dataAuthorityId = []
|
||||
this.roundAuthority(this.authority)
|
||||
this.row.dataAuthorityId&&this.row.dataAuthorityId.map(item=>{
|
||||
const obj = this.authoritys&&this.authoritys.filter(au=>au.authorityId === item.authorityId)&&this.authoritys.filter(au=>au.authorityId === item.authorityId)[0]
|
||||
this.dataAuthorityId.push(obj)
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less">
|
||||
</style>
|
||||
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="clearflex">
|
||||
<el-button @click="relation" class="fl-right" size="small" type="primary">确 定</el-button>
|
||||
</div>
|
||||
<el-tree
|
||||
:data="menuTreeData"
|
||||
:default-checked-keys="menuTreeIds"
|
||||
:props="menuDefaultProps"
|
||||
default-expand-all
|
||||
highlight-current
|
||||
node-key="ID"
|
||||
ref="menuTree"
|
||||
show-checkbox
|
||||
></el-tree>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getBaseMenuTree, getMenuAuthority, addMenuAuthority } from '@/api/menu'
|
||||
|
||||
export default {
|
||||
name: 'Menus',
|
||||
props: {
|
||||
row: {
|
||||
default: function() {
|
||||
return {}
|
||||
},
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
menuTreeData: [],
|
||||
menuTreeIds: [],
|
||||
menuDefaultProps: {
|
||||
children: 'children',
|
||||
label: 'nickName'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 关联树 确认方法
|
||||
async relation() {
|
||||
const checkArr = this.$refs.menuTree.getCheckedNodes(false, true)
|
||||
const res = await addMenuAuthority({
|
||||
menus: checkArr,
|
||||
authorityId: this.row.authorityId
|
||||
})
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '添加成功!'
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
// 获取所有菜单树
|
||||
const res = await getBaseMenuTree()
|
||||
this.menuTreeData = res.data.menus
|
||||
|
||||
const res1 = await getMenuAuthority({ authorityId: this.row.authorityId })
|
||||
const menus = res1.data.menus
|
||||
const arr = []
|
||||
menus.map(item => {
|
||||
// 防止直接选中父级造成全选
|
||||
if (!menus.some(same => same.parentId === item.menuId)) {
|
||||
arr.push(Number(item.menuId))
|
||||
}
|
||||
})
|
||||
this.menuTreeIds = arr
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
</style>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"SuperAdmin",
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="button-box clearflex">
|
||||
<el-button @click="addMenu('0')" type="primary">新增根菜单</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 -->
|
||||
<el-table :data="tableData" border row-key="ID" stripe>
|
||||
<el-table-column label="ID" min-width="100" prop="ID"></el-table-column>
|
||||
<el-table-column label="路由Name" min-width="160" prop="name"></el-table-column>
|
||||
<el-table-column label="是否隐藏" min-width="100" prop="hidden">
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.hidden?"隐藏":"显示"}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="父节点" min-width="90" prop="parentId"></el-table-column>
|
||||
<el-table-column label="排序" min-width="70" prop="sort"></el-table-column>
|
||||
<el-table-column label="文件路径" min-width="360" prop="component"></el-table-column>
|
||||
<el-table-column label="展示名称" min-width="120" prop="authorityName">
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.meta.title}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="图标" min-width="140" prop="authorityName">
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.meta.icon}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作" width="300">
|
||||
<template slot-scope="scope">
|
||||
<el-button @click="deleteMenu(scope.row.ID)" size="small" type="text">删除菜单</el-button>
|
||||
<el-button @click="editMenu(scope.row.ID)" size="small" type="text">编辑菜单</el-button>
|
||||
<el-button @click="addMenu(scope.row.ID)" size="small" type="text">添加子菜单</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog :before-close="handleClose" :visible.sync="dialogFormVisible" title="新增菜单">
|
||||
<el-form :inline="true" :model="form" :rules="rules" label-width="85px" ref="menuForm">
|
||||
<el-form-item label="路由name" prop="path">
|
||||
<el-input autocomplete="off" placeholder="唯一英文字符串" v-model="form.path"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否隐藏">
|
||||
<el-select placeholder="是否在列表隐藏" v-model="form.hidden">
|
||||
<el-option :value="false" label="否"></el-option>
|
||||
<el-option :value="true" label="是"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="父节点Id">
|
||||
<el-input autocomplete="off" disabled v-model="form.parentId"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件路径" prop="component">
|
||||
<el-input autocomplete="off" v-model="form.component"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="展示名称" prop="meta.title">
|
||||
<el-input autocomplete="off" v-model="form.meta.title"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="图标">
|
||||
<el-input autocomplete="off" v-model="form.meta.icon"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序标记">
|
||||
<el-input autocomplete="off" v-model="form.sort"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="warning">新增菜单需要在角色管理内配置权限才可使用</div>
|
||||
<div class="dialog-footer" slot="footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button @click="enterDialog" type="primary">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 获取列表内容封装在mixins内部 getTableData方法 初始化已封装完成
|
||||
|
||||
import {
|
||||
updateBaseMenu,
|
||||
getMenuList,
|
||||
addBaseMenu,
|
||||
deleteBaseMenu,
|
||||
getBaseMenuById
|
||||
} from '@/api/menu'
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
export default {
|
||||
name: 'Menus',
|
||||
mixins: [infoList],
|
||||
data() {
|
||||
return {
|
||||
listApi: getMenuList,
|
||||
listKey: 'list',
|
||||
dialogFormVisible: false,
|
||||
form: {
|
||||
ID: 0,
|
||||
path: '',
|
||||
name: '',
|
||||
hidden: '',
|
||||
parentId: '',
|
||||
component: '',
|
||||
meta: {
|
||||
title: '',
|
||||
icon: ''
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
path: [{ required: true, message: '请输入菜单name', trigger: 'blur' }],
|
||||
component: [
|
||||
{ required: true, message: '请输入文件路径', trigger: 'blur' }
|
||||
],
|
||||
'meta.title': [
|
||||
{ required: true, message: '请输入菜单展示名称', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
isEdit: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClose(done) {
|
||||
this.initForm()
|
||||
done()
|
||||
},
|
||||
// 懒加载子菜单
|
||||
load(tree, treeNode, resolve) {
|
||||
resolve([
|
||||
{
|
||||
id: 31,
|
||||
date: '2016-05-01',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1519 弄'
|
||||
},
|
||||
{
|
||||
id: 32,
|
||||
date: '2016-05-01',
|
||||
name: '王小虎',
|
||||
address: '上海市普陀区金沙江路 1519 弄'
|
||||
}
|
||||
])
|
||||
},
|
||||
// 删除菜单
|
||||
deleteMenu(ID) {
|
||||
this.$confirm('此操作将永久删除所有角色下该菜单, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
const res = await deleteBaseMenu({ ID })
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
})
|
||||
},
|
||||
// 初始化弹窗内表格方法
|
||||
initForm() {
|
||||
this.form = {
|
||||
path: '',
|
||||
name: '',
|
||||
hidden: '',
|
||||
parentId: '',
|
||||
component: '',
|
||||
meta: {
|
||||
title: '',
|
||||
icon: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
// 关闭弹窗
|
||||
closeDialog() {
|
||||
this.initForm()
|
||||
this.dialogFormVisible = false
|
||||
},
|
||||
// 添加menu
|
||||
async enterDialog() {
|
||||
this.$refs.menuForm.validate(async valid => {
|
||||
if (valid) {
|
||||
let res
|
||||
this.form.name = this.form.path
|
||||
if (this.isEdit) {
|
||||
res = await updateBaseMenu(this.form)
|
||||
} else {
|
||||
res = await addBaseMenu(this.form)
|
||||
}
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '添加成功!'
|
||||
})
|
||||
this.getTableData()
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '添加失败!'
|
||||
})
|
||||
}
|
||||
this.initForm()
|
||||
this.dialogFormVisible = false
|
||||
}
|
||||
})
|
||||
},
|
||||
// 添加菜单方法,id为 0则为添加根菜单
|
||||
addMenu(id) {
|
||||
this.form.parentId = String(id)
|
||||
this.isEdit = false
|
||||
this.dialogFormVisible = true
|
||||
},
|
||||
// 修改菜单方法
|
||||
async editMenu(id) {
|
||||
const res = await getBaseMenuById({ id })
|
||||
this.form = res.data.menu
|
||||
this.dialogFormVisible = true
|
||||
this.isEdit = true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.pageSize = 999
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.button-box {
|
||||
padding: 10px 20px;
|
||||
.el-button {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
.warning {
|
||||
color: #dc143c;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="button-box clearflex">
|
||||
<el-button @click="addUser" type="primary">新增用户</el-button>
|
||||
</div>
|
||||
<el-table :data="tableData" border stripe>
|
||||
<el-table-column label="头像" min-width="50">
|
||||
<template slot-scope="scope">
|
||||
<div :style="{'textAlign':'center'}">
|
||||
<img :src="scope.row.headerImg" height="50" width="50" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="uuid" min-width="250" prop="uuid"></el-table-column>
|
||||
<el-table-column label="用户名" min-width="150" prop="userName"></el-table-column>
|
||||
<el-table-column label="昵称" min-width="150" prop="nickName"></el-table-column>
|
||||
<el-table-column label="用户角色" min-width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-select
|
||||
@change="changeAuthority(scope.row)"
|
||||
placeholder="请选择"
|
||||
v-model="scope.row.authority.authorityId"
|
||||
>
|
||||
<el-option
|
||||
:key="item.authorityId"
|
||||
:label="item.authorityName"
|
||||
:value="item.authorityId"
|
||||
v-for="item in authOptions"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="[10, 30, 50, 100]"
|
||||
:style="{float:'right',padding:'20px'}"
|
||||
:total="total"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
></el-pagination>
|
||||
|
||||
<el-dialog :visible.sync="addUserDialog" custom-class="user-dialog" title="新增用户">
|
||||
<el-form :rules="rules" ref="userForm" :model="userInfo" >
|
||||
<el-form-item label="用户名" label-width="80px" prop="username">
|
||||
<el-input v-model="userInfo.username"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" label-width="80px" prop="password">
|
||||
<el-input v-model="userInfo.password"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="别名" label-width="80px" prop="nickName">
|
||||
<el-input v-model="userInfo.nickName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="头像" label-width="80px">
|
||||
<el-upload
|
||||
:headers="{'x-token':token}"
|
||||
:on-success="handleAvatarSuccess"
|
||||
:show-file-list="false"
|
||||
:action="`${path}/fileUploadAndDownload/upload?noSave=1`"
|
||||
class="avatar-uploader"
|
||||
name="file"
|
||||
>
|
||||
<img :src="userInfo.headerImg" class="avatar" v-if="userInfo.headerImg" />
|
||||
<i class="el-icon-plus avatar-uploader-icon" v-else></i>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户角色" label-width="80px" prop="authorityId">
|
||||
<el-select placeholder="请选择" v-model="userInfo.authorityId">
|
||||
<el-option
|
||||
:key="item.authorityId"
|
||||
:label="item.authorityName"
|
||||
:value="item.authorityId"
|
||||
v-for="item in authOptions"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="dialog-footer" slot="footer">
|
||||
<el-button @click="closeAddUserDialog">取 消</el-button>
|
||||
<el-button @click="enterAddUserDialog" type="primary">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
// 获取列表内容封装在mixins内部 getTableData方法 初始化已封装完成
|
||||
const path = process.env.VUE_APP_BASE_API
|
||||
import { getUserList, setUserAuthority, register } from '@/api/user'
|
||||
import { getAuthorityList } from '@/api/authority'
|
||||
import infoList from '@/components/mixins/infoList'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'Api',
|
||||
mixins: [infoList],
|
||||
data() {
|
||||
return {
|
||||
listApi: getUserList,
|
||||
listKey: 'userList',
|
||||
path:path,
|
||||
authOptions: [],
|
||||
addUserDialog: false,
|
||||
userInfo: {
|
||||
username: '',
|
||||
password: '',
|
||||
nickName: '',
|
||||
headerImg: '',
|
||||
authorityId: ''
|
||||
},
|
||||
rules: {
|
||||
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
||||
password: [
|
||||
{ required: true, message: '请输入用户密码', trigger: 'blur' }
|
||||
],
|
||||
nickName: [
|
||||
{ required: true, message: '请输入用户昵称', trigger: 'blur' }
|
||||
],
|
||||
authorityId: [
|
||||
{ required: true, message: '请选择用户角色', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('user', ['token'])
|
||||
},
|
||||
methods: {
|
||||
async enterAddUserDialog() {
|
||||
this.$refs.userForm.validate(async valid => {
|
||||
if (valid) {
|
||||
const res = await register(this.userInfo)
|
||||
if (res.success) {
|
||||
this.$message({ type: 'success', message: '创建成功' })
|
||||
}
|
||||
await this.getTableData()
|
||||
this.closeAddUserDialog()
|
||||
}
|
||||
})
|
||||
},
|
||||
closeAddUserDialog() {
|
||||
this.userInfo = {
|
||||
username: '',
|
||||
password: '',
|
||||
nickName: '',
|
||||
headerImg: '',
|
||||
authorityId: ''
|
||||
}
|
||||
this.addUserDialog = false
|
||||
},
|
||||
handleAvatarSuccess(res) {
|
||||
this.userInfo.headerImg = res.data.file.url
|
||||
},
|
||||
addUser() {
|
||||
this.addUserDialog = true
|
||||
},
|
||||
async changeAuthority(row) {
|
||||
const res = await setUserAuthority({
|
||||
uuid: row.uuid,
|
||||
authorityId: row.authority.authorityId
|
||||
})
|
||||
if (res.success) {
|
||||
this.$message({ type: 'success', message: '角色设置成功' })
|
||||
}
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
const res = await getAuthorityList({ page: 1, pageSize: 999 })
|
||||
this.authOptions = res.data.list
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.button-box {
|
||||
padding: 10px 20px;
|
||||
.el-button {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.user-dialog {
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
border: 1px dashed #d9d9d9 !important;
|
||||
border-radius: 6px;
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
line-height: 178px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form :model="dialogMiddle" ref="fieldDialogFrom" label-width="120px" label-position="left" :rules="rules">
|
||||
<el-form-item label="Field名称" prop="fieldName">
|
||||
<el-col :span="6">
|
||||
<el-input v-model="dialogMiddle.fieldName" autocomplete="off"></el-input>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="FieldJSON" prop="fieldJson">
|
||||
<el-col :span="6">
|
||||
<el-input v-model="dialogMiddle.fieldJson" autocomplete="off"></el-input>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据库字段名" prop="columnName">
|
||||
<el-col :span="6">
|
||||
<el-input v-model="dialogMiddle.columnName" autocomplete="off"></el-input>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="Field数据类型" prop="fieldType">
|
||||
<el-col :span="8">
|
||||
<el-select v-model="dialogMiddle.fieldType" placeholder="请选择field数据类型">
|
||||
<el-option
|
||||
v-for="item in typeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name:"FieldDialog",
|
||||
props:{
|
||||
dialogMiddle:{
|
||||
type:Object,
|
||||
default:function(){
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
visible:false,
|
||||
typeOptions:[
|
||||
{
|
||||
label:"字符串",
|
||||
value:"string"
|
||||
},
|
||||
{
|
||||
label:"整型",
|
||||
value:"int"
|
||||
},
|
||||
{
|
||||
label:"布尔值",
|
||||
value:"bool"
|
||||
},
|
||||
{
|
||||
label:"浮点型",
|
||||
value:"float64"
|
||||
},
|
||||
{
|
||||
label:"时间",
|
||||
value:"time.Time"
|
||||
},
|
||||
],
|
||||
rules:{
|
||||
fieldName:[ { required: true, message: '请输入field英文名', trigger: 'blur' }],
|
||||
fieldJson:[ { required: true, message: '请输入field格式化json', trigger: 'blur' }],
|
||||
fieldType:[ { required: true, message: '请选择field数据类型', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 初始版本自动化代码工具 -->
|
||||
<el-form ref="autoCodeForm" :rules="rules" :model="form" label-width="120px" :inline="true">
|
||||
<el-form-item label="Struct名称" prop="structName">
|
||||
<el-input v-model="form.structName" placeholder="首字母自动转换大写"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Struct简称" prop="abbreviation">
|
||||
<el-input v-model="form.abbreviation"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Package名称" prop="packageName">
|
||||
<el-input v-model="form.packageName"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 组件列表 -->
|
||||
<div class="button-box clearflex">
|
||||
<el-button @click="editAndAddField()" type="primary">新增Field</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="form.fields"
|
||||
border stripe>
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序列"
|
||||
width="280">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="fieldName"
|
||||
label="Field名"
|
||||
width="280">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="fieldJson"
|
||||
label="FieldJson"
|
||||
width="280">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="fieldType"
|
||||
label="Field数据类型"
|
||||
width="280">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="primary" @click="editAndAddField(scope.row)">编辑</el-button>
|
||||
<el-popover
|
||||
placement="top"
|
||||
width="280"
|
||||
v-model="scope.row.visible">
|
||||
<p>这是一段内容这是一段内容确定删除吗?</p>
|
||||
<div style="text-align: right; margin: 0">
|
||||
<el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button>
|
||||
<el-button type="primary" size="mini" @click="deleteField(scope.$index)">确定</el-button>
|
||||
</div>
|
||||
<el-button type="danger" slot="reference">删除</el-button>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 组件列表 -->
|
||||
<div class="button-box clearflex">
|
||||
<el-button @click="enterForm" type="primary">生成代码包</el-button>
|
||||
</div>
|
||||
<!-- 组件弹窗 -->
|
||||
<el-dialog title="组件内容" :visible.sync="dialogFlag">
|
||||
<FieldDialog :dialogMiddle="dialogMiddle" ref="fieldDialog"/>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="closeDialog">取 消</el-button>
|
||||
<el-button type="primary" @click="enterDialog">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const fieldTemplate={
|
||||
fieldName:"",
|
||||
fieldType:"",
|
||||
fieldJson:"",
|
||||
columnName:"",
|
||||
}
|
||||
|
||||
import FieldDialog from "@/view/systemTools/autoCode/component/fieldDialog.vue"
|
||||
import {toUpperCase} from "@/utils/toUpperCase.js"
|
||||
import {createTemp} from "@/api/autoCode.js"
|
||||
export default {
|
||||
name:"autoCode",
|
||||
data(){
|
||||
return{
|
||||
addFlag:"",
|
||||
form:{
|
||||
structName:"",
|
||||
packageName:"",
|
||||
abbreviation:"",
|
||||
fields:[]
|
||||
},
|
||||
rules:{
|
||||
structName:[{required: true, message: '请输入结构体名称', trigger: 'blur'}],
|
||||
abbreviation:[{required: true, message: '请输入结构体简称', trigger: 'blur'}],
|
||||
packageName:[{required: true, message: '请输入包名称', trigger: 'blur'}]
|
||||
},
|
||||
dialogMiddle:{},
|
||||
bk:{},
|
||||
dialogFlag:false
|
||||
}
|
||||
},
|
||||
components:{
|
||||
FieldDialog
|
||||
},
|
||||
methods:{
|
||||
editAndAddField(item){
|
||||
this.dialogFlag = true
|
||||
if(item){
|
||||
this.addFlag="edit"
|
||||
this.bk=JSON.parse(JSON.stringify(item))
|
||||
this.dialogMiddle = item
|
||||
}else{
|
||||
this.addFlag="add"
|
||||
this.dialogMiddle = JSON.parse(JSON.stringify(fieldTemplate))
|
||||
}
|
||||
},
|
||||
enterDialog(){
|
||||
this.$refs.fieldDialog.$refs.fieldDialogFrom.validate((valid) => {
|
||||
if (valid) {
|
||||
this.dialogMiddle.fieldName = toUpperCase(this.dialogMiddle.fieldName)
|
||||
if(this.addFlag=="add"){
|
||||
this.form.fields.push(this.dialogMiddle)
|
||||
}
|
||||
this.dialogFlag = false
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
closeDialog(){
|
||||
if(this.addFlag=="edit"){
|
||||
this.dialogMiddle = this.bk
|
||||
}
|
||||
this.dialogFlag = false
|
||||
},
|
||||
deleteField(index){
|
||||
this.form.fields.splice(index,1)
|
||||
},
|
||||
async enterForm(){
|
||||
if(this.form.fields.length<=0){
|
||||
this.$message({
|
||||
type:"error",
|
||||
message:"请填写至少一个field"
|
||||
})
|
||||
return false
|
||||
}
|
||||
this.$refs.autoCodeForm.validate(async (valid) => {
|
||||
if (valid) {
|
||||
this.form.structName = toUpperCase(this.form.structName)
|
||||
const data = await createTemp(this.form)
|
||||
const blob = new Blob([data])
|
||||
const fileName = 'ginvueadmin.zip'
|
||||
if ('download' in document.createElement('a')) { // 不是IE浏览器
|
||||
let url = window.URL.createObjectURL(blob)
|
||||
let link = document.createElement('a')
|
||||
link.style.display = 'none'
|
||||
link.href = url
|
||||
link.setAttribute('download', fileName)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link) // 下载完成移除元素
|
||||
window.URL.revokeObjectURL(url) // 释放掉blob对象
|
||||
} else { // IE 10+
|
||||
window.navigator.msSaveBlob(blob, fileName)
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scope lang="scss">
|
||||
.button-box {
|
||||
padding: 10px 20px;
|
||||
.el-button {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<div style="height:80vh">
|
||||
<iframe width="100%" height="100%" src="http://127.0.0.1:8888/form-generator/#/" frameborder="0"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"FormGenerator"
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"System",
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form :model="config" label-width="100px" ref="form" class="system">
|
||||
<h2>系统配置</h2>
|
||||
<el-form-item label="多点登录拦截">
|
||||
<el-checkbox v-model="config.system.useMultipoint">开启</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item label="环境值">
|
||||
<el-input v-model="config.system.env"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="端口值">
|
||||
<el-input v-model="config.system.addr"></el-input>
|
||||
</el-form-item>
|
||||
<h2>jwt签名</h2>
|
||||
<el-form-item label="jwt签名">
|
||||
<el-input v-model="config.jwt.signingKey"></el-input>
|
||||
</el-form-item>
|
||||
<h2>casbin配置</h2>
|
||||
<el-form-item label="模型地址">
|
||||
<el-input v-model="config.casbinConfig.modelPath"></el-input>
|
||||
</el-form-item>
|
||||
<h2>mysql admin数据库配置</h2>
|
||||
<el-form-item label="username">
|
||||
<el-input v-model="config.mysqlAdmin.username"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="password">
|
||||
<el-input v-model="config.mysqlAdmin.password"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="path">
|
||||
<el-input v-model="config.mysqlAdmin.path"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="dbname">
|
||||
<el-input v-model="config.mysqlAdmin.dbname"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="config">
|
||||
<el-input v-model.number="config.mysqlAdmin.maxIdleConns"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="config">
|
||||
<el-input v-model.number="config.mysqlAdmin.maxOpenConns"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="config">
|
||||
<el-input v-model="config.mysqlAdmin.logMode"></el-input>
|
||||
</el-form-item>
|
||||
<h2>Redis admin数据库配置</h2>
|
||||
<el-form-item label="addr">
|
||||
<el-input v-model="config.redisAdmin.addr"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="password">
|
||||
<el-input v-model="config.redisAdmin.password"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="db">
|
||||
<el-input v-model="config.redisAdmin.db"></el-input>
|
||||
</el-form-item>
|
||||
<h2>七牛密钥配置</h2>
|
||||
<el-form-item label="accessKey">
|
||||
<el-input v-model="config.qiniu.accessKey"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="secretKey">
|
||||
<el-input v-model="config.qiniu.secretKey"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="update" type="primary">立即更新</el-button>
|
||||
<el-button @click="reload" type="primary">重启服务(开发中)</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<h2>验证码配置</h2>
|
||||
<el-form-item label="keyLong">
|
||||
<el-input v-model.number="config.captcha.keyLong"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="imgWidth">
|
||||
<el-input v-model.number="config.captcha.imgWidth"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="imgHeight">
|
||||
<el-input v-model.number="config.captcha.imgHeight"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="update" type="primary">立即更新</el-button>
|
||||
<el-button @click="reload" type="primary">重启服务(开发中)</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<h2>日志配置</h2>
|
||||
<el-form-item label="prefix">
|
||||
<el-input v-model.number="config.log.prefix"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="logFile">
|
||||
<el-checkbox v-model="config.log.logFile"></el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="update" type="primary">立即更新</el-button>
|
||||
<el-button @click="reload" type="primary">重启服务(开发中)</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSystemConfig, setSystemConfig } from '@/api/system'
|
||||
export default {
|
||||
name: 'Config',
|
||||
data() {
|
||||
return {
|
||||
config: {
|
||||
system: {},
|
||||
jwt: {},
|
||||
casbinConfig: {},
|
||||
mysqlAdmin: {},
|
||||
redisAdmin: {},
|
||||
qiniu: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
await this.initForm()
|
||||
},
|
||||
methods: {
|
||||
async initForm() {
|
||||
const res = await getSystemConfig()
|
||||
if (res.success) {
|
||||
this.config = res.data.config
|
||||
}
|
||||
},
|
||||
reload() {},
|
||||
async update() {
|
||||
const res = await setSystemConfig({ config: this.config })
|
||||
if (res.success) {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '配置文件设置成功'
|
||||
})
|
||||
await this.initForm()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
h2 {
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
font-size: 16px;
|
||||
box-shadow:-4px 1px 3px 0px #e7e8e8
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<div>
|
||||
动态路由测试
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"Test"
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"Workflow",
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form :model="form" label-width="100px" ref="form">
|
||||
<el-form-item label="工作流名称">
|
||||
<el-input type="text" v-model="form.workflowNickName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="工作流英文id">
|
||||
<el-input type="text" v-model="form.workflowName"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="工作流描述">
|
||||
<el-input type="text" v-model="form.workflowDescription"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button @click="createWorkflowStep" class="fl-right mg" type="primary">新增</el-button>
|
||||
<el-table :data="form.workflowStep" border style="width: 100%">
|
||||
<el-table-column label="是否是完结流节点" prop="isEnd">
|
||||
<template slot-scope="scope">
|
||||
<el-select placeholder="请选择" v-model="scope.row.isEnd">
|
||||
<el-option
|
||||
:key="key"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
v-for="(item,key) in options"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否是开始流节点" prop="isStrat">
|
||||
<template slot-scope="scope">
|
||||
<el-select placeholder="请选择" v-model="scope.row.isStrat">
|
||||
<el-option
|
||||
:key="key"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
v-for="(item,key) in options"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作者级别id" prop="stepAuthorityID">
|
||||
<template slot-scope="scope">
|
||||
<el-input placeholder="请输入" type="text" v-model="scope.row.stepAuthorityID"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="工作流名称" prop="stepName">
|
||||
<template slot-scope="scope">
|
||||
<el-input placeholder="请输入" type="text" v-model="scope.row.stepName"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="步骤id" prop="stepNo">
|
||||
<template slot-scope="scope">
|
||||
<el-input placeholder="请输入" type="text" v-model="scope.row.stepNo"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-button @click="submit" type="primary" class="fl-right mg">提交</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createWorkFlow } from '@/api/workflow'
|
||||
export default {
|
||||
name: 'Workflow',
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
workflowName: '',
|
||||
workflowDescription: '',
|
||||
workflowNickName: '',
|
||||
workflowStep: [
|
||||
{
|
||||
isEnd: false,
|
||||
isStrat: true,
|
||||
stepAuthorityID: '',
|
||||
stepName: '',
|
||||
stepNo: ''
|
||||
}
|
||||
]
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: '是',
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: '否',
|
||||
value: false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
createWorkflowStep() {
|
||||
this.form.workflowStep.push({
|
||||
isEnd: false,
|
||||
isStrat: false,
|
||||
stepAuthorityID: '',
|
||||
stepName: '',
|
||||
stepNo: ''
|
||||
})
|
||||
},
|
||||
async submit() {
|
||||
const res = await createWorkFlow(this.form)
|
||||
if(res.success){
|
||||
this.$message({
|
||||
message:"创建成功",
|
||||
type:"success"
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
||||
Reference in New Issue
Block a user