mirror of
https://gitee.com/niucloud-team/niucloud-admin.git
synced 2025-12-13 11:12:49 +00:00
update
This commit is contained in:
parent
ecbef463d5
commit
80ecfb0ee0
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
@ -1,6 +1,6 @@
|
||||
{
|
||||
"app": "应用中心",
|
||||
"descriptionLeft": "请点击",
|
||||
"descriptionLeft": "暂无安装任何应用,请点击",
|
||||
"link": "安装应用",
|
||||
"descriptionRight": "安装使用",
|
||||
"niucloud": "Niucloud官网",
|
||||
|
||||
@ -51,12 +51,10 @@
|
||||
"authTips": "云安装需先绑定授权码,如果已有授权请先进行绑定,没有授权可到niucloud官网购买云服务之后再进行操作",
|
||||
"toBind": "绑定授权",
|
||||
"toNiucloud": "去niucloud官网",
|
||||
|
||||
"descriptionLeft": "暂无任何应用,马上去",
|
||||
"link": "官方应用市场",
|
||||
"descriptionRight": "逛逛",
|
||||
"installed-empty": "暂未安装任何应用,请先安装",
|
||||
|
||||
"siteAddressTips": "授权域名不匹配",
|
||||
"authCodePlaceholder": "请输入授权码",
|
||||
"authSecretPlaceholder": "请输入授权秘钥",
|
||||
@ -64,5 +62,6 @@
|
||||
"notHaveAuth": "还没有授权?去购买",
|
||||
"authInfoTips": "授权码和授权秘钥可在Niucloud官网我的授权 授权详情中查看",
|
||||
"addonUninstall": "插件卸载",
|
||||
"noAddon":"暂无插件"
|
||||
"appIdentification":"应用标识",
|
||||
"tipText":"标识指开发应用或插件的文件夹名称"
|
||||
}
|
||||
@ -40,7 +40,7 @@
|
||||
<div class="flex flex-1 flex-wrap justify-end relative">
|
||||
<el-button class="w-[154px] !h-[48px] mt-[8px]" type="primary"
|
||||
@click="authCodeApproveFn">授权码认证</el-button>
|
||||
<el-popover ref="getAuthCodeDialog" placement="bottom-start" :width="478" trigger="click"
|
||||
<el-popover ref="getAuthCodeDialog" placement="bottom" :width="478" trigger="click"
|
||||
class="mt-[8px]">
|
||||
<div class="px-[18px] py-[8px]">
|
||||
<p class="leading-[32px] text-[14px]">您在官方应用市场购买任意一款应用,即可获得授权码。输入正确授权码认证通过后,即可支持在线升级和其它相关服务
|
||||
@ -166,13 +166,14 @@ const save = async (formEl: FormInstance | undefined) => {
|
||||
})
|
||||
.catch(() => {
|
||||
saveLoading.value = false
|
||||
authCodeApproveDialog.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const market = () => {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
|
||||
const versions = ref('')
|
||||
|
||||
@ -605,7 +605,7 @@ const authElMessageBox = () => {
|
||||
router.push({ path: '/app/authorize' })
|
||||
}).catch((action: string) => {
|
||||
if (action === 'cancel') {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -665,7 +665,7 @@ const uninstallAddonFn = (key: string) => {
|
||||
}
|
||||
|
||||
const market = () => {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -214,7 +214,7 @@ const authElMessageBox = () => {
|
||||
router.push({ path: '/app/authorize' })
|
||||
}).catch((action: string) => {
|
||||
if (action === 'cancel') {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -78,8 +78,6 @@ const searchFormRef = ref<FormInstance>()
|
||||
// 选中数据
|
||||
const selectData = ref<any[]>([])
|
||||
|
||||
// 字典数据
|
||||
|
||||
/**
|
||||
* 获取商品标签列表
|
||||
*/
|
||||
|
||||
@ -1,164 +1,168 @@
|
||||
<template>
|
||||
<div class="box-border pt-[68px] px-[76px] overview-top" v-loading="loading">
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<div class="font-[600] text-[26px] text-[#222] leading-[37px]">{{ t('app') }}</div>
|
||||
<div class="font-[500] text-[14px] text-[#222] leading-[20px] mt-[12px]">{{ t('versionInfo') }} {{ t('currentVersion') }} {{ versions }}</div>
|
||||
<div class="box-border pt-[68px] px-[76px] overview-top" v-loading="loading">
|
||||
<div v-if="detail.appList && !loading">
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<div class="font-[600] text-[26px] text-[#222] leading-[37px]">{{ t('app') }}</div>
|
||||
<div class="font-[500] text-[14px] text-[#222] leading-[20px] mt-[12px]">{{ t('versionInfo') }} {{
|
||||
t('currentVersion') }} {{ versions }}</div>
|
||||
</div>
|
||||
<el-button @click="toAppStore" class="px-[15px]">
|
||||
<div class="mr-[9px] text-[#3F3F3F] iconfont iconxiazai01"></div>
|
||||
<span class="font-[600] text-[14px] text-[#222] leading-[20px]">{{ t('appStore') }}</span>
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button @click="toAppStore" class="px-[15px]">
|
||||
<div class="mr-[9px] text-[#3F3F3F] iconfont iconxiazai01"></div>
|
||||
<span class="font-[600] text-[14px] text-[#222] leading-[20px]">{{t('appStore')}}</span>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="flex flex-wrap mt-[40px]">
|
||||
<template v-for="(item, index) in detail.appList" :key="index">
|
||||
<div class="app-item w-[280px] box-border py-[42px] px-[32px] bg-[#fff] rounded-[8px] cursor-pointer mr-[20px] mb-[20px] "
|
||||
@click="itemPath(item)">
|
||||
<div class="flex items-center">
|
||||
<el-image class="w-[44px] h-[44px] rounded-[8px]" :src="img(item.icon)" fit="contain">
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<img class="w-[40px] h-[40px] rounded-[8px]"
|
||||
src="@/app/assets/images/app_store/app_store_default.png"/>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div class="ml-[12px] flex-1">
|
||||
<div class="font-[600] text-[14px] text-[#222] leading-[20px]">{{ item.title }}</div>
|
||||
<div class="font-[500] text-[13px] text-[#6D7278] leading-[18px] mt-[6px] w-[160px] truncate">{{ item.desc }}</div>
|
||||
<div class="flex flex-wrap mt-[40px]">
|
||||
<template v-for="(item, index) in detail.appList" :key="index">
|
||||
<div class="app-item w-[280px] box-border py-[42px] px-[32px] bg-[#fff] rounded-[8px] cursor-pointer mr-[20px] mb-[20px] "
|
||||
@click="itemPath(item)">
|
||||
<div class="flex items-center">
|
||||
<el-image class="w-[44px] h-[44px] rounded-[8px]" :src="img(item.icon)" fit="contain">
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<img class="w-[40px] h-[40px] rounded-[8px]"
|
||||
src="@/app/assets/images/app_store/app_store_default.png" />
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div class="ml-[12px] flex-1">
|
||||
<div class="font-[600] text-[14px] text-[#222] leading-[20px]">{{ item.title }}</div>
|
||||
<el-tooltip class="box-item" effect="light" :content="item.desc" placement="bottom-start">
|
||||
<div
|
||||
class="font-[500] text-[13px] text-[#6D7278] leading-[18px] mt-[6px] w-[160px] truncate">
|
||||
{{
|
||||
item.desc }}</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<el-empty class="mx-auto overview-empty" v-if="!detail.appList.length && !loading">
|
||||
<template #image>
|
||||
<div class="w-[230px] mx-auto">
|
||||
<img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt="">
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<p class="flex items-center">
|
||||
<span>{{ t('descriptionLeft') }}</span>
|
||||
<el-link type="primary" @click="toAppStore" class="mx-[5px]">{{ t('link') }}</el-link>
|
||||
<span>{{ t('descriptionRight') }}</span>
|
||||
</p>
|
||||
</template>
|
||||
</el-empty>
|
||||
|
||||
<el-empty class="mx-auto overview-empty" v-if="!detail.appList.length && !loading">
|
||||
<template #image>
|
||||
<div class="w-[230px] mx-auto">
|
||||
<img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt="">
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<p class="flex items-center">
|
||||
<span>{{ t('descriptionLeft') }}</span>
|
||||
<el-link type="primary" @click="toAppStore" class="mx-[5px]">{{ t('link') }}</el-link>
|
||||
<span>{{ t('descriptionRight') }}</span>
|
||||
</p>
|
||||
</template>
|
||||
</el-empty>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted , computed} from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getAuthaddon, getVersions} from '@/app/api/auth'
|
||||
import { img} from '@/utils/common'
|
||||
import {useRouter} from 'vue-router'
|
||||
import storage from '@/utils/storage'
|
||||
import {findFirstValidRoute} from '@/router/routers'
|
||||
import {UserFilled} from '@element-plus/icons-vue'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
const router = useRouter()
|
||||
import { reactive, ref, onMounted, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getAuthaddon, getVersions } from '@/app/api/auth'
|
||||
import { img } from '@/utils/common'
|
||||
import { useRouter } from 'vue-router'
|
||||
import storage from '@/utils/storage'
|
||||
import { findFirstValidRoute } from '@/router/routers'
|
||||
import { UserFilled } from '@element-plus/icons-vue'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
const router = useRouter()
|
||||
|
||||
const userStore = useUserStore()
|
||||
const loading = ref(true)
|
||||
const detail = reactive({
|
||||
appList: []
|
||||
})
|
||||
const appLink: any = ref({})
|
||||
|
||||
const getAuthaddonFn = () => {
|
||||
loading.value = true
|
||||
getAuthaddon().then(res => {
|
||||
res.data.forEach((item: any, index) => {
|
||||
if (item.type == 'app') {
|
||||
detail.appList.push(item)
|
||||
}
|
||||
})
|
||||
userStore.routers.forEach((item, index) => {
|
||||
if (item.children && item.children.length) {
|
||||
item.name = findFirstValidRoute(item.children)
|
||||
appLink.value[item.meta.app] = findFirstValidRoute(item.children)
|
||||
} else {
|
||||
appLink.value[item.meta.app] = item.name
|
||||
}
|
||||
})
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
|
||||
const userStore = useUserStore()
|
||||
const loading = ref(true)
|
||||
const detail = reactive({
|
||||
appList: []
|
||||
})
|
||||
const appLink: any = ref({})
|
||||
}
|
||||
|
||||
const getAuthaddonFn = () => {
|
||||
loading.value = true
|
||||
getAuthaddon().then(res => {
|
||||
res.data.forEach((item: any, index) => {
|
||||
if (item.type == 'app') {
|
||||
detail.appList.push(item)
|
||||
}
|
||||
})
|
||||
getAuthaddonFn()
|
||||
|
||||
userStore.routers.forEach((item, index) => {
|
||||
if (item.children && item.children.length) {
|
||||
item.name = findFirstValidRoute(item.children)
|
||||
appLink.value[item.meta.app] = findFirstValidRoute(item.children)
|
||||
} else {
|
||||
appLink.value[item.meta.app] = item.name
|
||||
}
|
||||
})
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
const itemPath = (data: any) => {
|
||||
console.log(appLink.value)
|
||||
storage.set({ key: 'menuAppStorage', data: data.key })
|
||||
storage.set({ key: 'plugMenuTypeStorage', data: '' })
|
||||
const appMenuList = userStore.appMenuList
|
||||
appMenuList.push(data.key)
|
||||
userStore.setAppMenuList(appMenuList)
|
||||
console.log(appLink.value)
|
||||
let name: any = appLink.value[data.key]
|
||||
console.log(name)
|
||||
router.push({ name: name })
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
const goAppManage = () => {
|
||||
router.push('/app_manage')
|
||||
}
|
||||
|
||||
getAuthaddonFn()
|
||||
const goRouter = () => {
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
|
||||
const itemPath = (data: any) => {
|
||||
storage.set({key: 'menuAppStorage', data: data.key})
|
||||
storage.set({key: 'plugMenuTypeStorage', data: ''})
|
||||
// 跳转至开发者
|
||||
const toAppStore = () => {
|
||||
router.push('/app_manage/app_store')
|
||||
}
|
||||
|
||||
const appMenuList = userStore.appMenuList
|
||||
appMenuList.push(data.key)
|
||||
userStore.setAppMenuList(appMenuList)
|
||||
const goNiucloud = () => {
|
||||
window.open('https://www.niucloud.com')
|
||||
}
|
||||
|
||||
let name: any = appLink.value[data.key];
|
||||
const logout = () => {
|
||||
userStore.logout();
|
||||
}
|
||||
|
||||
router.push({name: name})
|
||||
|
||||
}
|
||||
|
||||
const goAppManage = () => {
|
||||
router.push('/app_manage')
|
||||
}
|
||||
|
||||
const goRouter = () => {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
}
|
||||
|
||||
// 跳转至开发者
|
||||
const toAppStore = () => {
|
||||
router.push('/app_manage/app_store')
|
||||
}
|
||||
|
||||
const goNiucloud = () => {
|
||||
window.open('https://www.niucloud.com')
|
||||
}
|
||||
|
||||
const logout = () => {
|
||||
userStore.logout();
|
||||
}
|
||||
|
||||
const versions = ref('')
|
||||
const getVersionsInfo = () =>{
|
||||
getVersions().then(res =>{
|
||||
versions.value = res.data.version.version
|
||||
})
|
||||
}
|
||||
getVersionsInfo()
|
||||
const versions = ref('')
|
||||
const getVersionsInfo = () => {
|
||||
getVersions().then(res => {
|
||||
versions.value = res.data.version.version
|
||||
})
|
||||
}
|
||||
getVersionsInfo()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.main-container {
|
||||
background: linear-gradient(180deg, rgba(253, 253, 253, 0.24) 0%, #FAFAFA 100%);
|
||||
min-height: calc(100vh - 64px);
|
||||
}
|
||||
.main-container {
|
||||
background: linear-gradient(180deg, rgba(253, 253, 253, 0.24) 0%, #FAFAFA 100%);
|
||||
min-height: calc(100vh - 64px);
|
||||
}
|
||||
|
||||
.overview-top{
|
||||
background-image: url('@/app/assets/images/index/overview.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.app-item {
|
||||
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
.overview-top {
|
||||
background-image: url('@/app/assets/images/index/overview.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.app-item {
|
||||
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.overview-empty .el-empty__image {
|
||||
width: auto !important;
|
||||
}
|
||||
.overview-empty .el-empty__image {
|
||||
width: auto !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="main-container w-full p-5 bg-white" v-loading="loading">
|
||||
<div class="main-container w-full px-[64px] pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[20px]">{{ t('editPersonal') }}</span>
|
||||
</div>
|
||||
@ -9,7 +9,7 @@
|
||||
<upload-image v-model="saveInfo.head_img" :limit="1" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('userName')">
|
||||
<el-input v-model="saveInfo.username" clearable class="input-width" :readonly="true"/>
|
||||
<span>{{saveInfo.username}}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('realName')">
|
||||
<el-input v-model="saveInfo.real_name" :placeholder="t('realNamePlaceholder')" clearable class="input-width" />
|
||||
|
||||
@ -77,7 +77,7 @@ const itemPath = (key: any) => {
|
||||
|
||||
}
|
||||
const goRouter = ()=>{
|
||||
window.open('https://www.niucloud.com/product/')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="main-container w-full p-[64px] bg-white" v-loading="loading">
|
||||
<div class="main-container w-full px-[64px] pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[20px]">{{ t('personal') }}</span>
|
||||
<span class="text-[14px] text-[#999] cursor-pointer" @click="toEditPersonal">{{ t('editPersonal') }}</span>
|
||||
@ -7,10 +7,10 @@
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form :model="saveInfo" label-width="90px" ref="formRef" class="page-form">
|
||||
<el-form-item :label="t('headImg')">
|
||||
<el-image class="w-[70px] h-[70px] rounded-full" :src="img(saveInfo.head_img)" fit="contain">
|
||||
<el-image class="w-[70px] h-[70px]" :src="img(saveInfo.head_img)" fit="contain">
|
||||
<template #error>
|
||||
<div class="image-slot w-[70px] h-[70px] bg-[#c0c4cc] flex items-center justify-center">
|
||||
<el-icon class="text-[45px] text-[#fff]"><UserFilled /></el-icon>
|
||||
<div class="image-slot bg-[#c0c4cc] flex items-center justify-center w-[70px] h-[70px] rounded-full">
|
||||
<el-icon class="text-[#fff] text-[35px]"><UserFilled /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
@ -27,7 +27,6 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { UserFilled } from '@element-plus/icons-vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance, FormRules, ElNotification } from 'element-plus'
|
||||
|
||||
@ -1,200 +1,296 @@
|
||||
<template>
|
||||
<div class="pt-[64px] px-[90px] app-store" v-loading="loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[26px] text-[#222] font-600">{{ t('localAppText') }}</span>
|
||||
<el-input class="w-[247px]" :placeholder="t('search')" v-model="search_name" @keyup.enter="query">
|
||||
<template #suffix>
|
||||
<el-icon class="el-input__icon cursor-pointer" size="14px" @click="query">
|
||||
<search />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
</div>
|
||||
<div class="flex mt-[24px]">
|
||||
<div :class="{ '!bg-[#000] !border-0 !text-[#fff]': activeName === 'installed' }"
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'installed'">
|
||||
{{ t('installLabel') }}
|
||||
<div v-if="info[activeName] && !loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[26px] text-[#222] font-600">{{ t('localAppText') }}</span>
|
||||
<el-input class="w-[247px]" :placeholder="t('search')" v-model="search_name" @keyup.enter="query">
|
||||
<template #suffix>
|
||||
<el-icon class="el-input__icon cursor-pointer" size="14px" @click="query">
|
||||
<search />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div :class="{ '!bg-[#000] !border-0 !text-[#fff]': activeName === 'uninstalled' }"
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'uninstalled'">
|
||||
{{ t('uninstalledLabel') }}
|
||||
</div>
|
||||
<div :class="{ '!bg-[#000] !border-0 !text-[#fff]': activeName === 'all' }"
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'all'">
|
||||
{{ t('buyLabel') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[32px]">
|
||||
<el-table v-if="localList[activeName].length" :data="info[activeName]" size="large" class="pt-[5px]">
|
||||
<template #empty>
|
||||
<span>{{ t('noAddon') }}</span>
|
||||
</template>
|
||||
<el-table-column :label="t('appName')" align="left" min-width="200">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center">
|
||||
<el-image class="w-[54px] h-[54px] flex-shrink-0" :src="row.icon" fit="contain">
|
||||
<template #error>
|
||||
<img class="w-[54px] h-[54px]" src="@/app/assets/images/icon-addon.png" alt="">
|
||||
</template>
|
||||
</el-image>
|
||||
<div class="flex flex-col justify-center pl-[20px] text-[#222] font-500 text-[13px]">
|
||||
<div class="multi-hidden leading-[20px]">{{ row.title }}</div>
|
||||
<div class="leading-[18px] mt-[6px]">{{ row.version }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="" :label="t('introduction')" align="left" min-width="200">
|
||||
<template #default="{ row }">
|
||||
<span class="text-[#222] font-500 text-[13px] multi-hidden">{{ row.desc }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('type')" align="left" width="100">
|
||||
<template #default="{ row }">
|
||||
<span class="text-[#222] font-500 text-[13px]">{{ row.type === 'app' ? t('app') : t('addon')
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="" :label="t('author')" align="left" min-width="200">
|
||||
<template #default="{ row }">
|
||||
<span class="text-[#222] font-500 text-[13px] multi-hidden">{{ row.author }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('operation')" align="right" width="180">
|
||||
<template #default="{ row }">
|
||||
|
||||
<el-button class="!text-[13px]" v-if="row.install_info && Object.keys(row.install_info)?.length"
|
||||
type="primary" link @click="uninstallAddonFn(row.key)">{{ t('unload') }}</el-button>
|
||||
|
||||
<el-button class="!text-[13px]" v-else-if="row.is_download && row.install_info <= 0" type="primary"
|
||||
link @click="installAddonFn(row.key)">{{ t('install')
|
||||
}}</el-button>
|
||||
<el-button class="!text-[13px]" v-else :loading="downloading == row.key"
|
||||
:disabled="downloading != ''" type="primary" link @click.stop="downEvent(row)">{{
|
||||
t('down') }}</el-button>
|
||||
<el-button class="!text-[13px]" type="primary" link @click="getAddonDetialFn(row)">{{ t('detail')
|
||||
}}</el-button>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty class="mx-auto overview-empty"
|
||||
v-if="!localList.installed.length && !loading && activeName == 'installed'">
|
||||
<template #image>
|
||||
<div class="w-[230px] mx-auto">
|
||||
<img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt="">
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<p class="flex items-center">{{ t('installed-empty') }}</p>
|
||||
</template>
|
||||
</el-empty>
|
||||
<el-empty class="mx-auto overview-empty"
|
||||
v-if="!localList.uninstalled.length && !loading && activeName == 'uninstalled'">
|
||||
<template #image>
|
||||
<div class="w-[230px] mx-auto">
|
||||
<img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt="">
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<p class="flex items-center">
|
||||
<span>{{ t('descriptionLeft') }}</span>
|
||||
<el-link type="primary" @click="goRouter" class="mx-[5px]">{{ t('link') }}</el-link>
|
||||
<span>{{ t('descriptionRight') }}</span>
|
||||
</p>
|
||||
</template>
|
||||
</el-empty>
|
||||
<div v-if="!localList.all.length && !loading && !authinfo && activeName == 'all'"
|
||||
class="mx-auto overview-empty flex flex-col items-center pt-14 pb-6">
|
||||
<div class="mb-[20px] text-sm text-[#888]">检测到当前账号尚未绑定授权,请先绑定授权!</div>
|
||||
<div class="flex flex-1 flex-wrap justify-center relative">
|
||||
<el-button class="w-[154px] !h-[48px] mt-[8px]" type="primary"
|
||||
@click="authCodeApproveFn">授权码认证</el-button>
|
||||
<el-popover ref="getAuthCodeDialog" placement="bottom" :width="478" trigger="click" class="mt-[8px]">
|
||||
<div class="px-[18px] py-[8px]">
|
||||
<p class="leading-[32px] text-[14px]">
|
||||
您在官方应用市场购买任意一款应用,即可获得授权码。输入正确授权码认证通过后,即可支持在线升级和其它相关服务</p>
|
||||
<div class="flex justify-end mt-[36px]">
|
||||
<el-button class="w-[182px] !h-[48px]" plain @click="market">去应用市场逛逛</el-button>
|
||||
<el-button class="w-[100px] !h-[48px]" plain
|
||||
@click="getAuthCodeDialog.hide()">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<template #reference>
|
||||
<el-button
|
||||
class="w-[154px] !h-[48px] mt-[8px] !text-[var(--el-color-primary)] hover:!text-[var(--el-color-primary)] !bg-transparent"
|
||||
plain type="primary">如何获取授权码?</el-button>
|
||||
</template>
|
||||
</el-popover>
|
||||
<div class="flex mt-[24px]">
|
||||
<div :class="{ '!bg-[#000] !border-0 !text-[#fff]': activeName === 'installed' }"
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'installed'">
|
||||
{{ t('installLabel') }}
|
||||
</div>
|
||||
<div :class="{ '!bg-[#000] !border-0 !text-[#fff]': activeName === 'uninstalled' }"
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'uninstalled'">
|
||||
{{ t('uninstalledLabel') }}
|
||||
</div>
|
||||
<div :class="{ '!bg-[#000] !border-0 !text-[#fff]': activeName === 'all' }"
|
||||
class="w-[78px] h-[30rpx] text-[14px] text-[#242424] text-center rounded-[15px] leading-[30px] bg-[#F0F0F0] border-solid border-1 border-[#E0E0E0] cursor-pointer mr-[24px]"
|
||||
@click="activeName = 'all'">
|
||||
{{ t('buyLabel') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog v-model="authCodeApproveDialog" title="授权码认证" width="400px">
|
||||
<el-form :model="formData" label-width="0" ref="formRef" :rules="formRules" class="page-form">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form-item prop="auth_code">
|
||||
<el-input v-model="formData.auth_code" :placeholder="t('authCodePlaceholder')" class="input-width"
|
||||
clearable size="large" />
|
||||
</el-form-item>
|
||||
<div class="mt-[32px]">
|
||||
<el-table v-if="localList[activeName].length" :data="info[activeName]" size="large" class="pt-[5px]">
|
||||
<el-table-column :label="t('appName')" align="left" width="320">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center" :class="{'cursor-pointer': row.type == 'app' && Object.keys(row.install_info).length}" @click="itemPath(row)">
|
||||
<el-image class="w-[54px] h-[54px]" :src="row.icon" fit="contain">
|
||||
<template #error>
|
||||
<img class="w-[54px] h-[54px]" src="@/app/assets/images/icon-addon.png" alt="">
|
||||
</template>
|
||||
</el-image>
|
||||
<div
|
||||
class="flex flex-col justify-center h-[54px] pl-[20px] text-[#222] font-500 text-[13px]">
|
||||
<div class="w-[236px] truncate leading-[18px]">{{ row.title }}</div>
|
||||
<div class="w-[236px] truncate leading-[18px] mt-[6px]">{{ row.version }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" min-width="120">
|
||||
<template #header>
|
||||
<div class="flex items-center">
|
||||
<span class="text-[#222] font-500 text-[13px] mr-[5px]">{{ t('appIdentification') }}</span>
|
||||
<el-tooltip class="box-item" effect="light" :content="t('tipText')" placement="bottom">
|
||||
<el-icon class="cursor-pointer text-[16px] text-[#a9a9a9]">
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="{ row }">
|
||||
<span class="text-[#222] font-500 text-[13px]">{{ row.key }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="" :label="t('introduction')" align="left" min-width="200">
|
||||
<template #default="{ row }">
|
||||
<span class="text-[#222] font-500 text-[13px] multi-hidden">{{ row.desc }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('type')" align="left" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<span class="text-[#222] font-500 text-[13px]">{{ row.type === 'app' ? t('app') : t('addon')
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="" :label="t('author')" align="left" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<span class="text-[#222] font-500 text-[13px]">{{ row.author }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" width="150">
|
||||
<template #default="{ row }">
|
||||
<el-button class="!text-[13px]" type="primary" link @click="getAddonDetialFn(row)">{{
|
||||
t('detail') }}</el-button>
|
||||
<el-button class="!text-[13px]" v-if="row.install_info && Object.keys(row.install_info)?.length"
|
||||
type="primary" link @click="uninstallAddonFn(row.key)">{{ t('unload') }}</el-button>
|
||||
|
||||
<div class="mt-[20px]">
|
||||
<el-form-item prop="auth_secret">
|
||||
<el-input v-model="formData.auth_secret" clearable :placeholder="t('authSecretPlaceholder')"
|
||||
class="input-width" size="large" />
|
||||
<el-button class="!text-[13px]" v-else-if="row.is_download && row.install_info <= 0"
|
||||
type="primary" link @click="installAddonFn(row.key)">{{ t('install')
|
||||
}}</el-button>
|
||||
<el-button class="!text-[13px]" v-else :loading="downloading == row.key"
|
||||
:disabled="downloading != ''" type="primary" link @click.stop="downEvent(row)">{{
|
||||
t('down') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty class="mx-auto overview-empty"
|
||||
v-if="!localList.installed.length && !loading && activeName == 'installed'">
|
||||
<template #image>
|
||||
<div class="w-[230px] mx-auto">
|
||||
<img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt="">
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<p class="flex items-center">{{ t('installed-empty') }}</p>
|
||||
</template>
|
||||
</el-empty>
|
||||
<el-empty class="mx-auto overview-empty"
|
||||
v-if="!localList.uninstalled.length && !loading && activeName == 'uninstalled'">
|
||||
<template #image>
|
||||
<div class="w-[230px] mx-auto">
|
||||
<img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt="">
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<p class="flex items-center">
|
||||
<span>{{ t('descriptionLeft') }}</span>
|
||||
<el-link type="primary" @click="goRouter" class="mx-[5px]">{{ t('link') }}</el-link>
|
||||
<span>{{ t('descriptionRight') }}</span>
|
||||
</p>
|
||||
</template>
|
||||
</el-empty>
|
||||
<div v-if="!localList.all.length && !loading && !authinfo && activeName == 'all'"
|
||||
class="mx-auto overview-empty flex flex-col items-center pt-14 pb-6">
|
||||
<div class="mb-[20px] text-sm text-[#888]">检测到当前账号尚未绑定授权,请先绑定授权!</div>
|
||||
<div class="flex flex-1 flex-wrap justify-center relative">
|
||||
<el-button class="w-[154px] !h-[48px] mt-[8px]" type="primary"
|
||||
@click="authCodeApproveFn">授权码认证</el-button>
|
||||
<el-popover ref="getAuthCodeDialog" placement="bottom" :width="478" trigger="click"
|
||||
class="mt-[8px]">
|
||||
<div class="px-[18px] py-[8px]">
|
||||
<p class="leading-[32px] text-[14px]">
|
||||
您在官方应用市场购买任意一款应用,即可获得授权码。输入正确授权码认证通过后,即可支持在线升级和其它相关服务</p>
|
||||
<div class="flex justify-end mt-[36px]">
|
||||
<el-button class="w-[182px] !h-[48px]" plain @click="market">去应用市场逛逛</el-button>
|
||||
<el-button class="w-[100px] !h-[48px]" plain
|
||||
@click="getAuthCodeDialog.hide()">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<template #reference>
|
||||
<el-button
|
||||
class="w-[154px] !h-[48px] mt-[8px] !text-[var(--el-color-primary)] hover:!text-[var(--el-color-primary)] !bg-transparent"
|
||||
plain type="primary">如何获取授权码?</el-button>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog v-model="authCodeApproveDialog" title="授权码认证" width="400px">
|
||||
<el-form :model="formData" label-width="0" ref="formRef" :rules="formRules" class="page-form">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form-item prop="auth_code">
|
||||
<el-input v-model="formData.auth_code" :placeholder="t('authCodePlaceholder')"
|
||||
class="input-width" clearable size="large" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="text-sm mt-[10px] text-info">{{ t('authInfoTips') }}</div>
|
||||
<div class="mt-[20px]">
|
||||
<el-form-item prop="auth_secret">
|
||||
<el-input v-model="formData.auth_secret" clearable :placeholder="t('authSecretPlaceholder')"
|
||||
class="input-width" size="large" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="mt-[20px]">
|
||||
<el-button type="primary" class="w-full" size="large" :loading="saveLoading"
|
||||
@click="save(formRef)">{{ t('confirm') }}</el-button>
|
||||
</div>
|
||||
<div class="mt-[10px] text-right">
|
||||
<el-button type="primary" link @click="market">{{ t('notHaveAuth') }}</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<!-- 详情 -->
|
||||
<el-dialog v-model="appStoreShowDialog" :title="t('plugDetail')" width="500px" :destroy-on-close="true">
|
||||
<el-form :model="appStoreInfo" label-width="120px" ref="formRef" class="page-form">
|
||||
<el-form-item :label="t('title')">
|
||||
<div class="input-width"> {{ appStoreInfo.title }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('desc')">
|
||||
<div class="input-width"> {{ appStoreInfo.desc }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('author')">
|
||||
<div class="input-width"> {{ appStoreInfo.author }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('version')">
|
||||
<div class="input-width"> {{ appStoreInfo.version }} </div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button type="primary" @click="appStoreShowDialog = false">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<div class="text-sm mt-[10px] text-info">{{ t('authInfoTips') }}</div>
|
||||
|
||||
<!-- 安装弹窗 -->
|
||||
<el-dialog v-model="installShowDialog" :title="t('addonInstall')" width="850px" :close-on-click-modal="false"
|
||||
:close-on-press-escape="false" :before-close="installShowDialogClose">
|
||||
<el-steps :space="200" :active="installStep" finish-status="success" align-center>
|
||||
<el-step :title="t('envCheck')" class="flex-1" />
|
||||
<el-step :title="t('installProgress')" class="flex-1" />
|
||||
<el-step :title="t('installComplete')" class="flex-1" />
|
||||
</el-steps>
|
||||
<div v-show="installStep == 1" v-loading="!installCheckResult.dir">
|
||||
<div class="mt-[20px]">
|
||||
<el-button type="primary" class="w-full" size="large" :loading="saveLoading"
|
||||
@click="save(formRef)">{{ t('confirm') }}</el-button>
|
||||
</div>
|
||||
<div class="mt-[10px] text-right">
|
||||
<el-button type="primary" link @click="market">{{ t('notHaveAuth') }}</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<!-- 详情 -->
|
||||
<el-dialog v-model="appStoreShowDialog" :title="t('plugDetail')" width="500px" :destroy-on-close="true">
|
||||
<el-form :model="appStoreInfo" label-width="120px" ref="formRef" class="page-form">
|
||||
<el-form-item :label="t('title')">
|
||||
<div class="input-width"> {{ appStoreInfo.title }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('desc')">
|
||||
<div class="input-width"> {{ appStoreInfo.desc }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('author')">
|
||||
<div class="input-width"> {{ appStoreInfo.author }} </div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('version')">
|
||||
<div class="input-width"> {{ appStoreInfo.version }} </div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button type="primary" @click="appStoreShowDialog = false">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 安装弹窗 -->
|
||||
<el-dialog v-model="installShowDialog" :title="t('addonInstall')" width="850px" :close-on-click-modal="false"
|
||||
:close-on-press-escape="false" :before-close="installShowDialogClose">
|
||||
<el-steps :space="200" :active="installStep" finish-status="success" align-center>
|
||||
<el-step :title="t('envCheck')" class="flex-1" />
|
||||
<el-step :title="t('installProgress')" class="flex-1" />
|
||||
<el-step :title="t('installComplete')" class="flex-1" />
|
||||
</el-steps>
|
||||
<div v-show="installStep == 1" v-loading="!installCheckResult.dir">
|
||||
<el-scrollbar max-height="50vh">
|
||||
<div class="min-h-[150px]">
|
||||
<div class="bg-[#fff] my-3" v-if="installCheckResult.dir">
|
||||
<p class="pt-[20px] pl-[20px] ">{{ t('dirPermission') }}</p>
|
||||
<div class="px-[20px] pt-[10px] text-[14px]">
|
||||
<el-row class="py-[10px] items table-head-bg pl-[15px] mb-[10px]">
|
||||
<el-col :span="12">
|
||||
<span>{{ t('path') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('demand') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('status') }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]"
|
||||
v-for="item in installCheckResult.dir.is_readable">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('readable') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span v-if="item.status"><el-icon color="green"><Select /></el-icon></span>
|
||||
<span v-else>
|
||||
<el-icon color="red">
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]"
|
||||
v-for="item in installCheckResult.dir.is_write">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('write') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span v-if="item.status"><el-icon color="green"><Select /></el-icon></span>
|
||||
<span v-else>
|
||||
<el-icon color="red">
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<div class="flex justify-end">
|
||||
<el-tooltip effect="dark" :content="t('installTips')" placement="top">
|
||||
<el-button type="default" :disabled="!installCheckResult.is_pass || cloudInstalling"
|
||||
:loading="localInstalling" @click="handleInstall">{{
|
||||
t('localInstall')
|
||||
}}</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" :content="t('cloudInstallTips')" placement="top">
|
||||
<el-button type="primary" :disabled="!installCheckResult.is_pass || localInstalling"
|
||||
:loading="cloudInstalling" @click="handleCloudInstall">{{
|
||||
t('cloudInstall')
|
||||
}}</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="installStep == 2" class="h-[50vh] mt-[20px]">
|
||||
<terminal name="my-terminal" :context="currAddon" :init-log="null" :show-header="false"
|
||||
:show-log-time="true" />
|
||||
</div>
|
||||
<div v-show="installStep == 3" class="h-[50vh] mt-[20px] flex flex-col">
|
||||
<el-result icon="success" :title="t('addonInstallSuccess')"></el-result>
|
||||
<!-- 提示信息 -->
|
||||
<div v-for="item in installAfterTips" class="mb-[10px]">
|
||||
<el-alert :title="item" type="error" :closable="false" />
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="uninstallShowDialog" :title="t('addonUninstall')" width="850px"
|
||||
:close-on-click-modal="false" :close-on-press-escape="false">
|
||||
<el-scrollbar max-height="50vh">
|
||||
<div class="min-h-[150px]">
|
||||
<div class="bg-[#fff] my-3" v-if="installCheckResult.dir">
|
||||
<div class="bg-[#fff] my-3" v-if="uninstallCheckResult.dir">
|
||||
<p class="pt-[20px] pl-[20px] ">{{ t('dirPermission') }}</p>
|
||||
<div class="px-[20px] pt-[10px] text-[14px]">
|
||||
<el-row class="py-[10px] items table-head-bg pl-[15px] mb-[10px]">
|
||||
@ -209,7 +305,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]"
|
||||
v-for="item in installCheckResult.dir.is_readable">
|
||||
v-for="item in uninstallCheckResult.dir.is_readable">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
@ -225,7 +321,7 @@
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in installCheckResult.dir.is_write">
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in uninstallCheckResult.dir.is_write">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
@ -245,89 +341,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<div class="flex justify-end">
|
||||
<el-tooltip effect="dark" :content="t('installTips')" placement="top">
|
||||
<el-button type="default" :disabled="!installCheckResult.is_pass || cloudInstalling"
|
||||
:loading="localInstalling" @click="handleInstall">{{
|
||||
t('localInstall')
|
||||
}}</el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" :content="t('cloudInstallTips')" placement="top">
|
||||
<el-button type="primary" :disabled="!installCheckResult.is_pass || localInstalling"
|
||||
:loading="cloudInstalling" @click="handleCloudInstall">{{
|
||||
t('cloudInstall')
|
||||
}}</el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="installStep == 2" class="h-[50vh] mt-[20px]">
|
||||
<terminal name="my-terminal" :context="currAddon" :init-log="null" :show-header="false"
|
||||
:show-log-time="true" />
|
||||
</div>
|
||||
<div v-show="installStep == 3" class="h-[50vh] mt-[20px] flex flex-col">
|
||||
<el-result icon="success" :title="t('addonInstallSuccess')"></el-result>
|
||||
<!-- 提示信息 -->
|
||||
<div v-for="item in installAfterTips" class="mb-[10px]">
|
||||
<el-alert :title="item" type="error" :closable="false" />
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="uninstallShowDialog" :title="t('addonUninstall')" width="850px" :close-on-click-modal="false"
|
||||
:close-on-press-escape="false">
|
||||
<el-scrollbar max-height="50vh">
|
||||
<div class="min-h-[150px]">
|
||||
<div class="bg-[#fff] my-3" v-if="uninstallCheckResult.dir">
|
||||
<p class="pt-[20px] pl-[20px] ">{{ t('dirPermission') }}</p>
|
||||
<div class="px-[20px] pt-[10px] text-[14px]">
|
||||
<el-row class="py-[10px] items table-head-bg pl-[15px] mb-[10px]">
|
||||
<el-col :span="12">
|
||||
<span>{{ t('path') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('demand') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('status') }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in uninstallCheckResult.dir.is_readable">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('readable') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span v-if="item.status"><el-icon color="green"><Select /></el-icon></span>
|
||||
<span v-else>
|
||||
<el-icon color="red">
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="pb-[10px] items pl-[15px]" v-for="item in uninstallCheckResult.dir.is_write">
|
||||
<el-col :span="12">
|
||||
<span>{{ item.dir }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span>{{ t('write') }}</span>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<span v-if="item.status"><el-icon color="green"><Select /></el-icon></span>
|
||||
<span v-else>
|
||||
<el-icon color="red">
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -339,11 +354,13 @@ import { downloadVersion, getAuthinfo, setAuthinfo } from '@/app/api/module'
|
||||
import { ElMessageBox, ElNotification, FormInstance, FormRules } from 'element-plus'
|
||||
import { img } from '@/utils/common'
|
||||
import { Terminal, api as terminalApi } from 'vue-web-terminal'
|
||||
import { findFirstValidRoute } from '@/router/routers'
|
||||
import storage from '@/utils/storage'
|
||||
import { useRouter } from 'vue-router'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
const router = useRouter()
|
||||
const activeName = ref('installed')
|
||||
const loading = ref<Boolean>(false)
|
||||
const loading = ref<Boolean>(true)
|
||||
const downloading = ref('')
|
||||
const installAfterTips = ref<string[]>([])
|
||||
const userStore = useUserStore()
|
||||
@ -378,7 +395,7 @@ const search_name = ref('')
|
||||
const info = ref({
|
||||
installed: [],
|
||||
uninstalled: [],
|
||||
all: [],
|
||||
all: []
|
||||
})
|
||||
const query = () => {
|
||||
if (search_name.value == '' || search_name.value == null) {
|
||||
@ -390,8 +407,6 @@ const query = () => {
|
||||
info.value.installed = localList.value.installed.filter((el: any) => el.title.indexOf(search_name.value) != -1)
|
||||
info.value.uninstalled = localList.value.uninstalled.filter((el: any) => el.title.indexOf(search_name.value) != -1)
|
||||
info.value.all = localList.value.all.filter((el: any) => el.title.indexOf(search_name.value) != -1)
|
||||
|
||||
|
||||
}
|
||||
const localList = ref({
|
||||
installed: [],
|
||||
@ -418,6 +433,14 @@ const localListFn = () => {
|
||||
}
|
||||
}
|
||||
query()
|
||||
userStore.routers.forEach((item, index) => {
|
||||
if (item.children && item.children.length) {
|
||||
item.name = findFirstValidRoute(item.children)
|
||||
appLink.value[item.meta.app] = findFirstValidRoute(item.children)
|
||||
} else {
|
||||
appLink.value[item.meta.app] = item.name
|
||||
}
|
||||
})
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
@ -425,6 +448,22 @@ const localListFn = () => {
|
||||
}
|
||||
|
||||
localListFn()
|
||||
|
||||
// 点击应用可以进系统
|
||||
|
||||
const appLink: any = ref({})
|
||||
const itemPath = (data: any) => {
|
||||
if (data.type == 'app' && Object.keys(data.install_info).length) {
|
||||
storage.set({ key: 'menuAppStorage', data: data.key })
|
||||
storage.set({ key: 'plugMenuTypeStorage', data: '' })
|
||||
const appMenuList = userStore.appMenuList
|
||||
appMenuList.push(data.key)
|
||||
userStore.setAppMenuList(appMenuList)
|
||||
let name:any = appLink.value[data.key]
|
||||
router.push({ name: name })
|
||||
}
|
||||
}
|
||||
|
||||
const currAddon = ref('')
|
||||
|
||||
// 安装面板弹窗
|
||||
@ -556,10 +595,10 @@ const authElMessageBox = () => {
|
||||
cancelButtonText: t('toNiucloud')
|
||||
}
|
||||
).then(() => {
|
||||
authCodeApproveFn()
|
||||
router.push({ path: '/app/authorize' })
|
||||
}).catch((action: string) => {
|
||||
if (action === 'cancel') {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -619,7 +658,7 @@ const uninstallAddonFn = (key: string) => {
|
||||
}
|
||||
|
||||
const market = () => {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
|
||||
/**
|
||||
@ -639,8 +678,6 @@ const installShowDialogClose = (done: () => {}) => {
|
||||
).then(() => {
|
||||
done()
|
||||
}).catch(() => { })
|
||||
} else if(installStep.value == 3){
|
||||
location.reload();
|
||||
} else done()
|
||||
}
|
||||
|
||||
@ -711,14 +748,13 @@ const save = async (formEl: FormInstance | undefined) => {
|
||||
}
|
||||
|
||||
const goRouter = () => {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 多行超出隐藏 */
|
||||
.multi-hidden {
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
<template #description>
|
||||
<span class="text-[#999]">{{ t("describe3") }}</span>
|
||||
<div class="mt-[20px] mb-[40px] h-[32px]">
|
||||
<el-button type="primary" plain>{{t("btn3") }}</el-button>
|
||||
<el-button type="primary" plain @click="linkEvent('https://www.kancloud.cn/niushop/niucloud-admin-app/3199825')">{{t("btn3") }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-step>
|
||||
@ -134,7 +134,7 @@
|
||||
<span class="text-[#999]">{{ t("describe5") }}</span>
|
||||
<div class="mt-[20px] mb-[40px] h-[32px]">
|
||||
<el-button type="primary" plain
|
||||
@click="linkEvent('https://www.niucloud.com/product')">{{t("btn5") }}</el-button>
|
||||
@click="linkEvent('https://www.niucloud.com/app')">{{t("btn5") }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-step>
|
||||
|
||||
@ -84,15 +84,14 @@
|
||||
router.push(link)
|
||||
}
|
||||
const goRouter = () => {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style>
|
||||
.tools-item-shadow{
|
||||
box-shadow: 0px 0px 6px rgba(183, 183, 175, 1);
|
||||
|
||||
box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
|
||||
}
|
||||
/* 多行超出隐藏 */
|
||||
.multi-hidden {
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="flex border-t border-b main-wrap border-color w-full" :class="scene == 'select' ? 'h-[430px]' : 'h-full'">
|
||||
<div class="flex border-t border-b main-wrap border-color w-full" :class="scene == 'select' ? 'h-[40vh]' : 'h-full'">
|
||||
<!-- 分组 -->
|
||||
<div class="group-wrap w-[180px] p-[15px] h-full border-r border-color flex flex-col">
|
||||
|
||||
<el-input v-model="categoryParam.name" class="m-0" :placeholder="t('upload.attachmentCategoryPlaceholder')" clearable prefix-icon="Search" @input="getAttachmentCategoryList()"/>
|
||||
<div class="group-list flex-1 my-[10px]">
|
||||
<el-scrollbar height="300px">
|
||||
<el-scrollbar>
|
||||
<div class="group-item p-[10px] leading-none text-xs rounded cursor-pointer" :class="{ active: attachmentParam.cate_id == 0 }" @click="attachmentParam.cate_id = 0">
|
||||
{{ t('selectPlaceholder') }}
|
||||
</div>
|
||||
|
||||
@ -80,7 +80,7 @@ getEnvFn();
|
||||
|
||||
|
||||
const goRouter = () => {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
|
||||
// 跳转至开发者
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
</div>
|
||||
<div v-if="!data.length" class="flex-1 flex flex-col justify-center items-center pb-[30px]">
|
||||
<div class="w-[130px]"><img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt=""></div>
|
||||
<div class="text-[14px] text-[#909399]">暂无安装任何应用或插件,马上去<a href="https://www.niucloud.com/product/" target="_blank" class="text-[var(--el-color-primary)]">官方应用市场</a>逛逛</div>
|
||||
<div class="text-[14px] text-[#909399]">暂无安装任何应用或插件,马上去<a href="https://www.niucloud.com/app" target="_blank" class="text-[var(--el-color-primary)]">官方应用市场</a>逛逛</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -324,7 +324,7 @@ const toLink = (data, type) => {
|
||||
}
|
||||
router.push({ name: name })
|
||||
} else {
|
||||
window.open('https://www.niucloud.com/product/', '_blank')
|
||||
window.open('https://www.niucloud.com/app', '_blank')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
</div>
|
||||
<div v-if="!data.length" class="flex-1 flex flex-col justify-center items-center pb-[30px]">
|
||||
<div class="w-[130px]"><img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt=""></div>
|
||||
<div class="text-[14px] text-[#909399]">暂无安装任何应用或插件,马上去<a href="https://www.niucloud.com/product/" target="_blank" class="text-[var(--el-color-primary)]">官方应用市场</a>逛逛</div>
|
||||
<div class="text-[14px] text-[#909399]">暂无安装任何应用或插件,马上去<a href="https://www.niucloud.com/app" target="_blank" class="text-[var(--el-color-primary)]">官方应用市场</a>逛逛</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -339,7 +339,7 @@ const toLink = (data, type) => {
|
||||
}
|
||||
router.push({ name: name })
|
||||
} else {
|
||||
window.open('https://www.niucloud.com/product/', '_blank')
|
||||
window.open('https://www.niucloud.com/app', '_blank')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
</div>
|
||||
<div v-if="!data.length" class="flex-1 flex flex-col justify-center items-center pb-[30px]">
|
||||
<div class="w-[130px]"><img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt=""></div>
|
||||
<div class="text-[14px] text-[#909399]">暂无安装任何应用或插件,马上去<a href="https://www.niucloud.com/product/" target="_blank" class="text-[var(--el-color-primary)]">官方应用市场</a>逛逛</div>
|
||||
<div class="text-[14px] text-[#909399]">暂无安装任何应用或插件,马上去<a href="https://www.niucloud.com/app" target="_blank" class="text-[var(--el-color-primary)]">官方应用市场</a>逛逛</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -455,7 +455,7 @@ const toLink = (data, type) => {
|
||||
}
|
||||
router.push({ name: name })
|
||||
} else {
|
||||
window.open('https://www.niucloud.com/product/', '_blank')
|
||||
window.open('https://www.niucloud.com/app', '_blank')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,19 @@
|
||||
<template>
|
||||
<div class="mt-[20px] mb-[15px] mx-[10px] app-aside-wrap bg-[#fff]">
|
||||
<!-- <el-menu :router="true" unique-opened="true" :default-active="String(route.name)">
|
||||
<template v-for="(item, index) in menus" :key="index">
|
||||
<el-menu-item v-if="item.meta.key != 'official_market'" @click="toLink(item)" :index="String(item.name)">
|
||||
<icon v-if="item.meta.icon" :name="item.meta.icon" class="!w-auto mr-[6px]" size="16px" :title="item.meta.title" />
|
||||
<span>{{ item.meta.title }}</span>
|
||||
</el-menu-item>
|
||||
<div class="el-menu-item" v-else @click="toLink(item)">
|
||||
<icon v-if="item.meta.icon" :name="item.meta.icon" class="!w-auto mr-[6px]" size="16px" :title="item.meta.title" />
|
||||
<span class="text-[14px]">{{ item.meta.title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-menu> -->
|
||||
<div class="flex flex-wrap items-center">
|
||||
<div v-for="(item, index) in menus" :key="index" :class="['border-[1px] border-solid my-[5px] border-[#E0E0E0] rounded-full py-[5px] px-[10px] cursor-pointer',{'mr-[20px]': index != menus.length-1},{'text-[#fff] bg-[#000] border-[#000]': item.name == route.name}]" @click="toLink(item)">
|
||||
<div v-for="(item, index) in menus" :key="index" :class="['border-[1px] border-solid my-[5px] border-[#E0E0E0] rounded-full py-[5px] px-[10px] mr-[24px] cursor-pointer',{'text-[#fff] bg-[#000] border-[#000]': item.name == route.name}]" @click="toLink(item)">
|
||||
<icon v-if="item.meta.icon" :name="item.meta.icon" class="!w-auto mr-[4px]" size="14px" :title="item.meta.title" />
|
||||
<span class="text-[14px]">{{ item.meta.title }}</span>
|
||||
</div>
|
||||
@ -40,7 +52,7 @@ import useUserStore from '@/stores/modules/user'
|
||||
if(data.meta.key != 'official_market'){
|
||||
router.push({ name: data.name })
|
||||
}else{
|
||||
window.open('https://www.niucloud.com/product/', '_blank')
|
||||
window.open('https://www.niucloud.com/app', '_blank')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<el-dialog v-model="changePasswordDialog" width="450px" title="修改密码" :before-close="handleClose">
|
||||
<el-dialog v-model="changePasswordDialog" title="修改密码" :before-close="handleClose">
|
||||
<div>
|
||||
<el-form :model="saveInfo" label-width="90px" ref="formRef" :rules="formRules" class="page-form">
|
||||
<el-form-item :label="t('originalPassword')" prop="original_password">
|
||||
@ -53,6 +53,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { UserFilled } from '@element-plus/icons-vue'
|
||||
import { computed, reactive, ref, onMounted, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type { FormInstance, FormRules, ElNotification } from 'element-plus'
|
||||
@ -77,7 +78,7 @@ const getEnvFn = () => {
|
||||
getEnvFn();
|
||||
|
||||
const goRouter = () => {
|
||||
window.open('https://www.niucloud.com/product')
|
||||
window.open('https://www.niucloud.com/app')
|
||||
}
|
||||
|
||||
// 跳转至开发者
|
||||
|
||||
@ -73,7 +73,7 @@
|
||||
<tr>
|
||||
<td class="onetd">数据库编码:</td>
|
||||
<td>
|
||||
<label class="install-code">UTF8</label>
|
||||
<label class="install-code">utf8mb4</label>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@ -42,13 +42,13 @@
|
||||
<div class="other-links-pic">
|
||||
<img src="INSTALL_IMG/site_web.png" alt="">
|
||||
</div>
|
||||
<a href="javascript:void(0)" class="other-links-text" >站点电脑端</a>
|
||||
<a href="javascript:void(0)" class="other-links-text" >网站电脑端</a>
|
||||
</li>
|
||||
<li class="other-links-item" onclick="window.open('{$root_url}/wap/')">
|
||||
<div class="other-links-pic">
|
||||
<img src="INSTALL_IMG/site_h5.png" alt="">
|
||||
</div>
|
||||
<a href="javascript:void(0)" class="other-links-text" >站点手机端</a>
|
||||
<a href="javascript:void(0)" class="other-links-text" >网站手机端</a>
|
||||
</li>
|
||||
<li class="other-links-item" onclick="window.open('https://www.niucloud.com')">
|
||||
<div class="other-links-pic">
|
||||
|
||||
@ -49,7 +49,7 @@ class CoreAddonService extends CoreAddonBaseService
|
||||
'desc' => $v['app']['app_desc'],
|
||||
'key' => $v['app']['app_key'] ?? '',
|
||||
'version' => $v['version'] ?? '',
|
||||
'author' => $v['app']['app_name'],
|
||||
'author' => $v['site_name'],
|
||||
'type' => $v['app']['app_type'],
|
||||
'support_app' => $v['app']['support_channel'] ?? [],
|
||||
'is_download' => false,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user