mirror of
https://github.com/Kuingsmile/PicList.git
synced 2025-02-08 21:38:13 -05:00
✨ Feature: optimize filename display
This commit is contained in:
parent
e8189b0837
commit
2336483927
@ -50,12 +50,12 @@ class LocalApi {
|
|||||||
transBack (filePath: string | undefined) {
|
transBack (filePath: string | undefined) {
|
||||||
if (!filePath) return ''
|
if (!filePath) return ''
|
||||||
return this.isWindows
|
return this.isWindows
|
||||||
? filePath.split(path.posix.sep).join(path.sep).replace(/^\\+/, '')
|
? filePath.split(path.posix.sep).join(path.sep).replace(/^\\+|\\+$/g, '')
|
||||||
: `/${filePath.replace(/^\/+/, '')}`
|
: `/${filePath.replace(/^\/+|\/+$/g, '')}`
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFolder (item: fs.Stats, urlPrefix: string, fileName: string, filePath: string) {
|
formatFolder (item: fs.Stats, urlPrefix: string, fileName: string, filePath: string) {
|
||||||
const key = this.transPathToUnix(filePath)
|
const key = `${this.transPathToUnix(filePath)}/`.replace(/\/+$/, '/')
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
key,
|
key,
|
||||||
@ -71,8 +71,8 @@ class LocalApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatFile (item: fs.Stats, urlPrefix: string, fileName: string, filePath: string) {
|
formatFile (item: fs.Stats, urlPrefix: string, fileName: string, filePath: string, isDownload = false) {
|
||||||
const key = this.transPathToUnix(filePath)
|
const key = isDownload ? filePath : this.transPathToUnix(filePath)
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
key,
|
key,
|
||||||
@ -106,7 +106,7 @@ class LocalApi {
|
|||||||
finished: false
|
finished: false
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
res = fsWalk.walkSync(prefix, {
|
res = fsWalk.walkSync(this.transBack(prefix), {
|
||||||
followSymbolicLinks: true,
|
followSymbolicLinks: true,
|
||||||
fs,
|
fs,
|
||||||
stats: true,
|
stats: true,
|
||||||
@ -114,9 +114,9 @@ class LocalApi {
|
|||||||
})
|
})
|
||||||
if (res.length) {
|
if (res.length) {
|
||||||
result.fullList.push(
|
result.fullList.push(
|
||||||
...res.data
|
...res
|
||||||
.filter((item: fsWalk.Entry) => item.stats?.isFile())
|
.filter((item: fsWalk.Entry) => item.stats?.isFile())
|
||||||
.map((item: any) => this.formatFile(item, urlPrefix, item.name, item.path))
|
.map((item: any) => this.formatFile(item, urlPrefix, item.name, item.path, true))
|
||||||
)
|
)
|
||||||
result.success = true
|
result.success = true
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ class LocalApi {
|
|||||||
const { customUrl = '', cancelToken, baseDir } = configMap
|
const { customUrl = '', cancelToken, baseDir } = configMap
|
||||||
let prefix = configMap.prefix
|
let prefix = configMap.prefix
|
||||||
prefix = this.transBack(prefix)
|
prefix = this.transBack(prefix)
|
||||||
let urlPrefix = customUrl.replace(/\/+$/, '')
|
const urlPrefix = customUrl.replace(/\/+$/, '')
|
||||||
let webPath = configMap.webPath || ''
|
let webPath = configMap.webPath || ''
|
||||||
if (webPath && customUrl && webPath !== '/') {
|
if (webPath && customUrl && webPath !== '/') {
|
||||||
webPath = webPath.replace(/^\/+|\/+$/, '')
|
webPath = webPath.replace(/^\/+|\/+$/, '')
|
||||||
@ -156,20 +156,22 @@ class LocalApi {
|
|||||||
withFileTypes: true
|
withFileTypes: true
|
||||||
})
|
})
|
||||||
if (res.length) {
|
if (res.length) {
|
||||||
|
let urlPrefixF
|
||||||
res.forEach((item: fs.Dirent) => {
|
res.forEach((item: fs.Dirent) => {
|
||||||
const pathOfFile = path.join(prefix, item.name)
|
const pathOfFile = path.join(prefix, item.name)
|
||||||
const relativePath = path.relative(baseDir, pathOfFile)
|
let relative
|
||||||
const relative = webPath && urlPrefix + `/${path.join(webPath, relativePath)}`.replace(/\\/g, '/').replace(/\/+/g, '/')
|
if (customUrl) {
|
||||||
if (webPath && customUrl) {
|
const relativePath = path.relative(this.transBack(baseDir), pathOfFile)
|
||||||
urlPrefix = relative
|
relative = urlPrefix + `/${path.join(webPath, relativePath)}`.replace(/\\/g, '/').replace(/\/+/g, '/')
|
||||||
|
urlPrefixF = this.isWindows ? relative.replace(/\/[a-zA-Z]:\//, '/') : relative
|
||||||
} else {
|
} else {
|
||||||
urlPrefix = pathOfFile
|
urlPrefixF = pathOfFile
|
||||||
}
|
}
|
||||||
const stats = fs.statSync(pathOfFile)
|
const stats = fs.statSync(pathOfFile)
|
||||||
if (item.isDirectory()) {
|
if (item.isDirectory()) {
|
||||||
result.fullList.push(this.formatFolder(stats, urlPrefix, item.name, relativePath))
|
result.fullList.push(this.formatFolder(stats, urlPrefixF, item.name, pathOfFile))
|
||||||
} else {
|
} else {
|
||||||
result.fullList.push(this.formatFile(stats, urlPrefix, item.name, relativePath))
|
result.fullList.push(this.formatFile(stats, urlPrefixF, item.name, pathOfFile))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
result.success = true
|
result.success = true
|
||||||
@ -210,7 +212,7 @@ class LocalApi {
|
|||||||
const { key } = configMap
|
const { key } = configMap
|
||||||
let result = false
|
let result = false
|
||||||
try {
|
try {
|
||||||
await fs.rmdir(this.transBack(key), {
|
await fs.rm(this.transBack(key), {
|
||||||
recursive: true
|
recursive: true
|
||||||
})
|
})
|
||||||
result = true
|
result = true
|
||||||
@ -241,7 +243,7 @@ class LocalApi {
|
|||||||
noProgress: true
|
noProgress: true
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
fs.ensureFileSync(filePath)
|
fs.ensureFileSync(this.transBack(key))
|
||||||
await fs.copyFile(filePath, this.transBack(key))
|
await fs.copyFile(filePath, this.transBack(key))
|
||||||
instance.updateUploadTask({
|
instance.updateUploadTask({
|
||||||
id,
|
id,
|
||||||
@ -281,7 +283,7 @@ class LocalApi {
|
|||||||
const instance = UpDownTaskQueue.getInstance()
|
const instance = UpDownTaskQueue.getInstance()
|
||||||
for (const item of fileArray) {
|
for (const item of fileArray) {
|
||||||
const { alias, bucketName, key, fileName } = item
|
const { alias, bucketName, key, fileName } = item
|
||||||
const savedFilePath = path.join(downloadPath, fileName)
|
const savedFilePath = path.join(downloadPath, fileName.replace(/[:*?"<>|]/g, ''))
|
||||||
const id = `${alias}-${bucketName}-local-${key}`
|
const id = `${alias}-${bucketName}-local-${key}`
|
||||||
if (instance.getDownloadTask(id)) {
|
if (instance.getDownloadTask(id)) {
|
||||||
continue
|
continue
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-image
|
|
||||||
:src="isShowThumbnail && item.isImage ?
|
|
||||||
base64Image
|
|
||||||
: require(`../manage/pages/assets/icons/${getFileIconPath(item.fileName ?? '')}`)"
|
|
||||||
fit="contain"
|
|
||||||
style="height: 100px;width: 100%;margin: 0 auto;"
|
|
||||||
>
|
|
||||||
<template #placeholder>
|
|
||||||
<el-icon>
|
|
||||||
<Loading />
|
|
||||||
</el-icon>
|
|
||||||
</template>
|
|
||||||
<template #error>
|
|
||||||
<el-image
|
|
||||||
:src="require(`../manage/pages/assets/icons/${getFileIconPath(item.fileName ?? '')}`)"
|
|
||||||
fit="contain"
|
|
||||||
style="height: 100px;width: 100%;margin: 0 auto;"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-image>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, onBeforeMount, watch } from 'vue'
|
|
||||||
import { getFileIconPath } from '@/manage/utils/common'
|
|
||||||
import { Loading } from '@element-plus/icons-vue'
|
|
||||||
import fs from 'fs-extra'
|
|
||||||
import mime from 'mime-types'
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
const base64Image = ref('')
|
|
||||||
const props = defineProps(
|
|
||||||
{
|
|
||||||
isShowThumbnail: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
item: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
localPath: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.localPath,
|
|
||||||
async (newLocalPath, oldLocalPath) => {
|
|
||||||
if (newLocalPath !== oldLocalPath) {
|
|
||||||
try {
|
|
||||||
await createBase64Image()
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const createBase64Image = async () => {
|
|
||||||
const filePath = path.normalize(props.localPath)
|
|
||||||
const base64 = await fs.readFile(filePath, 'base64')
|
|
||||||
base64Image.value = `data:${mime.lookup(filePath) || 'image/png'};base64,${base64}`
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
|
||||||
try {
|
|
||||||
await createBase64Image()
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
@ -59,7 +59,7 @@
|
|||||||
class="icon"
|
class="icon"
|
||||||
size="25px"
|
size="25px"
|
||||||
>
|
>
|
||||||
<DocumentAdd />
|
<Upload />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -80,7 +80,7 @@
|
|||||||
size="25px"
|
size="25px"
|
||||||
style="margin-left: 5px;"
|
style="margin-left: 5px;"
|
||||||
>
|
>
|
||||||
<Upload />
|
<UploadFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -497,7 +497,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
|||||||
shadow="hover"
|
shadow="hover"
|
||||||
>
|
>
|
||||||
<el-image
|
<el-image
|
||||||
v-if="!item.isDir && currentPicBedName !== 'webdavplist' && currentPicBedName !== 'local'"
|
v-if="!item.isDir && currentPicBedName !== 'webdavplist'"
|
||||||
:src="isShowThumbnail && item.isImage ?
|
:src="isShowThumbnail && item.isImage ?
|
||||||
item.url
|
item.url
|
||||||
: require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)"
|
: require(`./assets/icons/${getFileIconPath(item.fileName ?? '')}`)"
|
||||||
@ -526,13 +526,6 @@ https://www.baidu.com/img/bd_logo1.png"
|
|||||||
:url="item.url"
|
:url="item.url"
|
||||||
@click="handleClickFile(item)"
|
@click="handleClickFile(item)"
|
||||||
/>
|
/>
|
||||||
<ImageLocal
|
|
||||||
v-else-if="!item.isDir && currentPicBedName === 'local'"
|
|
||||||
:is-show-thumbnail="isShowThumbnail"
|
|
||||||
:item="item"
|
|
||||||
:local-path="item.key"
|
|
||||||
@click="handleClickFile(item)"
|
|
||||||
/>
|
|
||||||
<el-image
|
<el-image
|
||||||
v-else
|
v-else
|
||||||
:src="require('./assets/icons/folder.webp')"
|
:src="require('./assets/icons/folder.webp')"
|
||||||
@ -554,7 +547,7 @@ https://www.baidu.com/img/bd_logo1.png"
|
|||||||
:underline="false"
|
:underline="false"
|
||||||
:type="item.checked ? 'primary' : 'info'"
|
:type="item.checked ? 'primary' : 'info'"
|
||||||
>
|
>
|
||||||
{{ formatFileName(item.fileName ?? '', 8) }}
|
{{ formatFileName(item.fileName ?? '', 15) }}
|
||||||
</el-link>
|
</el-link>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
@ -1422,7 +1415,7 @@ import { ref, reactive, watch, onBeforeMount, computed, onBeforeUnmount } from '
|
|||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
// Element Plus 图标
|
// Element Plus 图标
|
||||||
import { InfoFilled, Grid, Fold, Close, Folder, FolderAdd, Upload, CircleClose, Loading, CopyDocument, Edit, DocumentAdd, Link, Refresh, ArrowRight, HomeFilled, Document, Coin, Download, DeleteFilled, Sort, FolderOpened } from '@element-plus/icons-vue'
|
import { InfoFilled, Grid, Fold, Close, Folder, FolderAdd, Upload, CircleClose, Loading, CopyDocument, Edit, UploadFilled, Link, Refresh, ArrowRight, HomeFilled, Document, Coin, Download, DeleteFilled, Sort, FolderOpened } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
// 状态管理相关
|
// 状态管理相关
|
||||||
import { useManageStore } from '../store/manageStore'
|
import { useManageStore } from '../store/manageStore'
|
||||||
@ -1492,7 +1485,6 @@ import { videoExt } from '../utils/videofile'
|
|||||||
|
|
||||||
// 组件
|
// 组件
|
||||||
import ImageWebdav from '@/components/ImageWebdav.vue'
|
import ImageWebdav from '@/components/ImageWebdav.vue'
|
||||||
import ImageLocal from '@/components/ImageLocal.vue'
|
|
||||||
|
|
||||||
// 国际化函数
|
// 国际化函数
|
||||||
import { T as $T } from '@/i18n'
|
import { T as $T } from '@/i18n'
|
||||||
@ -2113,6 +2105,16 @@ async function initCustomDomainList () {
|
|||||||
currentCustomDomain.value = endpoint
|
currentCustomDomain.value = endpoint
|
||||||
}
|
}
|
||||||
handleChangeCustomUrl()
|
handleChangeCustomUrl()
|
||||||
|
} else if (currentPicBedName.value === 'local') {
|
||||||
|
const currentConfigs = await getConfig<any>('picBed')
|
||||||
|
const currentConfig = currentConfigs[configMap.alias]
|
||||||
|
const currentTransformedConfig = JSON.parse(currentConfig.transformedConfig ?? '{}')
|
||||||
|
if (currentTransformedConfig[configMap.bucketName] && currentTransformedConfig[configMap.bucketName]?.customUrl) {
|
||||||
|
currentCustomDomain.value = currentTransformedConfig[configMap.bucketName].customUrl ?? ''
|
||||||
|
} else {
|
||||||
|
currentCustomDomain.value = ''
|
||||||
|
}
|
||||||
|
handleChangeCustomUrl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2535,7 +2537,7 @@ function handleCreateFolder () {
|
|||||||
ElMessageBox.prompt($T('MANAGE_BUCKET_CREATE_FOLDER_BOX_TITLE'), $T('MANAGE_BUCKET_CREATE_FOLDER_BOX_TIP'), {
|
ElMessageBox.prompt($T('MANAGE_BUCKET_CREATE_FOLDER_BOX_TITLE'), $T('MANAGE_BUCKET_CREATE_FOLDER_BOX_TIP'), {
|
||||||
confirmButtonText: $T('MANAGE_BUCKET_CREATE_FOLDER_BOX_CONFIRM'),
|
confirmButtonText: $T('MANAGE_BUCKET_CREATE_FOLDER_BOX_CONFIRM'),
|
||||||
cancelButtonText: $T('MANAGE_BUCKET_CREATE_FOLDER_BOX_CANCEL'),
|
cancelButtonText: $T('MANAGE_BUCKET_CREATE_FOLDER_BOX_CANCEL'),
|
||||||
inputPattern: /^[\u4e00-\u9fff_a-zA-Z0-9/]+$/,
|
inputPattern: /^[\p{Unified_Ideograph}_a-zA-Z0-9-]+$/u,
|
||||||
inputErrorMessage: $T('MANAGE_BUCKET_CREATE_FOLDER_ERROR_MSG')
|
inputErrorMessage: $T('MANAGE_BUCKET_CREATE_FOLDER_ERROR_MSG')
|
||||||
}).then(async ({ value }) => {
|
}).then(async ({ value }) => {
|
||||||
let formatedPath = value
|
let formatedPath = value
|
||||||
@ -2801,7 +2803,6 @@ async function getBucketFileListBackStage () {
|
|||||||
param.baseDir = configMap.baseDir
|
param.baseDir = configMap.baseDir
|
||||||
param.webPath = configMap.webPath
|
param.webPath = configMap.webPath
|
||||||
}
|
}
|
||||||
console.log(param)
|
|
||||||
ipcRenderer.send('getBucketListBackstage', configMap.alias, param)
|
ipcRenderer.send('getBucketListBackstage', configMap.alias, param)
|
||||||
ipcRenderer.on('refreshFileTransferList', (evt: IpcRendererEvent, data) => {
|
ipcRenderer.on('refreshFileTransferList', (evt: IpcRendererEvent, data) => {
|
||||||
fileTransferStore.refreshFileTransferList(data)
|
fileTransferStore.refreshFileTransferList(data)
|
||||||
@ -3445,7 +3446,7 @@ const columns: Column<any>[] = [
|
|||||||
<div
|
<div
|
||||||
style="font-size: 14px;color: #303133;font-family: Arial, Helvetica, sans-serif;"
|
style="font-size: 14px;color: #303133;font-family: Arial, Helvetica, sans-serif;"
|
||||||
>
|
>
|
||||||
{formatFileName(item.fileName ?? '')}
|
{formatFileName(item.fileName ?? '', 40)}
|
||||||
</div>
|
</div>
|
||||||
</ElTooltip>
|
</ElTooltip>
|
||||||
</div>
|
</div>
|
||||||
|
@ -74,9 +74,9 @@
|
|||||||
effect="light"
|
effect="light"
|
||||||
:content="item.alias"
|
:content="item.alias"
|
||||||
placement="top"
|
placement="top"
|
||||||
:disabled="item.alias.length <= 15"
|
:disabled="isNeedToShorten(item.alias)"
|
||||||
>
|
>
|
||||||
{{ item.alias.length > 15 ? item.alias.slice(0, 8) + '...' + item.alias.slice(-6) : item.alias }}
|
{{ isNeedToShorten(item.alias) ? safeSliceF(item.alias, 17) + '...' : item.alias }}
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@ -290,6 +290,7 @@ import { getConfig as getPicBedsConfig } from '@/utils/dataSender'
|
|||||||
|
|
||||||
// 端点地址格式化
|
// 端点地址格式化
|
||||||
import { formatEndpoint } from '~/main/manage/utils/common'
|
import { formatEndpoint } from '~/main/manage/utils/common'
|
||||||
|
import { isNeedToShorten, safeSliceF } from '#/utils/common'
|
||||||
|
|
||||||
// 国际化函数
|
// 国际化函数
|
||||||
import { T as $T } from '@/i18n'
|
import { T as $T } from '@/i18n'
|
||||||
@ -373,7 +374,7 @@ async function handleConfigChange (name: string) {
|
|||||||
const aliasList = getAliasList()
|
const aliasList = getAliasList()
|
||||||
const allKeys = Object.keys(supportedPicBedList[name].configOptions)
|
const allKeys = Object.keys(supportedPicBedList[name].configOptions)
|
||||||
const resultMap:IStringKeyMap = {}
|
const resultMap:IStringKeyMap = {}
|
||||||
const reg = /^[\u4e00-\u9fff_a-zA-Z0-9-]+$/
|
const reg = /^[\p{Unified_Ideograph}_a-zA-Z0-9-]+$/u
|
||||||
for (const key of allKeys) {
|
for (const key of allKeys) {
|
||||||
const resultKey = name + '.' + key
|
const resultKey = name + '.' + key
|
||||||
if (supportedPicBedList[name].configOptions[key].required) {
|
if (supportedPicBedList[name].configOptions[key].required) {
|
||||||
|
@ -14,7 +14,7 @@ import { availableIconList } from './icon'
|
|||||||
import { getConfig } from './dataSender'
|
import { getConfig } from './dataSender'
|
||||||
|
|
||||||
// 工具函数
|
// 工具函数
|
||||||
import { handleUrlEncode } from '~/universal/utils/common'
|
import { handleUrlEncode, safeSliceF, isNeedToShorten } from '~/universal/utils/common'
|
||||||
|
|
||||||
export function randomStringGenerator (length: number): string {
|
export function randomStringGenerator (length: number): string {
|
||||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
||||||
@ -103,7 +103,7 @@ export function formatFileName (fileName: string, length: number = 20) {
|
|||||||
let ext = path.extname(fileName)
|
let ext = path.extname(fileName)
|
||||||
ext = ext.length > 5 ? ext.slice(ext.length - 5) : ext
|
ext = ext.length > 5 ? ext.slice(ext.length - 5) : ext
|
||||||
const name = path.basename(fileName, ext)
|
const name = path.basename(fileName, ext)
|
||||||
return name.length > length ? `${name.slice(0, length)}...${ext}` : fileName
|
return isNeedToShorten(fileName, length) ? `${safeSliceF(name, length - 3 - ext.length)}...${ext}` : fileName
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getExtension = (fileName: string) => path.extname(fileName).slice(1)
|
export const getExtension = (fileName: string) => path.extname(fileName).slice(1)
|
||||||
|
@ -44,3 +44,24 @@ export const isDev = process.env.NODE_ENV === 'development'
|
|||||||
export const trimValues = <T extends IStringKeyMap>(obj: T): {[K in keyof T]: T[K] extends string ? string : T[K]} => {
|
export const trimValues = <T extends IStringKeyMap>(obj: T): {[K in keyof T]: T[K] extends string ? string : T[K]} => {
|
||||||
return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, typeof value === 'string' ? value.trim() : value])) as {[K in keyof T]: T[K] extends string ? string : T[K]}
|
return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, typeof value === 'string' ? value.trim() : value])) as {[K in keyof T]: T[K] extends string ? string : T[K]}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isNeedToShorten (alias: string, cutOff: number = 20) {
|
||||||
|
let totalLen = 0
|
||||||
|
for (const s of alias) {
|
||||||
|
totalLen += s.charCodeAt(0) > 255 ? 2 : 1
|
||||||
|
}
|
||||||
|
return totalLen > cutOff
|
||||||
|
}
|
||||||
|
|
||||||
|
export function safeSliceF (str:string, total: number) {
|
||||||
|
let result = ''
|
||||||
|
let totalLen = 0
|
||||||
|
for (const s of str) {
|
||||||
|
if (totalLen >= total) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
result += s
|
||||||
|
totalLen += s.charCodeAt(0) > 255 ? 2 : 1
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user