Feature(custom): remove use of element-plus

This commit is contained in:
Kuingsmile
2025-08-10 16:19:33 +08:00
parent 66469ae2cf
commit b40eeee165
13 changed files with 428 additions and 556 deletions

View File

@@ -1,36 +1,41 @@
<template>
<el-image
:src="
isShowThumbnail && item.isImage
? base64Image
: `/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="`/assets/icons/${getFileIconPath(item.fileName ?? '')}`"
fit="contain"
style="height: 100px; width: 100%; margin: 0 auto"
/>
</template>
</el-image>
<div class="image-container">
<div
v-if="isLoading"
class="loading-placeholder"
>
<div class="loading-spinner" />
</div>
<img
v-else-if="!hasError"
:src="
isShowThumbnail && item.isImage
? base64Image
: `/assets/icons/${getFileIconPath(item.fileName ?? '')}`
"
alt=""
class="image"
@load="handleImageLoad"
@error="handleImageError"
>
<img
v-else
:src="`/assets/icons/${getFileIconPath(item.fileName ?? '')}`"
alt=""
class="image"
>
</div>
</template>
<script lang="ts" setup>
import { Loading } from '@element-plus/icons-vue'
import { onBeforeMount, ref } from 'vue'
import { getFileIconPath } from '@/manage/utils/common'
const base64Image = ref('')
const isLoading = ref(true)
const hasError = ref(false)
const props = defineProps<{
isShowThumbnail: boolean
item: {
@@ -41,16 +46,70 @@ const props = defineProps<{
}>()
const createBase64Image = async () => {
const filePath = window.node.path.normalize(props.localPath)
const base64 = await window.node.fs.readFile(filePath, 'base64')
base64Image.value = `data:${window.node.mime.lookup(filePath) || 'image/png'};base64,${base64}`
try {
const filePath = window.node.path.normalize(props.localPath)
const base64 = await window.node.fs.readFile(filePath, 'base64')
base64Image.value = `data:${window.node.mime.lookup(filePath) || 'image/png'};base64,${base64}`
isLoading.value = false
} catch (e) {
console.log(e)
hasError.value = true
isLoading.value = false
}
}
const handleImageLoad = () => {
isLoading.value = false
hasError.value = false
}
const handleImageError = () => {
isLoading.value = false
hasError.value = true
}
onBeforeMount(async () => {
try {
await createBase64Image()
} catch (e) {
console.log(e)
}
await createBase64Image()
})
</script>
<style scoped>
.image-container {
height: 100px;
width: 100%;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.image {
max-height: 100%;
max-width: 100%;
object-fit: contain;
display: block;
}
.loading-placeholder {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.loading-spinner {
width: 24px;
height: 24px;
border: 2px solid #e4e7ed;
border-top: 2px solid #409eff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>

View File

@@ -1,32 +1,37 @@
<template>
<el-image
:src="imageSource"
fit="contain"
style="height: 100px; width: 100%; margin: 0 auto"
>
<template #placeholder>
<el-icon>
<Loading />
</el-icon>
</template>
<template #error>
<el-image
:src="iconPath"
fit="contain"
style="height: 100px; width: 100%; margin: 0 auto"
/>
</template>
</el-image>
<div class="image-container">
<div
v-if="isLoading"
class="loading-placeholder"
>
<div class="loading-spinner" />
</div>
<img
v-else-if="!hasError"
:src="imageSource"
alt=""
class="image"
@load="handleImageLoad"
@error="handleImageError"
>
<img
v-else
:src="iconPath"
alt=""
class="image"
>
</div>
</template>
<script lang="ts" setup>
import { Loading } from '@element-plus/icons-vue'
import { computed, onMounted, ref, watch } from 'vue'
import { getFileIconPath } from '@/manage/utils/common'
import { IRPCActionType } from '@/utils/enum'
const preSignedUrl = ref('')
const isLoading = ref(true)
const hasError = ref(false)
const props = defineProps<{
item: {
@@ -49,10 +54,70 @@ const imageSource = computed(() => {
const iconPath = computed(() => `/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`)
async function getUrl () {
preSignedUrl.value = await window.electron.triggerRPC<any>(IRPCActionType.MANAGE_GET_PRE_SIGNED_URL, props.alias, props.config)
try {
isLoading.value = true
hasError.value = false
preSignedUrl.value = await window.electron.triggerRPC<any>(IRPCActionType.MANAGE_GET_PRE_SIGNED_URL, props.alias, props.config)
isLoading.value = false
} catch (error) {
console.error('Failed to get pre-signed URL:', error)
hasError.value = true
isLoading.value = false
}
}
const handleImageLoad = () => {
isLoading.value = false
hasError.value = false
}
const handleImageError = () => {
isLoading.value = false
hasError.value = true
}
watch(() => [props.url, props.item], getUrl, { deep: true })
onMounted(getUrl)
</script>
<style scoped>
.image-container {
height: 100px;
width: 100%;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.image {
max-height: 100%;
max-width: 100%;
object-fit: contain;
display: block;
}
.loading-placeholder {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.loading-spinner {
width: 24px;
height: 24px;
border: 2px solid #e4e7ed;
border-top: 2px solid #409eff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>

View File

@@ -1,64 +0,0 @@
import { Loading } from '@element-plus/icons-vue'
import { ElIcon, ElImage } from 'element-plus'
import { computed, defineComponent, onMounted, ref, watch } from 'vue'
import { getFileIconPath } from '@/manage/utils/common'
import { IRPCActionType } from '@/utils/enum'
export default defineComponent({
props: {
isShowThumbnail: {
type: Boolean,
required: true
},
item: {
type: Object,
required: true
},
alias: {
type: String,
required: true
},
url: {
type: String,
required: true
},
config: {
type: Object,
required: true
}
},
setup (props) {
const preSignedUrl = ref('')
const imageSource = computed(() => {
return props.isShowThumbnail && props.item.isImage
? preSignedUrl.value
: `/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`
})
const iconPath = computed(() =>
`/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`
)
async function getUrl () {
preSignedUrl.value = await window.electron.triggerRPC<any>(IRPCActionType.MANAGE_GET_PRE_SIGNED_URL, props.alias, props.config)
}
watch(() => [props.url, props.item], getUrl, { deep: true })
onMounted(getUrl)
return () => (
<ElImage src={imageSource.value} fit='contain' style='height: 100px;width: 100%;margin: 0 auto;'>
{{
placeholder: () => (
<ElIcon>
<Loading />
</ElIcon>
),
error: () => <ElImage src={iconPath.value} fit='contain' style='height: 100px;width: 100%;margin: 0 auto;' />
}}
</ElImage>
)
}
})

View File

@@ -1,26 +1,29 @@
<template>
<el-image
:src="imageSource"
fit="contain"
style="height: 100px; width: 100%; margin: 0 auto"
>
<template #placeholder>
<el-icon>
<Loading />
</el-icon>
</template>
<template #error>
<el-image
:src="iconPath"
fit="contain"
style="height: 100px; width: 100%; margin: 0 auto"
/>
</template>
</el-image>
<div class="image-container">
<div
v-if="isLoading"
class="loading-placeholder"
>
<div class="loading-spinner" />
</div>
<img
v-else-if="!hasError"
:src="imageSource"
alt=""
class="image"
@load="handleImageLoad"
@error="handleImageError"
>
<img
v-else
:src="iconPath"
alt=""
class="image"
>
</div>
</template>
<script lang="ts" setup>
import { Loading } from '@element-plus/icons-vue'
import { computed, onMounted, ref, watch } from 'vue'
import { getFileIconPath } from '@/manage/utils/common'
@@ -29,6 +32,8 @@ import { formatEndpoint } from '@/utils/common'
const base64Url = ref('')
const success = ref(false)
const isLoading = ref(true)
const hasError = ref(false)
const props = defineProps<{
item: {
@@ -72,22 +77,78 @@ async function getWebdavHeader (key: string) {
const fetchImage = async () => {
try {
isLoading.value = true
hasError.value = false
const headers = await getWebdavHeader(props.item.key)
const res = await fetch(props.url, { method: 'GET', headers })
if (res.status >= 200 && res.status < 300) {
const blob = await res.blob()
success.value = true
base64Url.value = URL.createObjectURL(blob)
isLoading.value = false
} else {
throw new Error('Network response was not ok.')
}
} catch (err) {
success.value = false
hasError.value = true
isLoading.value = false
console.log(err)
}
}
const handleImageLoad = () => {
isLoading.value = false
hasError.value = false
}
const handleImageError = () => {
isLoading.value = false
hasError.value = true
}
watch(() => [props.url, props.item], fetchImage, { deep: true })
onMounted(fetchImage)
</script>
<style scoped>
.image-container {
height: 100px;
width: 100%;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.image {
max-height: 100%;
max-width: 100%;
object-fit: contain;
display: block;
}
.loading-placeholder {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.loading-spinner {
width: 24px;
height: 24px;
border: 2px solid #e4e7ed;
border-top: 2px solid #409eff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>

View File

@@ -1,95 +0,0 @@
import { Loading } from '@element-plus/icons-vue'
import { ElIcon, ElImage } from 'element-plus'
import { computed, defineComponent, onMounted, ref, watch } from 'vue'
import { getFileIconPath } from '@/manage/utils/common'
import { getAuthHeader } from '@/manage/utils/digestAuth'
import { formatEndpoint } from '@/utils/common'
export default defineComponent({
props: {
isShowThumbnail: {
type: Boolean,
required: true
},
item: {
type: Object,
required: true
},
url: {
type: String,
required: true
},
config: {
type: Object,
required: true
}
},
setup (props) {
const base64Url = ref('')
const success = ref(false)
const imageSource = computed(() => {
return props.isShowThumbnail && props.item.isImage && success.value
? base64Url.value
: `/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`
})
const iconPath = computed(() =>
`/assets/icons/${getFileIconPath(props.item.fileName ?? '')}`
)
async function getWebdavHeader (key: string) {
let headers = {} as any
if (props.config.authType === 'digest') {
const authHeader = await getAuthHeader(
'GET',
formatEndpoint(props.config.endpoint, props.config.sslEnabled || false),
`/${key.replace(/^\//, '')}`,
props.config.username,
props.config.password
)
headers = {
Authorization: authHeader
}
} else {
headers = {
Authorization: 'Basic ' + Buffer.from(`${props.config.username}:${props.config.password}`).toString('base64')
}
}
return headers
}
const fetchImage = async () => {
try {
const headers = await getWebdavHeader(props.item.key)
const res = await fetch(props.url, { method: 'GET', headers })
if (res.status >= 200 && res.status < 300) {
const blob = await res.blob()
success.value = true
base64Url.value = URL.createObjectURL(blob)
} else {
throw new Error('Network response was not ok.')
}
} catch (err) {
success.value = false
console.log(err)
}
}
watch(() => [props.url, props.item], fetchImage, { deep: true })
onMounted(fetchImage)
return () => (
<ElImage src={imageSource.value} fit='contain' style='height: 100px;width: 100%;margin: 0 auto;'>
{{
placeholder: () => (
<ElIcon>
<Loading />
</ElIcon>
),
error: () => <ElImage src={iconPath.value} fit='contain' style='height: 100px;width: 100%;margin: 0 auto;' />
}}
</ElImage>
)
}
})

View File

@@ -213,7 +213,6 @@ import {
TransitionChild,
TransitionRoot
} from '@headlessui/vue'
import { ElMessage as $message } from 'element-plus'
import { pick } from 'lodash-es'
import { CheckIcon, ChevronDownIcon, CopyIcon, DatabaseIcon, FolderIcon, Info, PieChartIcon, PlugIcon, Settings, UploadIcon } from 'lucide-vue-next'
import QrcodeVue from 'qrcode.vue'
@@ -221,6 +220,7 @@ import pkg from 'root/package.json'
import { computed, nextTick, onBeforeMount, reactive, Ref, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import useMessage from '@/hooks/useMessage'
import * as config from '@/router/config'
import { SHOW_MAIN_PAGE_QRCODE } from '@/utils/constant'
import { getConfig } from '@/utils/dataSender'
@@ -231,6 +231,7 @@ import ThemeSwitcher from './ui/ThemeSwitcher.vue'
const version = ref(pkg.version)
const { t } = useI18n()
const message = useMessage()
const routerConfig = reactive(config)
const qrcodeVisible = ref(false)
const choosedPicBedForQRCode: Ref<string[]> = ref([])
@@ -264,7 +265,7 @@ function openMenu () {
function handleCopyPicBedConfig () {
window.electron.clipboard.writeText(picBedConfigString.value)
$message.success(t('navigation.copySuccess'))
message.success(t('navigation.copySuccess'))
}
const navigationItems = computed(() => [

View File

@@ -1,11 +1,9 @@
import 'element-plus/dist/index.css'
import 'video.js/dist/video-js.css'
import 'highlight.js/styles/stackoverflow-light.css'
import 'highlight.js/lib/common'
import hljsVuePlugin from '@highlightjs/vue-plugin'
import VueVideoPlayer from '@videojs-player/vue'
import ElementUI from 'element-plus'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import { createApp } from 'vue'
@@ -49,7 +47,6 @@ app.use(VueLazyLoad, {
delay: 500
})
app.use(i18n)
app.use(ElementUI)
app.use(router)
app.use(store)
app.use(pinia)

View File

@@ -1,46 +0,0 @@
<template>
<el-form-item>
<template #label>
<span style="position: absolute; left: 0">
<span
v-for="(segment, index) in segments"
:key="index"
:style="segment.style"
>
{{ segment.text }}
</span>
<el-tooltip
v-if="tooltip"
:content="tooltip"
effect="dark"
placement="right"
:persistent="false"
teleported
>
<el-icon>
<InfoFilled />
</el-icon>
</el-tooltip>
</span>
</template>
<el-switch
v-model="value"
:active-text="activeText"
:inactive-text="inactiveText"
style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949; position: absolute; right: 0"
/>
</el-form-item>
</template>
<script lang="ts" setup>
import { InfoFilled } from '@element-plus/icons-vue'
defineProps<{
tooltip?: string
activeText?: string
inactiveText?: string
segments?: { text: string; style: string }[]
}>()
const value = defineModel<boolean>()
</script>