460 lines
13 KiB
Vue
460 lines
13 KiB
Vue
<template>
|
|
<div class="icon-wrap">
|
|
<div
|
|
class="preview"
|
|
v-show="previewIcon.data">
|
|
<svg-icon
|
|
class="preview__icon"
|
|
:icon="previewIcon"></svg-icon>
|
|
<span class="preview__name">{{ previewIcon.name }}</span>
|
|
</div>
|
|
<div class="icon-btn-wrap">
|
|
<el-button
|
|
type="primary"
|
|
@click="openIconList">
|
|
选择图标
|
|
</el-button>
|
|
</div>
|
|
<el-dialog
|
|
title="选择图标"
|
|
width="60%"
|
|
v-model="iconDialog.visible"
|
|
:close-on-click-modal="false"
|
|
:fullscreen="GLOBAL.isMobile"
|
|
:append-to-body="true"
|
|
@close="onCloseDialog">
|
|
<div
|
|
class="item-icon"
|
|
style="">
|
|
<el-scrollbar
|
|
class="scrollbar"
|
|
wrap-class="scrollbar-wrapper"
|
|
style="width: 145px; border-right: 2px solid #ecececec">
|
|
<ul
|
|
class="icon-type-list"
|
|
ref="iconTypeListUl">
|
|
<li
|
|
class="type-item"
|
|
:class="[
|
|
{ isActive: activeTypeId === item.id },
|
|
{ themeBgColor: activeTypeId === item.id },
|
|
]"
|
|
v-for="item in iconTypeList"
|
|
:key="item.id"
|
|
:title="item.name"
|
|
@click="chooseIconType(item, $event)">
|
|
<span>{{ item.name }}</span>
|
|
</li>
|
|
</ul>
|
|
</el-scrollbar>
|
|
<el-scrollbar
|
|
v-loading="loading"
|
|
class="scrollbar"
|
|
ref="iconScrollbar"
|
|
wrap-class="scrollbar-wrapper"
|
|
style="width: 100%">
|
|
<span
|
|
v-if="!iconList || iconList.length < 1"
|
|
style="
|
|
display: block;
|
|
height: 60px;
|
|
line-height: 60px;
|
|
font-size: 14px;
|
|
margin: 10px auto;
|
|
text-align: center;
|
|
color: #909399;
|
|
">
|
|
没有图标
|
|
</span>
|
|
<ul
|
|
class="icon-list"
|
|
ref="iconListUl">
|
|
<li
|
|
class="icon-item"
|
|
:class="[
|
|
{ active: activeName === item.name },
|
|
{ themeBorderColor: activeName === item.name },
|
|
]"
|
|
v-for="item in iconList"
|
|
:key="item.id"
|
|
:title="item.name"
|
|
@click="chooseIcon(item, $event)"
|
|
@dblclick="onDBClick(item, $event)">
|
|
<div class="icon-twrap">
|
|
<svg-icon
|
|
style="font-size: 40px"
|
|
:icon="item"></svg-icon>
|
|
</div>
|
|
<span class="icon-name">{{ item.name }}</span>
|
|
</li>
|
|
</ul>
|
|
</el-scrollbar>
|
|
</div>
|
|
<template #footer>
|
|
<div class="dialog-footer">
|
|
<el-input
|
|
v-if="!GLOBAL.isMobile"
|
|
v-model="queryIcon"
|
|
placeholder="搜索图标"
|
|
class="fl icon-search"
|
|
prefix-icon="Search"
|
|
clearable
|
|
:validate-event="false"
|
|
@change="queryIconList()"></el-input>
|
|
<el-button @click="clickCancel">取消</el-button>
|
|
<el-button
|
|
type="primary"
|
|
@click="confirmIcon">
|
|
确定
|
|
</el-button>
|
|
</div>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapGetters } from 'vuex';
|
|
import SvgIcon from '@/components/icon/SvgIcon.vue';
|
|
import CellsysIcon from '@airkoon/cellsys/cellsysIcon.js';
|
|
|
|
export default {
|
|
name: 'IconSelect',
|
|
components: { SvgIcon },
|
|
model: {
|
|
prop: 'previewIcon',
|
|
event: 'confirm',
|
|
},
|
|
// props: {
|
|
// previewIcon: {
|
|
// type: Object,
|
|
// default: function () {
|
|
// return {};
|
|
// },
|
|
// },
|
|
// },
|
|
props: {
|
|
// 使用 v-model 绑定的 prop 名称在 Vue 3 中为 modelValue
|
|
modelValue: {
|
|
type: Object,
|
|
default: function () {
|
|
return {};
|
|
},
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
iconDialog: {
|
|
visible: false,
|
|
},
|
|
activeName: null,
|
|
activeTypeId: 1,
|
|
icon: new CellsysIcon(),
|
|
oldIcon: null,
|
|
iconList: [],
|
|
iconTypeList: [],
|
|
loading: false,
|
|
queryIcon: '', //icon名字查询条件
|
|
};
|
|
},
|
|
computed: {
|
|
...mapGetters(['cellsysOrg']),
|
|
// 将 modelValue 映射为 previewIcon 以便使用
|
|
previewIcon() {
|
|
return this.modelValue;
|
|
},
|
|
},
|
|
mounted() {
|
|
this.icon = this.previewIcon ? new CellsysIcon(this.previewIcon) : null;
|
|
},
|
|
methods: {
|
|
openIconList: function () {
|
|
let that = this;
|
|
that.cellsysOrg
|
|
.queryIconTypeList()
|
|
.then((res) => {
|
|
that.iconTypeList = res.data;
|
|
if (that.iconTypeList && that.iconTypeList.length > 0) {
|
|
if (that.previewIcon && that.previewIcon.type) {
|
|
that.activeTypeId = this.previewIcon.type;
|
|
that.activeName = this.previewIcon.name;
|
|
} else {
|
|
that.activeTypeId = that.iconTypeList[0].id;
|
|
that.activeName = '坐标';
|
|
}
|
|
that.queryIconListByType(that.activeName);
|
|
}
|
|
})
|
|
.finally(() => {
|
|
const ul = this.$refs.iconTypeListUl;
|
|
const item = ul.querySelector('li.isActive');
|
|
if (item) {
|
|
item.scrollIntoView(true);
|
|
}
|
|
});
|
|
this.iconDialog.visible = true;
|
|
},
|
|
chooseIconType: function (item, event) {
|
|
let vm = this;
|
|
this.activeTypeId = item.id;
|
|
this.queryIconListByType();
|
|
},
|
|
chooseIcon: function (icon, event) {
|
|
this.activeName = icon.name;
|
|
this.icon = icon;
|
|
},
|
|
onDBClick(icon, event) {
|
|
this.activeName = icon.name;
|
|
this.icon = icon;
|
|
this.confirmIcon();
|
|
},
|
|
confirmIcon: function () {
|
|
if (this.icon) {
|
|
this.$emit('update:modelValue', this.icon);
|
|
this.$emit('confirm', this.icon);
|
|
this.iconDialog.visible = false;
|
|
} else {
|
|
this.$message.error('请选择图标');
|
|
}
|
|
},
|
|
// 通过图标类型查询图标列表
|
|
queryIconListByType: function (name) {
|
|
this.loading = true;
|
|
let filters = [];
|
|
filters.push({ field: 'type', operator: '=', value: this.activeTypeId });
|
|
this.cellsysOrg
|
|
.queryIconList(filters)
|
|
.then((res) => {
|
|
this.iconList = res.data.map((o) => {
|
|
return new CellsysIcon(o);
|
|
});
|
|
//判断默认图标
|
|
this.icon = name ? this.iconList.find((o) => o.name === name) : null;
|
|
|
|
// if (this.iconDialog.visible && this.$refs.iconScrollbar) {
|
|
// this.$nextTick(() => {
|
|
// this.$refs.iconScrollbar.update();
|
|
// this.$refs.iconScrollbar.wrap.scrollTop = 0;
|
|
// });
|
|
// }
|
|
})
|
|
.finally(() => {
|
|
this.loading = false;
|
|
const ul = this.$refs.iconListUl;
|
|
console.log(ul);
|
|
const item = ul.querySelector('li.active');
|
|
if (item) {
|
|
item.scrollIntoView(true);
|
|
}
|
|
});
|
|
},
|
|
// 查询图标列表
|
|
queryIconList: function () {
|
|
this.activeName = null;
|
|
if (this.queryIcon) {
|
|
this.loading = true;
|
|
let filters = [];
|
|
filters.push({ field: 'name', operator: 'like', value: this.queryIcon });
|
|
filters.push({
|
|
field: 'tags',
|
|
operator: 'like',
|
|
value: this.queryIcon,
|
|
type: 'or',
|
|
});
|
|
this.cellsysOrg
|
|
.queryIconList(filters)
|
|
.then((res) => {
|
|
this.iconList = res.data.map((o) => {
|
|
return new CellsysIcon(o);
|
|
});
|
|
if (this.iconDialog.visible) {
|
|
this.$nextTick(() => {
|
|
this.$refs.iconScrollbar.update();
|
|
this.$refs.iconScrollbar.wrap.scrollTop = 0;
|
|
});
|
|
}
|
|
})
|
|
.finally(() => {
|
|
this.loading = false;
|
|
});
|
|
} else {
|
|
this.queryIconListByType();
|
|
}
|
|
},
|
|
onCloseDialog() {
|
|
if (this.queryIcon) {
|
|
this.queryIcon = null;
|
|
}
|
|
this.activeName = null;
|
|
this.iconList = [];
|
|
},
|
|
clickCancel() {
|
|
this.iconDialog.visible = false;
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
:deep(.scrollbar-wrapper) {
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
.scrollbar {
|
|
height: 100%;
|
|
}
|
|
|
|
.item-icon {
|
|
height: 540px;
|
|
display: flex;
|
|
}
|
|
|
|
.icon-wrap {
|
|
height: 100%;
|
|
display: flex;
|
|
}
|
|
|
|
.icon-btn-wrap {
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.icon-type-list {
|
|
width: 120px;
|
|
}
|
|
|
|
.icon-type-list li:hover:not(.isActive) {
|
|
background: #f7f7fc;
|
|
}
|
|
|
|
.icon-type-list .type-item {
|
|
cursor: pointer;
|
|
width: 115px;
|
|
height: 41px;
|
|
line-height: 41px;
|
|
text-align: center;
|
|
color: black;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.isActive {
|
|
color: white !important;
|
|
}
|
|
|
|
.preview {
|
|
box-sizing: border-box;
|
|
height: 32px;
|
|
line-height: 32px;
|
|
margin-right: 20px;
|
|
min-width: 70px;
|
|
}
|
|
|
|
.preview__icon {
|
|
font-size: 32px;
|
|
}
|
|
|
|
.preview__name {
|
|
margin-left: 8px;
|
|
vertical-align: middle;
|
|
display: inline-block;
|
|
position: relative;
|
|
font-size: 12px;
|
|
font-weight: normal;
|
|
opacity: 0.7;
|
|
color: #232323;
|
|
}
|
|
|
|
.icon-search {
|
|
position: relative;
|
|
top: -625px;
|
|
left: 125px;
|
|
width: 215px;
|
|
}
|
|
|
|
/** 图标样式 */
|
|
.icon-list {
|
|
padding: 1px 10px;
|
|
}
|
|
|
|
.icon-list .icon-item {
|
|
margin: 1px;
|
|
color: #666;
|
|
float: left;
|
|
width: 100px;
|
|
height: 105px;
|
|
text-align: center;
|
|
position: relative;
|
|
overflow: visible;
|
|
border: 1px dashed transparent;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.icon-item.active {
|
|
border: 1px solid #4285f4;
|
|
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.8), -1px -1px 4px rgba(0, 0, 0, 0.8);
|
|
}
|
|
|
|
.icon-list .icon-item .icon-twrap {
|
|
display: inline-block;
|
|
margin-top: 18px;
|
|
}
|
|
|
|
.icon-list .icon-item .icon-name {
|
|
display: block;
|
|
height: 20px;
|
|
line-height: 20px;
|
|
color: #666;
|
|
font-size: 14px;
|
|
margin: 15px 4px 0px 5px;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
text-align: center;
|
|
}
|
|
|
|
@media screen and (max-width: 750px) {
|
|
.item-icon {
|
|
height: 100%;
|
|
}
|
|
|
|
.icon-list .icon-item {
|
|
width: 5rem;
|
|
height: 5rem;
|
|
}
|
|
|
|
.icon-list .icon-item .icon-twrap {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.icon-list .icon-item .icon-name {
|
|
margin: 0;
|
|
}
|
|
|
|
.icon-search {
|
|
position: absolute;
|
|
top: 15px;
|
|
left: 120px;
|
|
}
|
|
}
|
|
|
|
@media screen and (max-height: 900px) {
|
|
.item-icon {
|
|
min-height: 49vh;
|
|
max-height: 80vh;
|
|
}
|
|
|
|
:deep(.el-dialog__body) {
|
|
padding: 0;
|
|
}
|
|
|
|
.icon-search {
|
|
position: absolute;
|
|
top: 10px;
|
|
left: 130px;
|
|
}
|
|
}
|
|
</style>
|