<template>
|
<el-container>
|
<el-main>
|
<basic-container>
|
<div style="display: flex;justify-content: space-between;flex-wrap: wrap">
|
<div class="tag-group">
|
<span class="tag-group__title" v-if="types.length>0">分组</span>
|
<el-tag
|
v-for="item in types"
|
:key="item.key"
|
:type="checkedTypes.includes(item.key)?'success':'info'" size="small"
|
effect="plain" @click="changeType(item.key)">
|
{{ item.value }}
|
</el-tag>
|
</div>
|
<avue-input v-model="searchText" @change="handleSearch" placeholder="查询" size="mini" prefixIcon="el-icon-search" style="width: 300px;max-width: 30%"></avue-input>
|
</div>
|
<div style="height: calc(100vh - 190px)">
|
<div>
|
<el-button v-if="permissionList.addBtn" class="button-custom-icon" type="primary" size="small" @click="addHandler">
|
<icon-show :name="permissionList.addBtn.source"></icon-show>
|
添加
|
</el-button>
|
<el-button v-if="permissionList.uploadBtn" class="button-custom-icon" type="primary" size="small" @click="uploadHandler">
|
<icon-show :name="permissionList.uploadBtn.source"></icon-show>
|
上传
|
</el-button>
|
</div>
|
|
<el-tabs v-model="activeName" @tab-click="handleClick">
|
<el-tab-pane v-for="item in iconList" :label="item.lable" :name="item.lable" style="height: calc(100vh - 270px);overflow: auto ">
|
<div class="iconList">
|
<div class="iconItem" v-for="svg in item.list"
|
:data-value="svg.name" v-right-click="{action:checkSvg,data:svg}">
|
<div class="svgContent" v-html="svg.content"></div>
|
<span>{{svg.name.split(':')[1]}}</span>
|
</div>
|
</div>
|
<div v-if="menuVisible" class="el-cascader-panel is-bordered iconList__menu" :style="menuPosition">
|
<div class="iconList__item" @click="editHandler">编 辑</div>
|
<div class="iconList__item" @click="delHandler">删 除</div>
|
</div>
|
</el-tab-pane>
|
</el-tabs>
|
</div>
|
<!-- 上传 -->
|
<el-dialog
|
v-dialogDrag
|
title="上传图标"
|
:visible.sync="visible"
|
append-to-body="true"
|
class="avue-dialog"
|
width="600px"
|
@close="visibleCloseHandler"
|
>
|
<avue-form ref="form" :option="option" v-model="form" :upload-after="uploadAfter" style="margin-bottom: 0;height:90px;overflow: hidden"> </avue-form>
|
<pre style="font-size: 12px;color: #909399;margin-top: 0;padding:5px;background-color: #F5F7FA">上传文件为json文件,示例如下
|
[{
|
"name": "图标库名:图标名称",
|
"svg": "svg的html代码"
|
},
|
{
|
"name": "图标库名:图标名称",
|
"svg": "svg的html代码"
|
}]
|
文件内容须严格按照示例格式,name为图标库名+图标名称,以“:”分隔,svg为图标html代码</pre>
|
</el-dialog>
|
<!-- 添加、修改 -->
|
<el-dialog
|
v-dialogDrag
|
:title="editType=='add'?'添加图标':'修改图标'"
|
:visible.sync="editVisible"
|
append-to-body="true"
|
class="avue-dialog"
|
width="500px"
|
@close="closeHandler"
|
>
|
<avue-form ref="editForm" :option="editOption" v-model="editForm"> </avue-form>
|
<span slot="footer" class="dialog-footer">
|
<el-button size="small" type="primary" @click="editSaveHandler">确 定</el-button>
|
<el-button size="small" @click="closeHandler">取 消</el-button>
|
</span>
|
</el-dialog>
|
</basic-container>
|
</el-main>
|
</el-container>
|
</template>
|
|
<script>
|
import {getIcons,addIcon,updateIcon,deleteIcon} from "@/api/UI/Icons";
|
import {getDicts} from "@/api/system/dict";
|
import {validatenull} from "@/util/validate";
|
import {getStore} from "@/util/store";
|
import store from "@/store";
|
import {getToken} from "@/util/auth";
|
import {mapGetters} from "vuex";
|
|
export default {
|
name: "index",
|
directives: {
|
rightClick: {
|
bind(el, binding) {
|
el.oncontextmenu = (e) => {
|
e.preventDefault();
|
const menu = binding.value;
|
menu.action(e,menu.data);
|
};
|
}
|
}
|
},
|
data() {
|
return {
|
types: [],
|
checkedTypes:[],
|
searchText:'',
|
activeName:'',
|
allIconList:[],
|
iconList:[],
|
visible: false,
|
checkItem:null,
|
option: {
|
labelWidth: 80,
|
submitBtn:false,
|
emptyBtn:false,
|
column: [{
|
label: '分组',
|
prop: 'groups',
|
type: 'select',
|
span: 24,
|
multiple:true,
|
dicData:[],
|
props:{
|
label:'value',
|
value:'key'
|
}
|
}, {
|
label: "附件上传",
|
prop: "file",
|
type: "upload",
|
dataType: "object",
|
accept:'.json',
|
action:"api/webIconController/importIcon",
|
data:{},
|
headers:this.uploadHeaders,
|
span: 24,
|
}
|
]
|
},
|
form:{
|
type:'svg',
|
groups:[],
|
file:null
|
},
|
editType:'edit',
|
editVisible:false,
|
editOption:{
|
labelWidth: 90,
|
submitBtn:false,
|
emptyBtn:false,
|
column: [{
|
label: '图标库名',
|
prop: 'libname',
|
type: 'input',
|
disabled:true,
|
span: 24,
|
rules: [{
|
required: true,
|
message: "请输入图标库名",
|
trigger: "blur"
|
}]
|
},{
|
label: '名称',
|
prop: 'iconname',
|
type: 'input',
|
disabled:true,
|
span: 24,
|
rules: [{
|
required: true,
|
message: "请输入图标名称",
|
trigger: "blur"
|
}]
|
},{
|
label: '分组',
|
prop: 'groups',
|
type: 'select',
|
span: 24,
|
multiple:true,
|
dicData:[],
|
props:{
|
label:'value',
|
value:'key'
|
}
|
}, {
|
label: "图标代码",
|
prop: "content",
|
type: "textarea",
|
span: 24,
|
placeholder:'请输入图标html代码,格式示例<svg xmlns=\"http://www.w3.org/2000/svg\" ></svg>',
|
rules: [{
|
required: true,
|
message: "请输入图标svg代码",
|
trigger: "blur"
|
}]
|
}]
|
},
|
editForm:{
|
oid:'',
|
libname:'',
|
iconname:'',
|
content:''
|
},
|
menuVisible:false,
|
menuPosition: {
|
top: 0,
|
left: 0
|
}
|
}
|
},
|
computed: {
|
uploadHeaders() {
|
return {
|
"Authorizationtoken":getToken(),
|
};
|
},
|
...mapGetters(["permission"]),
|
permissionList() {
|
return {
|
addBtn: this.vaildData(this.permission[this.$route.query.id].ADD, false),
|
uploadBtn: this.vaildData(this.permission[this.$route.query.id].UPLOAD, false),
|
};
|
},
|
},
|
watch:{
|
'form.groups'(val){
|
this.option.column[1].data={
|
type:'svg',
|
groups:val
|
}
|
}
|
},
|
created() {
|
this.getGroups();
|
this.initList();
|
},
|
methods:{
|
getGroups() {
|
getDicts('EnumIconGroups').then(res => {
|
if (res.data.success) {
|
this.types = res.data.obj;
|
this.option.column[0].dicData = res.data.obj;
|
this.editOption.column[2].dicData =res.data.obj;
|
} else {
|
this.$message.error(res.data.msg);
|
}
|
})
|
},
|
initList(reload){
|
if(reload) {
|
getIcons().then(res => {
|
if (res.data.success) {
|
this.iconList = res.data.data;
|
this.allIconList = this.iconList;
|
store.dispatch("setIcons", this.iconList);
|
if (this.iconList.length > 0) {
|
this.activeName = this.iconList[0].lable;
|
}
|
} else {
|
this.$message.error(res.data.msg);
|
}
|
})
|
|
return;
|
}
|
if (!validatenull(this.$store.state.icons)) {
|
this.iconList = this.$store.state.icons;
|
} else {
|
this.iconList = getStore({ name:'icons'});
|
}
|
this.allIconList=this.iconList;
|
if(this.iconList && this.iconList.length>0){
|
this.activeName=this.iconList[0].lable;
|
}else {
|
getIcons().then(res => {
|
if (res.data.success) {
|
this.iconList = [{
|
lable: 'iconoir',
|
list: [{
|
oid: '',
|
groups: '1',
|
"name": "iconoir:accessibility",
|
"content": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\"><path d=\"M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2S2 6.477 2 12s4.477 10 10 10M7 9l5 1m5-1l-5 1m0 0v3m0 0l-2 5m2-5l2 5\"/><path fill=\"currentColor\" d=\"M12 7a.5.5 0 1 1 0-1a.5.5 0 0 1 0 1\"/></g></svg>"
|
}]
|
}]
|
this.iconList = res.data.data;
|
this.allIconList = this.iconList;
|
store.dispatch("setIcons", this.iconList);
|
if (this.iconList.length > 0) {
|
this.activeName = this.iconList[0].lable;
|
}
|
} else {
|
this.$message.error(res.data.msg);
|
}
|
})
|
}
|
},
|
changeType(type){
|
if(this.checkedTypes.includes(type)){
|
this.checkedTypes=this.checkedTypes.filter(item=> item!=type)
|
}else {
|
this.checkedTypes.push(type)
|
}
|
//按照分类过滤图标
|
if(this.checkedTypes.length==0){
|
this.iconList=this.allIconList
|
}else{
|
const checkedTypes=JSON.stringify(this.checkedTypes);
|
const iconList=[];
|
this.allIconList.forEach(item=>{
|
iconList.push({
|
lable:item.lable,
|
list:item.list.filter(iconitem=> {
|
return checkedTypes.indexOf(iconitem.groups)!=-1;
|
})
|
})
|
})
|
this.iconList=iconList;
|
}
|
this.activeName=this.iconList[0].lable;
|
},
|
handleSearch(data){
|
if(data.value==''){
|
this.iconList=this.allIconList;
|
}
|
let iconList=[]
|
this.allIconList.forEach(item=> {
|
iconList.push({
|
lable:item.lable,
|
list: item.list.filter(iconItem=>{
|
return iconItem.name.replace(item.lable,'').indexOf(data.value)!=-1;
|
})
|
})
|
})
|
this.iconList=iconList;
|
},
|
handleClick(tab, event){
|
|
},
|
uploadHandler(){
|
this.visible = true;
|
},
|
//上传后
|
uploadAfter(res,done){
|
if (res.success) {
|
this.$message.success(res.msg);
|
this.initList(true);
|
this.visibleCloseHandler();
|
}else {
|
this.$message.error(res.msg);
|
}
|
done();
|
},
|
// 关闭对话框
|
visibleCloseHandler() {
|
const form = {
|
type:'svg',
|
groups:[],
|
file:null
|
}
|
this.form = form;
|
this.visible = false;
|
this.$refs.form.clearValidate();
|
},
|
checkSvg(event,svgObj){
|
this.checkItem=svgObj;
|
// 设置菜单可见
|
this.menuVisible = true;
|
this.menuPosition.top = `${event.clientY}px`;
|
this.menuPosition.left = `${event.clientX}px`;
|
document.addEventListener('click',()=>{
|
this.menuVisible=false;
|
})
|
},
|
// 上传保存
|
uploadSaveHandler() {
|
this.$refs.form.validate((valid,done) => {
|
if (valid) {
|
done()
|
addIcon(this.form).then(res => {
|
if (res.data.code === 200) {
|
this.$message.success(res.data.msg);
|
this.initList(true);
|
done();
|
this.visibleCloseHandler();
|
} else {
|
this.$message.error(res.data.msg);
|
}
|
})
|
} else {
|
return false;
|
}
|
});
|
},
|
addHandler(){
|
this.editOption.column[0].disabled=false;
|
this.editOption.column[1].disabled=false;
|
this.editType='add';
|
this.editVisible=true;
|
},
|
editHandler(){
|
this.editType='edit';
|
this.editOption.column[0].disabled=true;
|
this.editOption.column[1].disabled=true;
|
this.editForm=this.checkItem;
|
this.editForm.libname=this.checkItem.name.split(':')[0]
|
this.editForm.iconname=this.checkItem.name.split(':')[1]
|
this.editVisible=true;
|
},
|
editSaveHandler(){
|
this.$refs.editForm.validate((valid,done) => {
|
if (valid) {
|
done()
|
this.editForm.name= this.editForm.libname+':'+ this.editForm.iconname;
|
if(this.editType=='edit'){
|
updateIcon(this.editForm).then(res => {
|
if (res.data.code === 200) {
|
this.$message.success(res.data.msg);
|
this.initList(true);
|
done();
|
this.closeHandler();
|
} else {
|
this.$message.error(res.data.msg);
|
}
|
})
|
}else {
|
addIcon(this.editForm).then(res => {
|
if (res.data.code === 200) {
|
this.$message.success(res.data.msg);
|
this.initList(true);
|
done();
|
this.closeHandler();
|
} else {
|
this.$message.error(res.data.msg);
|
}
|
})
|
}
|
} else {
|
return false;
|
}
|
});
|
},
|
closeHandler(){
|
this.editForm={
|
type:'svg',
|
oid:'',
|
libname:'',
|
iconname:'',
|
groups:[],
|
content:''
|
};
|
this.editOption.column[0].disabled=false;
|
this.editOption.column[1].disabled=false;
|
this.editVisible=false;
|
this.$refs.editForm.clearValidate();
|
},
|
delHandler(){
|
this.$confirm('您确定要删除该图标吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
const {name,oid} = this.checkItem;
|
const obj = {name,oid};
|
deleteIcon(obj).then(res => {
|
if (res.data.code === 200) {
|
this.$message.success(res.data.msg);
|
this.initList(true);
|
}
|
})
|
}).catch(() => {
|
this.$message({
|
type: 'info',
|
message: '已取消删除'
|
});
|
});
|
}
|
}
|
}
|
</script>
|
|
<style scoped lang="scss">
|
::v-deep{
|
svg{
|
font-size: inherit;
|
height: 100%;
|
width:100%;
|
}
|
}
|
.tag-group{font-size: 14px;}
|
.el-tag{
|
margin: 0 0 10px 10px;
|
cursor: pointer;
|
}
|
.iconList{
|
display: flex;
|
justify-content: flex-start;
|
flex-wrap: wrap;
|
}
|
.iconList .iconItem{
|
width: 85px;
|
margin: 6px 5px 10px 5px;
|
text-align: center;
|
}
|
.iconList .iconItem .svgContent{
|
font-size: 24px;
|
width: 24px;
|
height: 24px;
|
margin: 0 auto;
|
}
|
.iconList .iconItem .svgContent:hover{
|
transform: scale(1.5);
|
}
|
.iconList .iconItem span{
|
font-size: 12px;
|
}
|
.iconList__menu{
|
width: 150px;
|
position: fixed;
|
z-index: 1024;
|
flex-wrap: wrap;
|
background-color: #fff;
|
}
|
.iconList__item {
|
height: 34px;
|
line-height: 34px;
|
outline: 0;
|
padding: 0 10px;
|
white-space: nowrap;
|
text-overflow: ellipsis;
|
width: 100%;
|
color: #666;
|
}
|
.iconList__item:hover {
|
cursor: pointer;
|
color: #409eff
|
}
|
</style>
|