feat(视图): 色彩地图增加标记功能

This commit is contained in:
fit2cloud-chenyw
2022-12-15 14:01:28 +08:00
parent acd771cfd0
commit 4fa41d8676
60 changed files with 2534 additions and 18 deletions

View File

@@ -0,0 +1,86 @@
<template>
<i
v-if="fontClass"
:class="iconName"
@click="click(iconName,$event)"
/>
<svg
v-else-if="svg"
:class="svgClass"
aria-hidden="true"
@click="click(iconName,$event)"
>
<use :xlink:href="iconName" />
</svg>
<div
v-else-if="isExternal"
:style="styleExternalIcon"
:class="className"
class="icon external-icon"
@click="click(iconName,$event)"
/>
</template>
<script>
import { isExternal } from '../utils/index'
export default {
name: 'EIcon',
props: {
iconName: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
fontClass() {
return this.iconName && this.iconName.trim().length > 2 && (!isExternal(this.iconName) && !this.iconName.startsWith('#'))
},
svg() {
return this.iconName && this.iconName.trim().length > 2 && (!isExternal(this.iconName) && this.iconName.startsWith('#'))
},
isExternal() {
return isExternal(this.iconName)
},
svgClass() {
if (this.className) {
return 'icon ' + this.className
} else {
return 'icon'
}
},
styleExternalIcon() {
return {
'background-image': `url(${this.iconName})`,
'background-repeat': 'no-repeat',
'background-size': '100% 100%',
'-moz-background-size': '100% 100%'
}
}
},
methods: {
click(iconName, event) {
if (event) event.preventDefault()
this.$emit('click', iconName)
}
}
}
</script>
<style scoped>
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.external-icon {
display: inline-block;
}
</style>

View File

@@ -0,0 +1 @@
export default ['xianxingbenzitubiao1', 'xianxinganquansuotubiao', 'xianxingbenzitubiao2', 'xianxingdianzantubiao', 'xianxingdiannaotubiao', 'xianxingjishibentubiao', 'xianxingdianhuatubiao', 'xianxinghuishouzhantubiao', 'xianxingWIFItubiao', 'xianxingduihuakuangtubiao', 'xianxinglajitongtubiao', 'xianxingjiangpaitubiao2', 'xianxingjiaoyoutubiao', 'xianxingquerentubiao', 'xianxingrenwutubiao', 'xianxingjiangpaitubiao1', 'xianxingshoujitubiao', 'xianxinglianxirentubiao', 'xianxingrenyuantubiao', 'xianxinggongjutubiao', 'xianxingshenfentubiao', 'xianxingxiangjitubiao', 'xianxingwendatubiao', 'xianxingyanjingtubiao', 'xianxingxinxitubiao', 'xianxingxinjiantubiao', 'xianxingtudingtubiao', 'xianxingshijiantubiao', 'xianxingqianbaotubiao', 'xianxingtupiantubiao', 'xianxingzhifubaotubiao', 'xianxingyoujiantubiao', 'xianxingzhifeijitubiao', 'xianxingyuantubiao', 'xianxingxiangfatubiao', 'diannao-01', 'jiaojuan-01', 'shuji-01', 'gujianzhu-01', 'simiao-01', 'yundong-yumaoqiu', 'sanjiaojia-01', 'zhaoxiangji-01', 'shuihu-01', 'yumaopai-01', 'yanjing-01', 'chalaoban-01', 'shouji-01', 'yinzhang-01', 'xiangyan-01', 'guangpan-01', 'kafei-01', 'erji-01', 'foling-01', 'xiong-01', 'bingxiang', 'diannao', 'chufangcheng', 'biludianshi', 'dayinji', 'guangpan', 'jiashiqi', 'fengshan', 'kongtiao', 'dianfanbao', 'fengrenji', 'dianzicheng', 'mensuo', 'shexiangji', 'saodijiqiren', 'lvshuiji', 'shuzhuodeng', 'kafeiji', 'jisuanqi', 'xiyiji', 'shexiangtou'].map(s => 'eiconfont e-icon-' + s)

View File

@@ -0,0 +1 @@
export default ['platform-eleme', 'eleme', 'delete-solid', 'delete', 's-tools', 'setting', 'user-solid', 'user', 'phone', 'phone-outline', 'more', 'more-outline', 'star-on', 'star-off', 's-goods', 'goods', 'warning', 'warning-outline', 'question', 'info', 'remove', 'circle-plus', 'success', 'error', 'zoom-in', 'zoom-out', 'remove-outline', 'circle-plus-outline', 'circle-check', 'circle-close', 's-help', 'help', 'minus', 'plus', 'check', 'close', 'picture', 'picture-outline', 'picture-outline-round', 'upload', 'upload2', 'download', 'camera-solid', 'camera', 'video-camera-solid', 'video-camera', 'message-solid', 'bell', 's-cooperation', 's-order', 's-platform', 's-fold', 's-unfold', 's-operation', 's-promotion', 's-home', 's-release', 's-ticket', 's-management', 's-open', 's-shop', 's-marketing', 's-flag', 's-comment', 's-finance', 's-claim', 's-custom', 's-opportunity', 's-data', 's-check', 's-grid', 'menu', 'share', 'd-caret', 'caret-left', 'caret-right', 'caret-bottom', 'caret-top', 'bottom-left', 'bottom-right', 'back', 'right', 'bottom', 'top', 'top-left', 'top-right', 'arrow-left', 'arrow-right', 'arrow-down', 'arrow-up', 'd-arrow-left', 'd-arrow-right', 'video-pause', 'video-play', 'refresh', 'refresh-right', 'refresh-left', 'finished', 'sort', 'sort-up', 'sort-down', 'rank', 'loading', 'view', 'c-scale-to-original', 'date', 'edit', 'edit-outline', 'folder', 'folder-opened', 'folder-add', 'folder-remove', 'folder-delete', 'folder-checked', 'tickets', 'document-remove', 'document-delete', 'document-copy', 'document-checked', 'document', 'document-add', 'printer', 'paperclip', 'takeaway-box', 'search', 'monitor', 'attract', 'mobile', 'scissors', 'umbrella', 'headset', 'brush', 'mouse', 'coordinate', 'magic-stick', 'reading', 'data-line', 'data-board', 'pie-chart', 'data-analysis', 'collection-tag', 'film', 'suitcase', 'suitcase-1', 'receiving', 'collection', 'files', 'notebook-1', 'notebook-2', 'toilet-paper', 'office-building', 'school', 'table-lamp', 'house', 'no-smoking', 'smoking', 'shopping-cart-full', 'shopping-cart-1', 'shopping-cart-2', 'shopping-bag-1', 'shopping-bag-2', 'sold-out', 'sell', 'present', 'box', 'bank-card', 'money', 'coin', 'wallet', 'discount', 'price-tag', 'news', 'guide', 'male', 'female', 'thumb', 'cpu', 'link', 'connection', 'open', 'turn-off', 'set-up', 'chat-round', 'chat-line-round', 'chat-square', 'chat-dot-round', 'chat-dot-square', 'chat-line-square', 'message', 'postcard', 'position', 'turn-off-microphone', 'microphone', 'close-notification', 'bangzhu', 'time', 'odometer', 'crop', 'aim', 'switch-button', 'full-screen', 'copy-document', 'mic', 'stopwatch', 'medal-1', 'medal', 'trophy', 'trophy-1', 'first-aid-kit', 'discover', 'place', 'location', 'location-outline', 'location-information', 'add-location', 'delete-location', 'map-location', 'alarm-clock', 'timer', 'watch-1', 'watch', 'lock', 'unlock', 'key', 'service', 'mobile-phone', 'bicycle', 'truck', 'ship', 'basketball', 'football', 'soccer', 'baseball', 'wind-power', 'light-rain', 'lightning', 'heavy-rain', 'sunrise', 'sunrise-1', 'sunset', 'sunny', 'cloudy', 'partly-cloudy', 'cloudy-and-sunny', 'moon', 'moon-night', 'dish', 'dish-1', 'food', 'chicken', 'fork-spoon', 'knife-fork', 'burger', 'tableware', 'sugar', 'dessert', 'ice-cream', 'hot-water', 'water-cup', 'coffee-cup', 'cold-drink', 'goblet', 'goblet-full', 'goblet-square', 'goblet-square-full', 'refrigerator', 'grape', 'watermelon', 'cherry', 'apple', 'pear', 'orange', 'coffee', 'ice-tea', 'ice-drink', 'milk-tea', 'potato-strips', 'lollipop', 'ice-cream-square', 'ice-cream-round'].map(s => 'el-icon-' + s)

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,48 @@
import { TypeUtil } from './utils/index'
import fontAwesome from './fontAwesome'
import elementUI from './elementUI'
import eIconList from './eIconList'
const add = function(list, item) {
let arr = []
if (item && TypeUtil.isArray(item)) {
arr = list.concat(item)
} else if (item && TypeUtil.isString(item)) {
arr = arr.concat(list)
arr.push(item)
}
return arr
}
const remove = function(list, item) {
if (item && TypeUtil.isArray(item)) {
for (let i = 0; i < item.length; i++) {
for (let j = 0; j < list.length; j++) {
if (list[j] === item[i]) {
list.splice(j, 1)
j--
}
}
}
} else if (item && TypeUtil.isString(item)) {
list = list.filter(function(i) {
return i !== item
})
}
return list
}
const iconList = {
list: [],
addIcon: function(item) {
this.list = add(this.list, item)
},
removeIcon: function(item) {
this.list = remove(this.list, item)
}
}
export { fontAwesome, elementUI, eIconList }
export default iconList

View File

@@ -0,0 +1,539 @@
<template>
<div class="ui-fas">
<div
v-if="!!name"
class="selected-icon-container"
>
<span
title="icon"
:style="{color: color}"
>
<e-icon
:icon-name="name"
:title="name"
class="e-icon"
/>
</span>
</div>
<el-popover
ref="popover"
v-model="visible"
:disabled="disabled"
:placement="myPlacement"
popper-class="el-icon-popper"
:width="popoverWidth"
show-arrow
trigger="manual"
@show="setTempSelected"
>
<template slot="reference">
<slot
name="default"
:data="{prefixIcon,visible,placeholder,disabled,clearable,readonly,size}"
>
<el-input
ref="input"
v-model="proxyValue"
class="de-icon-picker-input"
:placeholder="dynamicPlaceholder"
:style="styles"
:clearable="clearable"
:disabled="disabled"
:readonly="true"
:size="size"
@input="_change"
@clear="_initIcon(false)"
@focus="_popoverShowFun(false)"
>
<template
v-if="showPrefix"
slot="prepend"
>
<slot
name="prepend"
:icon="prefixIcon"
>
<e-icon
:icon-name="prefixIcon"
class="e-icon"
/>
</slot>
</template>
</el-input>
</slot>
</template>
<div class="de-icon-picker-container">
<div class="top-container">
<el-color-picker
v-model="curColor"
show-alpha
@change="colorChange"
/>
<div class="top-sure-button-div">
<el-button
type="primary"
size="mini"
icon="el-icon-check"
@click.stop="sure"
/>
</div>
</div>
<el-divider class="top-divider" />
<el-scrollbar
v-if="!destroy"
ref="eScrollbar"
tag="div"
wrap-class="el-select-dropdown__wrap"
view-class="el-select-dropdown__list"
:class="'is-empty-'+id"
>
<ul
v-if="dataList && dataList.length > 0"
ref="fasIconList"
class="fas-icon-list"
>
<li
v-for="(item, index) in dataList"
:key="index"
class="picker-li"
:style="tempSelected === item && (highLightColor !== '' || !!curColor) ? {color: highLightColor || curColor, border: '1px solid ' + curColor} : ''"
@click="_selectedIcon(item)"
>
<slot
name="icon"
:icon="item"
>
<e-icon
:icon-name="item"
:title="item"
class="e-icon"
/>
</slot>
</li>
</ul>
<span
v-else
class="fas-no-data"
v-text="emptyText"
/>
</el-scrollbar>
</div>
</el-popover>
</div>
</template>
<script>
import iconList, { eIconList, elementUI, fontAwesome } from './iconList'
import { off, on } from './utils/index'
import EIcon from './eIcon/e-icon'
import ElInput from 'element-ui/lib/input'
import ElPopover from 'element-ui/lib/popover'
import ElScrollbar from 'element-ui/lib/scrollbar'
import { PopupManager } from 'element-ui/lib/utils/popup'
export default {
name: 'EIconPicker',
components: {
EIcon,
ElInput,
ElPopover,
ElScrollbar
},
props: {
disabled: {
type: Boolean,
default() {
return false
}
},
readonly: {
type: Boolean,
default() {
return false
}
},
clearable: {
type: Boolean,
default() {
return false
}
},
styles: {
type: Object,
default() {
return {}
}
},
placement: {
type: String,
default() {
return 'bottom'
}
},
value: {
type: String,
default() {
return ''
}
},
options: {},
width: {
type: Number,
default() {
return -1
}
},
size: {
type: String,
default() {
return 'medium'
}
},
placeholder: {
type: String,
default() {
return '请选择图标'
}
},
defaultIcon: {
type: String,
default() {
return 'eiconfont e-icon-bi'
}
},
emptyText: {
type: String,
default() {
return '暂无可选图标'
}
},
highLightColor: {
type: String,
default() {
return ''
}
},
zIndex: {
type: Number,
default() {
return null
}
},
showPrefix: {
type: Boolean,
default() {
return false
}
},
color: {
type: String,
default() {
return 'rgba(255, 0, 0, 1.0)'
}
}
},
data() {
return {
iconList: [],
visible: false,
prefixIcon: 'eiconfont e-icon-bi',
name: '',
icon: {},
myPlacement: 'bottom',
popoverWidth: 200,
destroy: false,
id: new Date().getTime(),
proxyValue: '',
curColor: '',
tempSelected: ''
}
},
computed: {
dataList: function() {
const arr1 = []
for (let i = 0, len = this.iconList.length; i < len; i++) {
if (arr1.indexOf(this.iconList[i]) === -1) {
arr1.push(this.iconList[i])
}
}
return arr1
},
dynamicPlaceholder() {
return this.name ? '' : this.placeholder
}
},
watch: {
value: function(val) {
setTimeout(() => {
this.name = val
this.prefixIcon = this.name ? this.name : this.defaultIcon
}, 50)
},
visible: function(val) {
if (val === false) {
this.$nextTick(() => {
off(document, 'mouseup', this._popoverHideFun)
})
} else {
this.$nextTick(() => {
this.createIconList()
on(document, 'mouseup', this._popoverHideFun)
})
}
},
options: {
handler(newV, oldV) {
const self = this
setTimeout(() => {
self._initIcon(true)
}, 50)
},
deep: true
}
},
mounted() {
this._updateW()
},
beforeDestroy() {
off(document, 'mouseup', this._popoverHideFun)
this.destroyIconList()
},
created() {
this.createIconList()
this._initIcon(true)
this.curColor = this.color
},
methods: {
colorChange(c) {
this.color = c
this.$emit('set-color', c)
},
setTempSelected() {
this.tempSelected = this.name
},
sure() {
this.visible = false
this.name = this.tempSelected
this.prefixIcon = this.name
this.color = this.curColor
this._emitFun(this.name)
this.$emit('set-color', this.curColor)
},
_change(val) {
this.iconList = this.icon.list.filter(function(i) {
return i.indexOf(val) !== -1
})
},
_initIcon(type) {
this.prefixIcon = this.value && type && type === true ? this.value : this.defaultIcon
this.name = type === true ? this.value : ''
this.icon = Object.assign({}, iconList)
if (this.options) {
this.icon.list = []
if (this.options.addIconList !== undefined &&
this.options.addIconList &&
this.options.addIconList.length > 0) {
this.icon.addIcon(this.options.addIconList)
}
if (this.options.removeIconList !== undefined &&
this.options.removeIconList &&
this.options.removeIconList.length > 0) {
this.icon.removeIcon(this.options.removeIconList)
}
if (this.options.FontAwesome === true) {
this.icon.addIcon(fontAwesome)
}
if (this.options.ElementUI === true) {
this.icon.addIcon(elementUI)
}
if (this.options.eIcon === true) {
if (this.options.eIconSymbol) {
const list = eIconList.map((item) => {
return item.replace('eiconfont ', '#')
})
this.icon.addIcon(list)
} else {
this.icon.addIcon(eIconList)
}
}
}
this.iconList = this.icon.list
if (this.placement && (this.placement === 'bottom' || this.placement === 'top')) {
this.myPlacement = this.placement
}
if (type === false) {
this._emitFun('')
}
},
addIcon(item = []) {
if (item !== undefined && item && item.length > 0) {
this.icon.addIcon(item)
this.iconList = this.icon.list
}
},
removeIcon(item = []) {
if (item !== undefined && item && item.length > 0) {
this.icon.removeIcon(item)
this.iconList = this.icon.list
}
},
updatePopper(zIndex) {
if (zIndex) {
PopupManager.zIndex = zIndex
}
this._popoverShowFun(true)
setTimeout(() => {
this.$refs.popover.updatePopper()
}, 100)
},
_selectedIcon(item) {
this.tempSelected = item
},
_updateW() {
this.$nextTick(() => {
if (this.width === -1 && this.$refs.input && this.$refs.input.$el) {
this.popoverWidth = this.$refs.input.$el.getBoundingClientRect().width - 36
} else {
this.popoverWidth = this.width
}
if (this.$refs.eScrollbar && this.$refs.eScrollbar.wrap) {
this.$refs.eScrollbar.wrap.scrollTop = 0
this.$refs.eScrollbar.handleScroll()
this.$refs.eScrollbar.update()
}
})
},
_popoverShowFun(flag) {
const _this = this
if (_this.readonly !== true && _this.disabled !== true) {
if (!flag && _this.zIndex) {
PopupManager.zIndex = this.zIndex
}
_this.visible = true
_this._updateW()
}
},
_popoverHideFun(e) {
const path = e.path || (e.composedPath && e.composedPath())
const isInside = path.some(list => {
return list.className && typeof list.className === 'string' && (list.className.indexOf('ui-fas') !== -1 || list.className.indexOf('de-icon-picker-container') !== -1)
})
if (!isInside) {
this.visible = false
}
const isInput = path.some(list => {
return list.className && typeof list.className === 'string' && list.className.indexOf('de-icon-picker-input') !== -1
})
if (this.visible && isInput) {
// this.visible = false
}
},
_emitFun(val) {
this.$emit('input', val)
this.$emit('change', val)
},
destroyIconList() {
this.destroy = true
},
createIconList() {
this.destroy = false
},
show() {
this._popoverShowFun(false)
},
hide() {
this.visible = false
}
}
}
</script>
<style lang="scss" scoped>
@import '~element-ui/lib/theme-chalk/input.css';
@import '~element-ui/lib/theme-chalk/popover.css';
@import '~element-ui/lib/theme-chalk/scrollbar.css';
@import '~element-ui/lib/theme-chalk/select-dropdown.css';
.fas-icon-list {
list-style-type: none;
margin: 0 0 0 -4px;
padding: 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.ui-fas .el-input__inner {
cursor: pointer;
}
.fas-icon-list li {
width: 30px;
height: 30px;
margin: 5px;
}
.fas-icon-list li i, .fas-icon-list li svg {
font-size: 20px;
cursor: pointer;
}
.el-icon-popper {
max-height: 400px;
overflow: auto;
overflow-x: hidden;
overflow-y: hidden;
}
.el-icon-popper[x-placement^="bottom"] {
margin-top: 5px;
}
.fas-no-data {
display: block;
}
.e-icon {
font-size: 16px;
}
.top-divider {
margin: 5px 0 0 0 !important;
}
.top-container {
display: flex;
}
.top-sure-button-div {
margin: 4px 15px 0 auto;
::v-deep button {
width: 25px;
height: 20px;
padding: 4px 5px;
}
}
.selected-icon-container {
position: absolute;
z-index: 9;
width: 21%;
text-align: center;
margin-top: 2px;
pointer-events: none;
}
.picker-li {
text-align: center;
line-height: 30px;
}
</style>

View File

@@ -0,0 +1,27 @@
export const TypeUtil = {
isArray: function(obj) {
return (typeof obj === 'object') && obj.constructor === Array
},
isString: function(obj) {
return (typeof obj === 'string') && obj.constructor === String
},
isNumber: function(obj) {
return (typeof obj === 'number') && obj.constructor === Number
},
isDate: function(obj) {
return (typeof obj === 'object') && obj.constructor === Date
},
isFunction: function(obj) {
return (typeof obj === 'function') && obj.constructor === Function
},
isObject: function(obj) {
return (typeof obj === 'object') && obj.constructor === Object
}
}

View File

@@ -0,0 +1,36 @@
import { isServer } from './util'
export const on = (function() {
if (!isServer) {
if (document && document.addEventListener) {
return function(element, event, handler) {
if (element && event && handler) {
element.addEventListener(event, handler, false)
}
}
} else {
return function(element, event, handler) {
if (element && event && handler) {
element.attachEvent('on' + event, handler)
}
}
}
}
})()
export const off = (function() {
if (!isServer) {
if (document && document.removeEventListener) {
return function(element, event, handler) {
if (element && event) {
element.removeEventListener(event, handler, false)
}
}
} else {
return function(element, event, handler) {
if (element && event) {
element.detachEvent('on' + event, handler)
}
}
}
}
})()

View File

@@ -0,0 +1,15 @@
const req = require.context(process.env.VUE_APP_SVG, false, /\.svg$/)
const requireAllFile = requireContext => requireContext.keys().map(requireContext)
requireAllFile(req)
const re = /\.\/(.*)\.svg/
const requireAll = requireContext => requireContext.keys()
const svgIcons = requireAll(req).map(i => {
return '#' + i.match(re)[1]
})
export default svgIcons

View File

@@ -0,0 +1,28 @@
(function(e, d, w) {
if (!e.composedPath) {
e.composedPath = function() {
if (this.path) {
return this.path
}
let target = this.target
this.path = []
while (target.parentNode !== null) {
this.path.push(target)
target = target.parentNode
}
this.path.push(d, w)
return this.path
}
}
if (!String.prototype.startsWith) {
// eslint-disable-next-line no-extend-native
String.prototype.startsWith = function(search, pos) {
return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search
}
}
})(Event.prototype, document, window)
export * from './util'
export * from './dom'
export * from './TypeUtil'

View File

@@ -0,0 +1,53 @@
export const analyzingIconForIconfont = function(json) {
let font_family = ''
let css_prefix_text = ''
let list = []
if (json) {
if (json.font_family) {
font_family = json.font_family
}
if (json.css_prefix_text) {
css_prefix_text = json.css_prefix_text
}
if (json.glyphs) {
list = json.glyphs.map(function(value, index, array) {
return font_family + ' ' + css_prefix_text + value.font_class
})
}
}
return {
font_family,
css_prefix_text,
list
}
}
export const eIconSymbol = function(json) {
let font_family = ''
let css_prefix_text = ''
let list = []
if (json) {
if (json.font_family) {
font_family = json.font_family
}
if (json.css_prefix_text) {
css_prefix_text = json.css_prefix_text
}
if (json.glyphs) {
list = json.glyphs.map(function(value, index, array) {
return '#' + css_prefix_text + value.font_class
})
}
}
return {
font_family,
css_prefix_text,
list
}
}
export function isExternal(path) {
return /^(https?:|data:|\/\/?)/.test(path)
}
export const isServer = typeof window === 'undefined'