mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-07-24 07:09:31 +08:00
🐛 Fix(custom): fix static assets bugs
This commit is contained in:
@@ -1,115 +1,115 @@
|
||||
<template>
|
||||
<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 { 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: {
|
||||
isImage: boolean
|
||||
fileName: string
|
||||
}
|
||||
localPath: string
|
||||
}>()
|
||||
|
||||
const createBase64Image = async () => {
|
||||
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 () => {
|
||||
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>
|
||||
<template>
|
||||
<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 { 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: {
|
||||
isImage: boolean
|
||||
fileName: string
|
||||
}
|
||||
localPath: string
|
||||
}>()
|
||||
|
||||
const createBase64Image = async () => {
|
||||
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 () => {
|
||||
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>
|
||||
|
||||
@@ -1,123 +1,123 @@
|
||||
<template>
|
||||
<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 { 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: {
|
||||
key: string
|
||||
isImage: boolean
|
||||
fileName: string | null | undefined
|
||||
}
|
||||
alias: string
|
||||
url: string
|
||||
config: any
|
||||
isShowThumbnail: boolean
|
||||
}>()
|
||||
|
||||
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 () {
|
||||
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>
|
||||
<template>
|
||||
<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 { 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: {
|
||||
key: string
|
||||
isImage: boolean
|
||||
fileName: string | null | undefined
|
||||
}
|
||||
alias: string
|
||||
url: string
|
||||
config: any
|
||||
isShowThumbnail: boolean
|
||||
}>()
|
||||
|
||||
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 () {
|
||||
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>
|
||||
|
||||
@@ -1,154 +1,154 @@
|
||||
<template>
|
||||
<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 { computed, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import { getFileIconPath } from '@/manage/utils/common'
|
||||
import { getAuthHeader } from '@/manage/utils/digestAuth'
|
||||
import { formatEndpoint } from '@/utils/common'
|
||||
|
||||
const base64Url = ref('')
|
||||
const success = ref(false)
|
||||
const isLoading = ref(true)
|
||||
const hasError = ref(false)
|
||||
|
||||
const props = defineProps<{
|
||||
item: {
|
||||
key: string
|
||||
isImage: boolean
|
||||
fileName: string | null | undefined
|
||||
}
|
||||
url: string
|
||||
config: any
|
||||
isShowThumbnail: boolean
|
||||
}>()
|
||||
|
||||
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 {
|
||||
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>
|
||||
<template>
|
||||
<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 { computed, onMounted, ref, watch } from 'vue'
|
||||
|
||||
import { getFileIconPath } from '@/manage/utils/common'
|
||||
import { getAuthHeader } from '@/manage/utils/digestAuth'
|
||||
import { formatEndpoint } from '@/utils/common'
|
||||
|
||||
const base64Url = ref('')
|
||||
const success = ref(false)
|
||||
const isLoading = ref(true)
|
||||
const hasError = ref(false)
|
||||
|
||||
const props = defineProps<{
|
||||
item: {
|
||||
key: string
|
||||
isImage: boolean
|
||||
fileName: string | null | undefined
|
||||
}
|
||||
url: string
|
||||
config: any
|
||||
isShowThumbnail: boolean
|
||||
}>()
|
||||
|
||||
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 {
|
||||
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>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="title-left">
|
||||
<div class="app-icon">
|
||||
<img
|
||||
src="/roundLogo.png"
|
||||
:src="defaultLogo"
|
||||
alt="App Icon"
|
||||
width="20"
|
||||
height="20"
|
||||
@@ -75,13 +75,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { MinusIcon, PinIcon, ShrinkIcon, XIcon } from 'lucide-vue-next'
|
||||
import { onBeforeMount, onBeforeUnmount, ref } from 'vue'
|
||||
import { computed, onBeforeMount, onBeforeUnmount, ref } from 'vue'
|
||||
|
||||
import { IRPCActionType } from '@/utils/enum'
|
||||
|
||||
const isShowprogress = ref(false)
|
||||
const progress = ref(0)
|
||||
const isAlwaysOnTop = ref(false)
|
||||
const defaultLogo = computed(() => `${import.meta.env.BASE_URL}roundLogo.png`)
|
||||
|
||||
function setAlwaysOnTop () {
|
||||
isAlwaysOnTop.value = !isAlwaysOnTop.value
|
||||
|
||||
Reference in New Issue
Block a user