This commit is contained in:
全栈小学生 2023-10-26 17:24:23 +08:00
parent ecbef463d5
commit 80ecfb0ee0
27 changed files with 511 additions and 462 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,6 +1,6 @@
{
"app": "应用中心",
"descriptionLeft": "请点击",
"descriptionLeft": "暂无安装任何应用,请点击",
"link": "安装应用",
"descriptionRight": "安装使用",
"niucloud": "Niucloud官网",

View File

@ -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":"标识指开发应用或插件的文件夹名称"
}

View File

@ -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('')

View File

@ -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')
}
/**

View File

@ -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')
}
})
}

View File

@ -78,8 +78,6 @@ const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
/**
* 获取商品标签列表
*/

View File

@ -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') }}&nbsp;{{ t('currentVersion') }}&nbsp;{{ 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') }}&nbsp;{{
t('currentVersion') }}&nbsp;{{ 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>

View File

@ -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" />

View File

@ -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>

View File

@ -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'

View File

@ -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;

View File

@ -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>

View File

@ -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 {

View File

@ -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>

View File

@ -80,7 +80,7 @@ getEnvFn();
const goRouter = () => {
window.open('https://www.niucloud.com/product')
window.open('https://www.niucloud.com/app')
}
//

View File

@ -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>

View File

@ -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')
}
}

View File

@ -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>

View File

@ -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')
}
}

View File

@ -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>

View File

@ -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')
}
}

View File

@ -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>

View File

@ -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')
}
//

View File

@ -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>

View File

@ -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">

View File

@ -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,