安装进度弹窗更新为使用独立的组件实现

This commit is contained in:
jingrow 2025-10-27 02:19:18 +08:00
parent 6a90f5ec39
commit 8c21e8cd31
3 changed files with 113 additions and 94 deletions

View File

@ -115,26 +115,13 @@
</div> </div>
<!-- 安装进度弹窗 --> <!-- 安装进度弹窗 -->
<n-modal v-model:show="showProgressModal" preset="card" style="width: 500px"> <InstallProgressModal
<template #header> v-model="showProgressModal"
<h3>{{ t('Installing App') }}</h3> :progress="installProgress"
</template> :message="installMessage"
:status="installStatus"
<div class="progress-content"> :installing="installing"
<n-progress />
:percentage="installProgress"
:status="installStatus"
:show-indicator="true"
/>
<n-text class="progress-text">{{ installMessage }}</n-text>
</div>
<template #action>
<n-button @click="showProgressModal = false" :disabled="installing">
{{ installing ? t('Installing...') : t('Close') }}
</n-button>
</template>
</n-modal>
</div> </div>
</template> </template>
@ -142,10 +129,11 @@
import { ref, onMounted, computed } from 'vue' import { ref, onMounted, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { get_session_api_headers } from '@/shared/api/auth' import { get_session_api_headers } from '@/shared/api/auth'
import { NButton, NIcon, NSpin, NEmpty, useMessage, NModal, NProgress, NText } from 'naive-ui' import { NButton, NIcon, NSpin, NEmpty, useMessage } from 'naive-ui'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
import axios from 'axios' import axios from 'axios'
import { t } from '@/shared/i18n' import { t } from '@/shared/i18n'
import InstallProgressModal from './InstallProgressModal.vue'
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
@ -216,11 +204,14 @@ async function installApp() {
installStatus.value = 'info' installStatus.value = 'info'
showProgressModal.value = true showProgressModal.value = true
// //
setTimeout(() => { setTimeout(() => {
installProgress.value = 30 installProgress.value = 20
installMessage.value = t('正在安装应用...') }, 300)
}, 500)
//
installProgress.value = 30
installMessage.value = t('正在安装应用...')
const response = await axios.post('/jingrow/install-from-url', new URLSearchParams({ const response = await axios.post('/jingrow/install-from-url', new URLSearchParams({
url: app.value.file_url url: app.value.file_url
@ -231,16 +222,12 @@ async function installApp() {
} }
}) })
setTimeout(() => { //
installProgress.value = 80 installProgress.value = 100
installMessage.value = t('正在同步数据库...')
}, 1000)
setTimeout(() => {
installProgress.value = 100
}, 1500)
if (response.data.success) { if (response.data.success) {
//
installing.value = false
installStatus.value = 'success' installStatus.value = 'success'
installMessage.value = t('应用安装成功!') installMessage.value = t('应用安装成功!')
message.success(t('应用安装成功')) message.success(t('应用安装成功'))
@ -253,6 +240,7 @@ async function installApp() {
} }
} catch (error: any) { } catch (error: any) {
console.error('Install app error:', error) console.error('Install app error:', error)
installing.value = false
installStatus.value = 'error' installStatus.value = 'error'
installMessage.value = error.response?.data?.detail || error.message || t('安装失败') installMessage.value = error.response?.data?.detail || error.message || t('安装失败')
message.error(error.response?.data?.detail || t('安装失败')) message.error(error.response?.data?.detail || t('安装失败'))
@ -260,8 +248,6 @@ async function installApp() {
setTimeout(() => { setTimeout(() => {
showProgressModal.value = false showProgressModal.value = false
}, 3000) }, 3000)
} finally {
installing.value = false
} }
} }
@ -492,18 +478,6 @@ onMounted(() => {
font-style: italic; font-style: italic;
} }
.progress-content {
display: flex;
flex-direction: column;
gap: 16px;
padding: 20px 0;
}
.progress-text {
text-align: center;
color: #666;
}
@media (max-width: 768px) { @media (max-width: 768px) {
.app-card { .app-card {
padding: 20px; padding: 20px;

View File

@ -132,37 +132,25 @@
</div> </div>
<!-- 安装进度弹窗 --> <!-- 安装进度弹窗 -->
<n-modal v-model:show="showProgressModal" preset="card" style="width: 500px"> <InstallProgressModal
<template #header> v-model="showProgressModal"
<h3>{{ t('Installing App') }}</h3> :progress="installProgress"
</template> :message="installMessage"
:status="installStatus"
<div class="progress-content"> :installing="installing"
<n-progress />
:percentage="installProgress"
:status="installStatus"
:show-indicator="true"
/>
<n-text class="progress-text">{{ installMessage }}</n-text>
</div>
<template #action>
<n-button @click="showProgressModal = false" :disabled="installing">
{{ installing ? t('Installing...') : t('Close') }}
</n-button>
</template>
</n-modal>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, computed, watch } from 'vue' import { ref, onMounted, computed, watch } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { NInput, NButton, NIcon, NSpin, NEmpty, NSelect, NPagination, useMessage, NModal, NProgress, NText } from 'naive-ui' import { NInput, NButton, NIcon, NSpin, NEmpty, NSelect, NPagination, useMessage } from 'naive-ui'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
import axios from 'axios' import axios from 'axios'
import { t } from '@/shared/i18n' import { t } from '@/shared/i18n'
import { get_session_api_headers } from '@/shared/api/auth' import { get_session_api_headers } from '@/shared/api/auth'
import InstallProgressModal from './InstallProgressModal.vue'
const message = useMessage() const message = useMessage()
const router = useRouter() const router = useRouter()
@ -255,11 +243,14 @@ async function installApp(app: any) {
installStatus.value = 'info' installStatus.value = 'info'
showProgressModal.value = true showProgressModal.value = true
// //
setTimeout(() => { setTimeout(() => {
installProgress.value = 30 installProgress.value = 20
installMessage.value = t('正在安装应用...') }, 300)
}, 500)
//
installProgress.value = 30
installMessage.value = t('正在安装应用...')
const response = await axios.post('/jingrow/install-from-url', new URLSearchParams({ const response = await axios.post('/jingrow/install-from-url', new URLSearchParams({
url: app.file_url url: app.file_url
@ -270,16 +261,12 @@ async function installApp(app: any) {
} }
}) })
setTimeout(() => { //
installProgress.value = 80 installProgress.value = 100
installMessage.value = t('正在同步数据库...')
}, 1000)
setTimeout(() => {
installProgress.value = 100
}, 1500)
if (response.data.success) { if (response.data.success) {
//
installing.value = false
installStatus.value = 'success' installStatus.value = 'success'
installMessage.value = t('应用安装成功!') installMessage.value = t('应用安装成功!')
message.success(t('应用安装成功')) message.success(t('应用安装成功'))
@ -292,6 +279,7 @@ async function installApp(app: any) {
} }
} catch (error: any) { } catch (error: any) {
console.error('Install app error:', error) console.error('Install app error:', error)
installing.value = false
installStatus.value = 'error' installStatus.value = 'error'
installMessage.value = error.response?.data?.detail || error.message || t('安装失败') installMessage.value = error.response?.data?.detail || error.message || t('安装失败')
message.error(error.response?.data?.detail || t('安装失败')) message.error(error.response?.data?.detail || t('安装失败'))
@ -299,8 +287,6 @@ async function installApp(app: any) {
setTimeout(() => { setTimeout(() => {
showProgressModal.value = false showProgressModal.value = false
}, 3000) }, 3000)
} finally {
installing.value = false
} }
} }
@ -653,16 +639,4 @@ watch(() => localStorage.getItem('itemsPerPage'), (newValue) => {
height: 180px; height: 180px;
} }
} }
.progress-content {
display: flex;
flex-direction: column;
gap: 16px;
padding: 20px 0;
}
.progress-text {
text-align: center;
color: #666;
}
</style> </style>

View File

@ -0,0 +1,71 @@
<template>
<n-modal v-model:show="show" preset="card" style="width: 500px">
<template #header>
<h3>{{ t('Installing App') }}</h3>
</template>
<div class="progress-content">
<n-progress
:percentage="progress"
:show-indicator="true"
color="#10b981"
/>
<n-text class="progress-text">{{ message }}</n-text>
</div>
<template #action>
<n-button @click="handleClose" :disabled="installing">
{{ installing ? t('Installing...') : t('Close') }}
</n-button>
</template>
</n-modal>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { NModal, NProgress, NText, NButton, useMessage } from 'naive-ui'
import { t } from '@/shared/i18n'
interface Props {
modelValue: boolean
progress: number
message: string
status: 'success' | 'error' | 'info'
installing: boolean
}
const props = defineProps<Props>()
const emit = defineEmits<{
'update:modelValue': [value: boolean]
}>()
const show = ref(props.modelValue)
watch(() => props.modelValue, (newVal) => {
show.value = newVal
})
watch(show, (newVal) => {
emit('update:modelValue', newVal)
})
function handleClose() {
if (!props.installing) {
show.value = false
}
}
</script>
<style scoped>
.progress-content {
display: flex;
flex-direction: column;
gap: 16px;
padding: 20px 0;
}
.progress-text {
text-align: center;
color: #666;
}
</style>