cellsysArt/components/icon/IconSelect.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>