@ithinkdt/cloud
Version:
iThinkDT Cloud
130 lines (115 loc) • 3.54 kB
JavaScript
import { ref, readonly, h, reactive } from 'vue'
import { $fetch } from '@ithinkdt/core'
export function icon(CTX) {
const iconMap = new Map()
let _clean
function clean() {
if (_clean === undefined) {
setTimeout(() => {
requestIdleCallback(() => {
for (const k of iconMap.keys()) {
if (iconMap.get(k).value !== undefined) {
iconMap.delete(k)
}
}
_clean = undefined
})
}, 60_000)
_clean = true
}
}
function _getIcon(id) {
return fetch(`${CTX._BASE + CTX.SYS}pub/logo/${id}`, {
method: 'get',
credentials: 'omit',
})
.then((resp) => resp.blob())
.then((blob) => blob.text())
.then((text) => {
try {
const e = JSON.parse(text)
console.debug(`获取图标失败,id: ${id}`, e)
return ''
} catch {
return text
} finally {
clean()
}
})
}
const t = 'data:image/svg+xml;base64,'
function getIconUri(id) {
if (iconMap.has(id)) {
return iconMap.get(id)
}
const icon = ref()
const _icon = readonly(icon)
iconMap.set(id, _icon)
_getIcon(id).then((text) => {
icon.value = text
})
return _icon
}
return {
async saveIcon(icon) {
icon = { type: 'other', ...icon }
if (icon.body instanceof File) {
const file = icon.body
if (!icon.name) {
icon.name = file.name
}
icon.body = await new Promise((resolve) => {
const fr = new FileReader()
fr.addEventListener('load', () => {
resolve(fr.result)
})
fr.readAsDataURL(file)
})
}
return $fetch
.post(`${CTX.SYS}cer/logo/save`, {
id: icon.id,
name: icon.name,
logo: icon.body,
type: icon.type,
remark: icon.remark,
})
.then((res) => {
icon.id = res.id
return icon
})
},
getIconUri,
getIcon(id) {
const uri = getIconUri(id)
return readonly(
reactive({
id,
body: uri,
}),
)
},
getIconRender(id) {
return () => {
let text = getIconUri(id).value
if (!text) return
if (text.startsWith(t)) {
text = window.atob(text.slice(t.length))
return h('span', {
innerHTML: text,
style: {
lineHeight: '0',
},
})
} else {
return h('img', {
src: text,
style: {
height: '1em',
},
})
}
}
},
}
}