update admin

This commit is contained in:
全栈小学生 2023-10-23 17:37:13 +08:00
parent 07767b9d4a
commit e1d8c974f1
9 changed files with 421 additions and 241 deletions

View File

@ -76,3 +76,12 @@ export function getAddonInstalltask() {
export function getAddonCloudInstallLog(addon: string) { export function getAddonCloudInstallLog(addon: string) {
return request.get(`addon/cloudinstall/${addon}`) return request.get(`addon/cloudinstall/${addon}`)
} }
/**
*
* @param addon
* @returns
*/
export function preUninstallCheck(addon: string) {
return request.get(`addon/uninstall/check/${addon}`, { timeout: 30 * 1000 })
}

View File

@ -4,7 +4,7 @@ import request from '@/utils/request'
* *
*/ */
export function getAuthinfo() { export function getAuthinfo() {
return request.get('niucloud/authinfo') return request.get('niucloud/authinfo', { showErrorMessage: false })
} }
/** /**

View File

@ -43,5 +43,6 @@
"downloading": "下载中", "downloading": "下载中",
"authTips": "云安装需先绑定授权码如果已有授权请先进行绑定没有授权可到niucloud官网购买云服务之后再进行操作", "authTips": "云安装需先绑定授权码如果已有授权请先进行绑定没有授权可到niucloud官网购买云服务之后再进行操作",
"toBind": "绑定授权", "toBind": "绑定授权",
"toNiucloud": "去niucloud官网" "toNiucloud": "去niucloud官网",
"addonUninstall": "插件卸载"
} }

View File

@ -55,5 +55,6 @@
"authSecretPlaceholder": "请输入授权秘钥", "authSecretPlaceholder": "请输入授权秘钥",
"updateCode": "重新绑定", "updateCode": "重新绑定",
"notHaveAuth": "还没有授权?去购买", "notHaveAuth": "还没有授权?去购买",
"authInfoTips": "授权码和授权秘钥可在Niucloud官网我的授权 授权详情中查看" "authInfoTips": "授权码和授权秘钥可在Niucloud官网我的授权 授权详情中查看",
"addonUninstall": "插件卸载"
} }

View File

@ -17,30 +17,44 @@
<div class="flex flex-col"> <div class="flex flex-col">
<div class="flex flex-wrap items-center"> <div class="flex flex-wrap items-center">
<p class="text-[20px] text-[#333] mr-[20px]">授权信息</p> <p class="text-[20px] text-[#333] mr-[20px]">授权信息</p>
<span class="text-[14px] text-[#666]">{{authinfo.company_name || '--'}}</span> <span class="text-[14px] text-[#666]">{{ authinfo.company_name || '--' }}</span>
</div> </div>
<div class="mt-[46px] ml-[40px] flex flex-wrap"> <div class="mt-[46px] ml-[40px] flex flex-wrap">
<span class="text-[14px] text-[#797979] mr-[84px]">授权域名<em class="ml-[12px] text-[12px] text-[#222222]">{{authinfo.site_address || '--'}}</em></span> <span class="text-[14px] text-[#797979] mr-[84px]">授权域名<em
class="ml-[12px] text-[12px] text-[#222222]">{{ authinfo.site_address || '--'
}}</em></span>
<span class="text-[14px] flex items-center text-[#797979]"> <span class="text-[14px] flex items-center text-[#797979]">
<span>授权码</span> <span>授权码</span>
<em class="ml-[12px] mr-[10px] text-[12px] text-[#222222]">{{ authinfo.auth_code ? (isCheck ? authinfo.auth_code : hideAuthCode(authinfo.auth_code)) : '--' }}</em> <em class="ml-[12px] mr-[10px] text-[12px] text-[#222222]">{{ authinfo.auth_code ? (isCheck
<el-icon v-if="!isCheck" @click="isCheck = !isCheck" class="text-[12px] cursor-pointer"><View/></el-icon> ?
<el-icon v-else @click="isCheck = !isCheck" class="text-[12px] cursor-pointer"><Hide /></el-icon> authinfo.auth_code : hideAuthCode(authinfo.auth_code)) : '--' }}</em>
<el-icon v-if="!isCheck" @click="isCheck = !isCheck" class="text-[12px] cursor-pointer">
<View />
</el-icon>
<el-icon v-else @click="isCheck = !isCheck" class="text-[12px] cursor-pointer">
<Hide />
</el-icon>
</span> </span>
</div> </div>
</div> </div>
<div class="flex flex-1 flex-wrap justify-end relative" > <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-button class="w-[154px] !h-[48px] mt-[8px]" type="primary"
<el-popover ref="getAuthCodeDialog" placement="bottom" :width="478" trigger="click" class="mt-[8px]"> @click="authCodeApproveFn">授权码认证</el-button>
<el-popover ref="getAuthCodeDialog" placement="bottom" :width="478" trigger="click"
class="mt-[8px]">
<div class="px-[18px] py-[8px]"> <div class="px-[18px] py-[8px]">
<p class="leading-[32px] text-[14px]">您在官方应用市场购买任意一款应用即可获得授权码输入正确授权码认证通过后即可支持在线升级和其它相关服务</p> <p class="leading-[32px] text-[14px]">您在官方应用市场购买任意一款应用即可获得授权码输入正确授权码认证通过后即可支持在线升级和其它相关服务
</p>
<div class="flex justify-end mt-[36px]"> <div class="flex justify-end mt-[36px]">
<el-button class="w-[182px] !h-[48px]" plain @click="market">去应用市场逛逛</el-button> <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> <el-button class="w-[100px] !h-[48px]" plain
@click="getAuthCodeDialog.hide()">关闭</el-button>
</div> </div>
</div> </div>
<template #reference> <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> <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> </template>
</el-popover> </el-popover>
</div> </div>
@ -48,19 +62,23 @@
<el-form :model="formData" label-width="0" ref="formRef" :rules="formRules" class="page-form"> <el-form :model="formData" label-width="0" ref="formRef" :rules="formRules" class="page-form">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<el-form-item prop="auth_code"> <el-form-item prop="auth_code">
<el-input v-model="formData.auth_code" :placeholder="t('authCodePlaceholder')" class="input-width" clearable size="large" /> <el-input v-model="formData.auth_code" :placeholder="t('authCodePlaceholder')"
class="input-width" clearable size="large" />
</el-form-item> </el-form-item>
<div class="mt-[20px]"> <div class="mt-[20px]">
<el-form-item prop="auth_secret"> <el-form-item prop="auth_secret">
<el-input v-model="formData.auth_secret" clearable :placeholder="t('authSecretPlaceholder')" class="input-width" size="large" /> <el-input v-model="formData.auth_secret" clearable
:placeholder="t('authSecretPlaceholder')" class="input-width" size="large" />
</el-form-item> </el-form-item>
</div> </div>
<div class="text-sm mt-[10px] text-info">{{ t('authInfoTips') }}</div> <div class="text-sm mt-[10px] text-info">{{ t('authInfoTips') }}</div>
<div class="mt-[20px]"> <div class="mt-[20px]">
<el-button type="primary" class="w-full" size="large" :loading="saveLoading" @click="save(formRef)">{{ t('confirm') }}</el-button> <el-button type="primary" class="w-full" size="large" :loading="saveLoading"
@click="save(formRef)">{{
t('confirm') }}</el-button>
</div> </div>
<div class="mt-[10px] text-right"> <div class="mt-[10px] text-right">
<el-button type="primary" link @click="market">{{ t('notHaveAuth') }}</el-button> <el-button type="primary" link @click="market">{{ t('notHaveAuth') }}</el-button>
@ -75,87 +93,87 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref } from "vue"; import { reactive, ref } from 'vue'
import { t } from "@/lang"; import { t } from '@/lang'
import { getAuthinfo, setAuthinfo, getAdminAuthinfo } from "@/app/api/module"; import { getAuthinfo, setAuthinfo, getAdminAuthinfo } from '@/app/api/module'
import { FormInstance, FormRules } from "element-plus"; import { FormInstance, FormRules } from 'element-plus'
import { useRoute } from "vue-router"; import { useRoute } from 'vue-router'
const route = useRoute(); const route = useRoute()
const pageName = route.meta.title; const pageName = route.meta.title
let getAuthCodeDialog = ref(null); const getAuthCodeDialog = ref(null)
let authCodeApproveDialog = ref(false); const authCodeApproveDialog = ref(false)
let isCheck = ref(false); const isCheck = ref(false)
const hideAuthCode = (res)=>{ const hideAuthCode = (res) => {
let authCode = JSON.parse(JSON.stringify(res)); const authCode = JSON.parse(JSON.stringify(res))
let data = authCode.slice(0, authCode.length/2) + authCode.slice(authCode.length/2, authCode.length-1).replace(/./g, '*') const data = authCode.slice(0, authCode.length / 2) + authCode.slice(authCode.length / 2, authCode.length - 1).replace(/./g, '*')
return data return data
} }
const authCodeApproveFn = ()=>{ const authCodeApproveFn = () => {
authCodeApproveDialog.value = true; authCodeApproveDialog.value = true
} }
const authinfo = ref(""); const authinfo = ref('')
const loading = ref(true); const loading = ref(true)
const saveLoading = ref(false); const saveLoading = ref(false)
const checkAppMange = () => { const checkAppMange = () => {
getAuthinfo() getAuthinfo()
.then((res) => { .then((res) => {
loading.value = false; loading.value = false
if (res.data.data && res.data.data.length != 0) { if (res.data.data && res.data.data.length != 0) {
authinfo.value = res.data.data; authinfo.value = res.data.data
authCodeApproveDialog.value = false; authCodeApproveDialog.value = false
} }
}) })
.catch(() => { .catch(() => {
loading.value = false; loading.value = false
authCodeApproveDialog.value = false; authCodeApproveDialog.value = false
}); })
}; }
checkAppMange(); checkAppMange()
const formData = reactive<Record<string, string>>({ const formData = reactive<Record<string, string>>({
auth_code: "", auth_code: '',
auth_secret: "", auth_secret: ''
}); })
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>()
// //
const formRules = reactive<FormRules>({ const formRules = reactive<FormRules>({
auth_code: [ auth_code: [
{ required: true, message: t("authCodePlaceholder"), trigger: "blur" }, { required: true, message: t('authCodePlaceholder'), trigger: 'blur' }
], ],
auth_secret: [ auth_secret: [
{ required: true, message: t("authSecretPlaceholder"), trigger: "blur" }, { required: true, message: t('authSecretPlaceholder'), trigger: 'blur' }
], ]
}); })
const save = async (formEl: FormInstance | undefined) => { const save = async (formEl: FormInstance | undefined) => {
if (saveLoading.value || !formEl) return; if (saveLoading.value || !formEl) return
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
saveLoading.value = true; saveLoading.value = true
setAuthinfo(formData) setAuthinfo(formData)
.then(() => { .then(() => {
saveLoading.value = false; saveLoading.value = false
checkAppMange(); checkAppMange()
}) })
.catch(() => { .catch(() => {
saveLoading.value = false; saveLoading.value = false
authCodeApproveDialog.value = false; authCodeApproveDialog.value = false
}); })
} }
}); })
}; }
const market = () => { const market = () => {
window.open("https://www.niucloud.com/product"); window.open('https://www.niucloud.com/product')
}; }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -165,21 +183,25 @@ const market = () => {
text-overflow: ellipsis; text-overflow: ellipsis;
-o-text-overflow: ellipsis; -o-text-overflow: ellipsis;
} }
.main { .main {
background-color: var(--el-bg-color-overlay); background-color: var(--el-bg-color-overlay);
} }
em{
font-style:normal em {
font-style: normal
} }
</style> </style>
<style> <style>
.auth-code-dialog .el-overlay{ .auth-code-dialog .el-overlay {
background-color: transparent; background-color: transparent;
} }
.auth-code-dialog .el-dialog__header{
.auth-code-dialog .el-dialog__header {
padding: 0; padding: 0;
} }
.auth-code-dialog .el-dialog__body{
.auth-code-dialog .el-dialog__body {
padding: 20px 30px; padding: 20px 30px;
} }
</style> </style>

View File

@ -310,13 +310,68 @@
</div> </div>
</el-dialog> </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>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, watch, computed, h } from 'vue' import { ref, watch, computed, h } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { getAddonLocal, uninstallAddon, installAddon, preInstallCheck, cloudInstallAddon, getAddonInstalltask, getAddonCloudInstallLog } from '@/app/api/addon' import { getAddonLocal, uninstallAddon, installAddon, preInstallCheck, cloudInstallAddon, getAddonInstalltask, getAddonCloudInstallLog, preUninstallCheck } from '@/app/api/addon'
import { downloadVersion, getAuthinfo } from '@/app/api/module' import { downloadVersion, getAuthinfo } from '@/app/api/module'
import { TabsPaneContext, ElMessageBox, ElNotification } from 'element-plus' import { TabsPaneContext, ElMessageBox, ElNotification } from 'element-plus'
import { img } from '@/utils/common' import { img } from '@/utils/common'
@ -582,11 +637,19 @@ watch(currAddon, (nval) => {
installCheckResult.value = {} installCheckResult.value = {}
}) })
//
const uninstallShowDialog = ref(false)
//
const uninstallCheckResult = ref({})
/** /**
* 卸载 * 卸载
* @param key * @param key
*/ */
const uninstallAddonFn = (key: string) => { const uninstallAddonFn = (key: string) => {
preUninstallCheck(key).then(({ data }) => {
if (data.is_pass) {
uninstallAddon({ addon: key }).then(res => { uninstallAddon({ addon: key }).then(res => {
localListFn() localListFn()
userStore.getAppList() userStore.getAppList()
@ -594,6 +657,11 @@ const uninstallAddonFn = (key: string) => {
}).catch(() => { }).catch(() => {
loading.value = false loading.value = false
}) })
} else {
uninstallCheckResult.value = data
uninstallShowDialog.value = true
}
})
} }
const market = () => { const market = () => {

View File

@ -60,7 +60,6 @@
</div> </div>
</div> </div>
<el-empty class="mx-auto overview-empty" v-if="!localList.installed.length && !loading"> <el-empty class="mx-auto overview-empty" v-if="!localList.installed.length && !loading">
<template #image> <template #image>
<div class="w-[230px] mx-auto"> <div class="w-[230px] mx-auto">
@ -68,7 +67,7 @@
</div> </div>
</template> </template>
<template #description> <template #description>
<p class="flex items-center">{{t('installed-empty')}}</p> <p class="flex items-center">{{ t('installed-empty') }}</p>
</template> </template>
</el-empty> </el-empty>
</div> </div>
@ -157,16 +156,17 @@
@click="getAddonDetialFn(item)" v-if="showType == 'small'"> @click="getAddonDetialFn(item)" v-if="showType == 'small'">
<div class="p-3"> <div class="p-3">
<img v-if="item.icon" class="w-[44px] h-[44px] rounded-sm" :src="item.icon" alt=""> <img v-if="item.icon" class="w-[44px] h-[44px] rounded-sm" :src="item.icon" alt="">
<img v-else class="w-[44px] h-[44px] rounded-sm" src="@/app/assets/images/icon-addon.png" <img v-else class="w-[44px] h-[44px] rounded-sm"
alt=""> src="@/app/assets/images/icon-addon.png" alt="">
</div> </div>
<div class="flex items-center w-[220px] border-b py-3 justify-between"> <div class="flex items-center w-[220px] border-b py-3 justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<span class="text-[14px] truncate w-[160px]">{{ item.title }}</span> <span class="text-[14px] truncate w-[160px]">{{ item.title }}</span>
<span class="text-xs text-gray-400 truncate w-[160px] mt-[4px]">{{ item.desc }}</span> <span class="text-xs text-gray-400 truncate w-[160px] mt-[4px]">{{ item.desc
}}</span>
</div> </div>
<el-button v-if="item.install_info && Object.keys(item.install_info)?.length" size="small" <el-button v-if="item.install_info && Object.keys(item.install_info)?.length"
round class="!text-primary !border-primary !bg-transparent" size="small" round class="!text-primary !border-primary !bg-transparent"
@click.stop="uninstallAddonFn(item.key)">{{ t('unload') @click.stop="uninstallAddonFn(item.key)">{{ t('unload')
}}</el-button> }}</el-button>
<el-button v-else-if="item.is_download && item.install_info <= 0" size="small" round <el-button v-else-if="item.is_download && item.install_info <= 0" size="small" round
@ -175,14 +175,16 @@
}}</el-button> }}</el-button>
<el-button v-else size="small" :loading="downloading == item.key" <el-button v-else size="small" :loading="downloading == item.key"
:disabled="downloading != ''" round :disabled="downloading != ''" round
class="!text-primary !border-primary !bg-transparent" @click.stop="downEvent(item)">{{ class="!text-primary !border-primary !bg-transparent"
@click.stop="downEvent(item)">{{
t('down') }}</el-button> t('down') }}</el-button>
</div> </div>
</div> </div>
<div class="flex flex-wrap plug-list pb-10 plug-large" v-if="showType == 'large'"> <div class="flex flex-wrap plug-list pb-10 plug-large" v-if="showType == 'large'">
<div class="app-item cursor-pointer mr-4 mt-[20px] pb-2 bg-[#f7f7f7]" <div class="app-item cursor-pointer mr-4 mt-[20px] pb-2 bg-[#f7f7f7]"
v-for="(item, index) in localList.all" :key="index + 'a'" @click="getAddonDetialFn(item)"> v-for="(item, index) in localList.all" :key="index + 'a'"
@click="getAddonDetialFn(item)">
<div class="flex justify-center items-center"> <div class="flex justify-center items-center">
<img v-if="item.icon && !item.is_download" class="w-[240px] h-[120px]" <img v-if="item.icon && !item.is_download" class="w-[240px] h-[120px]"
:src="img(item.icon)" /> :src="img(item.icon)" />
@ -201,8 +203,8 @@
size="small" round class="!text-primary !border-primary !bg-transparent" size="small" round class="!text-primary !border-primary !bg-transparent"
@click.stop="uninstallAddonFn(item.key)">{{ t('unload') @click.stop="uninstallAddonFn(item.key)">{{ t('unload')
}}</el-button> }}</el-button>
<el-button v-else-if="item.is_download && item.install_info <= 0" size="small" round <el-button v-else-if="item.is_download && item.install_info <= 0" size="small"
class="!text-primary !border-primary !bg-transparent" round class="!text-primary !border-primary !bg-transparent"
@click.stop="installAddonFn(item.key)">{{ t('install') @click.stop="installAddonFn(item.key)">{{ t('install')
}}</el-button> }}</el-button>
<el-button v-else size="small" round :loading="downloading == item.key" <el-button v-else size="small" round :loading="downloading == item.key"
@ -215,20 +217,27 @@
</div> </div>
</template> </template>
<div v-if="!localList.all.length && !loading && !authinfo" class="mx-auto overview-empty flex flex-col items-center pt-14 pb-6"> <div v-if="!localList.all.length && !loading && !authinfo"
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="mb-[20px] text-sm text-[#888]">检测到当前账号尚未绑定授权请先绑定授权</div>
<div class="flex flex-1 flex-wrap justify-center relative" > <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-button class="w-[154px] !h-[48px] mt-[8px]" type="primary"
<el-popover ref="getAuthCodeDialog" placement="bottom" :width="478" trigger="click" class="mt-[8px]"> @click="authCodeApproveFn">授权码认证</el-button>
<el-popover ref="getAuthCodeDialog" placement="bottom" :width="478" trigger="click"
class="mt-[8px]">
<div class="px-[18px] py-[8px]"> <div class="px-[18px] py-[8px]">
<p class="leading-[32px] text-[14px]">您在官方应用市场购买任意一款应用即可获得授权码输入正确授权码认证通过后即可支持在线升级和其它相关服务</p> <p class="leading-[32px] text-[14px]">
您在官方应用市场购买任意一款应用即可获得授权码输入正确授权码认证通过后即可支持在线升级和其它相关服务</p>
<div class="flex justify-end mt-[36px]"> <div class="flex justify-end mt-[36px]">
<el-button class="w-[182px] !h-[48px]" plain @click="market">去应用市场逛逛</el-button> <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> <el-button class="w-[100px] !h-[48px]" plain
@click="getAuthCodeDialog.hide()">关闭</el-button>
</div> </div>
</div> </div>
<template #reference> <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> <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> </template>
</el-popover> </el-popover>
</div> </div>
@ -237,19 +246,23 @@
<el-form :model="formData" label-width="0" ref="formRef" :rules="formRules" class="page-form"> <el-form :model="formData" label-width="0" ref="formRef" :rules="formRules" class="page-form">
<el-card class="box-card !border-none" shadow="never"> <el-card class="box-card !border-none" shadow="never">
<el-form-item prop="auth_code"> <el-form-item prop="auth_code">
<el-input v-model="formData.auth_code" :placeholder="t('authCodePlaceholder')" class="input-width" clearable size="large" /> <el-input v-model="formData.auth_code" :placeholder="t('authCodePlaceholder')"
class="input-width" clearable size="large" />
</el-form-item> </el-form-item>
<div class="mt-[20px]"> <div class="mt-[20px]">
<el-form-item prop="auth_secret"> <el-form-item prop="auth_secret">
<el-input v-model="formData.auth_secret" clearable :placeholder="t('authSecretPlaceholder')" class="input-width" size="large" /> <el-input v-model="formData.auth_secret" clearable
:placeholder="t('authSecretPlaceholder')" class="input-width"
size="large" />
</el-form-item> </el-form-item>
</div> </div>
<div class="text-sm mt-[10px] text-info">{{ t('authInfoTips') }}</div> <div class="text-sm mt-[10px] text-info">{{ t('authInfoTips') }}</div>
<div class="mt-[20px]"> <div class="mt-[20px]">
<el-button type="primary" class="w-full" size="large" :loading="saveLoading" @click="save(formRef)">{{ t('confirm') }}</el-button> <el-button type="primary" class="w-full" size="large" :loading="saveLoading"
@click="save(formRef)">{{ t('confirm') }}</el-button>
</div> </div>
<div class="mt-[10px] text-right"> <div class="mt-[10px] text-right">
<el-button type="primary" link @click="market">{{ t('notHaveAuth') }}</el-button> <el-button type="primary" link @click="market">{{ t('notHaveAuth') }}</el-button>
@ -375,13 +388,68 @@
</div> </div>
</el-dialog> </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>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, watch, computed, h } from 'vue' import { ref, reactive, watch, computed, h } from 'vue'
import { t } from '@/lang' import { t } from '@/lang'
import { getAddonLocal, uninstallAddon, installAddon, preInstallCheck, cloudInstallAddon, getAddonInstalltask, getAddonCloudInstallLog } from '@/app/api/addon' import { getAddonLocal, uninstallAddon, installAddon, preInstallCheck, cloudInstallAddon, getAddonInstalltask, getAddonCloudInstallLog, preUninstallCheck } from '@/app/api/addon'
import { downloadVersion, getAuthinfo, setAuthinfo } from '@/app/api/module' import { downloadVersion, getAuthinfo, setAuthinfo } from '@/app/api/module'
import { TabsPaneContext, ElMessageBox, ElNotification, FormInstance, FormRules } from 'element-plus' import { TabsPaneContext, ElMessageBox, ElNotification, FormInstance, FormRules } from 'element-plus'
import { img } from '@/utils/common' import { img } from '@/utils/common'
@ -648,19 +716,31 @@ watch(currAddon, (nval) => {
installCheckResult.value = {} installCheckResult.value = {}
}) })
//
const uninstallShowDialog = ref(false)
//
const uninstallCheckResult = ref({})
/** /**
* 卸载 * 卸载
* @param key * @param key
*/ */
const uninstallAddonFn = (key: string) => { const uninstallAddonFn = (key: string) => {
preUninstallCheck(key).then(({ data }) => {
if (data.is_pass) {
uninstallAddon({ addon: key }).then(res => { uninstallAddon({ addon: key }).then(res => {
storage.set({key: 'menuAppStorage', data: ""})
localListFn() localListFn()
userStore.getAppList() userStore.getAppList()
loading.value = false loading.value = false
}).catch(() => { }).catch(() => {
loading.value = false loading.value = false
}) })
} else {
uninstallCheckResult.value = data
uninstallShowDialog.value = true
}
})
} }
const market = () => { const market = () => {
@ -696,62 +776,61 @@ const getAddonDetialFn = (data: AnyObject) => {
} }
// //
let authCodeApproveDialog = ref(false); const authCodeApproveDialog = ref(false)
const authinfo = ref(""); const authinfo = ref('')
let getAuthCodeDialog = ref(null); const getAuthCodeDialog = ref(null)
const saveLoading = ref(false); const saveLoading = ref(false)
const checkAppMange = () => { const checkAppMange = () => {
getAuthinfo() getAuthinfo()
.then((res) => { .then((res) => {
if (res.data.data && res.data.data.length != 0) { if (res.data.data && res.data.data.length != 0) {
authinfo.value = res.data.data; authinfo.value = res.data.data
} }
}) })
.catch(() => { .catch(() => {
authCodeApproveDialog.value = false; authCodeApproveDialog.value = false
}); })
}; }
checkAppMange(); checkAppMange()
const authCodeApproveFn = ()=>{ const authCodeApproveFn = () => {
authCodeApproveDialog.value = true; authCodeApproveDialog.value = true
} }
const formData = reactive<Record<string, string>>({ const formData = reactive<Record<string, string>>({
auth_code: "", auth_code: '',
auth_secret: "", auth_secret: ''
}); })
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>()
// //
const formRules = reactive<FormRules>({ const formRules = reactive<FormRules>({
auth_code: [ auth_code: [
{ required: true, message: t("authCodePlaceholder"), trigger: "blur" }, { required: true, message: t('authCodePlaceholder'), trigger: 'blur' }
], ],
auth_secret: [ auth_secret: [
{ required: true, message: t("authSecretPlaceholder"), trigger: "blur" }, { required: true, message: t('authSecretPlaceholder'), trigger: 'blur' }
], ]
}); })
const save = async (formEl: FormInstance | undefined) => { const save = async (formEl: FormInstance | undefined) => {
if (saveLoading.value || !formEl) return; if (saveLoading.value || !formEl) return
await formEl.validate(async (valid) => { await formEl.validate(async (valid) => {
if (valid) { if (valid) {
saveLoading.value = true; saveLoading.value = true
setAuthinfo(formData) setAuthinfo(formData)
.then(() => { .then(() => {
saveLoading.value = false; saveLoading.value = false
checkAppMange(); checkAppMange()
}) })
.catch(() => { .catch(() => {
saveLoading.value = false; saveLoading.value = false
authCodeApproveDialog.value = false; authCodeApproveDialog.value = false
}); })
} }
}); })
}; }
const goRouter = () => { const goRouter = () => {
window.open('https://www.niucloud.com/product') window.open('https://www.niucloud.com/product')

View File

@ -1,7 +1,7 @@
<template> <template>
<el-container class="h-[60px] bg-[#2B303B] flex items-center justify-between px-[15px] text-white"> <el-container class="h-[60px] bg-[#2B303B] flex items-center justify-between px-[15px] text-white">
<div class="flex items-center text-[14px] leading-[1]"> <div class="flex items-center text-[14px] leading-[1]">
<span class="iconfont icontuodong !text-[24px] mr-[6px]"></span> <span class="iconfont icontuodong !text-[25px] mr-[6px]"></span>
<span class="cursor-pointer" @click="goAppManage">{{ t('appMarketPlace') }}</span> <span class="cursor-pointer" @click="goAppManage">{{ t('appMarketPlace') }}</span>
<template v-if="app_debug"> <template v-if="app_debug">
<span class="mx-2 text-[#4F5563] mx-[15px]">|</span> <span class="mx-2 text-[#4F5563] mx-[15px]">|</span>

View File

@ -1,7 +1,7 @@
<template> <template>
<el-container class="h-[60px] bg-[#2B303B] flex items-center justify-between px-[15px] text-white"> <el-container class="h-[60px] bg-[#2B303B] flex items-center justify-between px-[15px] text-white">
<div class="flex items-center text-[14px]"> <div class="flex items-center text-[14px] leading-[1]">
<span class="iconfont icontuodong !text-[24px] mr-[6px]"></span> <span class="iconfont icontuodong !text-[25px] mr-[6px]"></span>
<span class="cursor-pointer" @click="goAppManage">{{ t('appMarketPlace') }}</span> <span class="cursor-pointer" @click="goAppManage">{{ t('appMarketPlace') }}</span>
<template v-if="app_debug"> <template v-if="app_debug">
<span class="mx-2 text-[#4F5563] mx-[15px]">|</span> <span class="mx-2 text-[#4F5563] mx-[15px]">|</span>