update admin

This commit is contained in:
全栈小学生 2023-09-19 11:01:52 +08:00
parent befe7805e3
commit f3b5985c79
15 changed files with 396 additions and 256 deletions

View File

@ -0,0 +1,17 @@
import request from '@/utils/request'
/**
*
* @returns
*/
export function getShopTransaction() {
return request.get('shop/transaction')
}
/**
*
* @returns
*/
export function setShopTransaction(param:any) {
return request.post('shop/transaction',param, {showSuccessMessage: true})
}

View File

@ -59,6 +59,16 @@ export function getWeappPreview() {
export function getWeappVersionList(params: Record<string, any>) {
return request.get('weapp/version', { params })
}
/**
*
* @param key
* @returns
*/
export function getWeappUploadLog(key: string) {
return request.get(`weapp/upload/${key}`)
}
/***************************************************** 管理端 ****************************************************/
/**
@ -113,22 +123,4 @@ export function editVersion(params: Record<string, any>) {
*/
export function deleteVersion(id: string) {
return request.delete(`applet/version/${id}`)
}
/**
*
* @param params
* @returns
*/
export function versionDown(id: string) {
return request.get(`applet/version/download/${id}`, { "responseType": "blob" })
}
/**
*
* @param params
* @returns
*/
export function addProcess(params: Record<string, any>) {
return request.post('weapp/examine', params, { showSuccessMessage: true })
}

View File

@ -40,5 +40,8 @@
"cloudInstallTips": "云安装可实现一键安装,安装后无需手动更新依赖和编译前端源码",
"installingTips": "有插件正在安装中请等待安装完成之后再进行其他操作,点击查看",
"installPercent": "安装进度",
"downloading": "下载中"
"downloading": "下载中",
"authTips": "云安装需先绑定授权码如果已有授权请先进行绑定没有授权可到niucloud官网购买云服务之后再进行操作",
"toBind": "绑定授权",
"toNiucloud": "去niucloud官网"
}

View File

@ -34,5 +34,6 @@
"authTips": "上传代码需先绑定授权码如果已有授权请先进行绑定没有授权可到niucloud官网购买云服务之后再进行操作",
"toBind": "绑定授权",
"toNiucloud": "去niucloud官网",
"failReason": "失败原因:"
"failReason": "失败原因:",
"toSetting": "去配置"
}

View File

@ -1,12 +1,68 @@
<template>
<div class="main main-container min-w-[1000px] min-h-[650px]" v-loading="loading">
<el-card class="box-card !border-none" shadow="never" v-if="!loading">
<div class="flex items-center">
<div
class="main main-container min-w-[1000px] min-h-[650px]"
v-loading="loading"
>
<el-card class="box-card !border-none" shadow="never" v-if="!loading">
<div class="flex">
<div class="left bg-gray-100 mr-[14px] w-[402px] h-[188px]">
<div class="flex">
<span class="ml-[32px] mt-[34px] text-[20px] text-[#333333]">版本信息</span>
<el-button class="ml-[166px] mt-[34px] text-[#DDDDDD]" plain
>检测更新</el-button
>
</div>
<div>
<p class="ml-[32px] mt-[34px] text-[14px] text-[#797979]">
当前版本 <span class="text-[26px]">1.0.35</span
><em class="text-[12px] text-[#797979]">(当前已是最新版本)</em>
</p>
</div>
</div>
<div class="right flex bg-gray-100 w-[1188px] h-[188px]">
<div class="left w-[730px]">
<div class="flex w-[100%]">
<p class="ml-[30px] mt-[34px] text-[20px] text-[#333333]">授权信息</p>
<span class="ml-[30px] mt-[40px] text-[14px] text-[#666666]"
>杭州数字运动科技有限公司</span
>
</div>
<div class="ml-[70px] mt-[44px] w-[100%]">
<span class="text-[14px] text-[#797979]"
>授权域名<em class="ml-[12px] text-[12px] text-[#222222]">sseeee</em></span
>
<span class="text-[14px] ml-[84px] text-[#797979]"
>授权码 <em class="ml-[12px] text-[12px] text-[#222222]">94302</em><el-icon class="text-[12px] ml-[20px]"><View />
</el-icon><el-icon class="text-[12px] ml-[2px]"><Hide /></el-icon></span
>
</div>
</div>
<div class="right flex w-[458px] ml-[200px] mt-[70px]" >
<el-button class="btn1" type="primary" >授权码认证</el-button>
<el-popover :visible="visible" placement="bottom" :width="478" popper-class="popper1">
<p class="leading-[32px] w-[418px] h-[96px] text-[18px] mx-[auto] mt-[40px]">您在官方应用市场购买任意一款应用即可获得授权码输入正确授权码认证通过后即可支持在线升级和其它相关服务</p>
<div style="text-align: right; margin: 0">
<el-button class="btn3 mt-[36px]" size="default" type="plain" @click="visible = false"
>去应用市场逛逛</el-button
>
<el-button class=" btn4 mt-[36px]" size="default" type="plain" text @click="visible = false"
>关闭</el-button
>
</div>
<template #reference>
<el-button class="btn2" @click="visible = true">如何获取授权码?</el-button>
</template>
</el-popover>
</div>
</div>
</div>
<!-- <div class="flex items-center">
<span class="text-[20px]">{{ pageName }}</span>
<span v-if="authinfo" class="text-[14px] ml-[20px] block"> {{ t('authCode') }} {{ authinfo.auth_code }}
<span class="cursor-pointer text-primary" @click="authEvent">{{ t('updateCode') }}</span> </span>
</div>
<div v-if="authinfo" class="mt-[50px]">
</div> -->
<!-- <div v-if="authinfo" class="mt-[50px]">
<el-row>
<el-col :span="8" class="mb-[20px]">
<div class="flex mt-[15px]">
@ -66,99 +122,135 @@
</el-card>
</el-form>
</div>
</el-card>
</div>
</div> -->
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getAuthinfo, setAuthinfo, getAdminAuthinfo } from '@/app/api/module'
import { FormInstance, FormRules } from 'element-plus'
import { useRoute } from 'vue-router'
import { reactive, ref } from "vue";
import { t } from "@/lang";
import { getAuthinfo, setAuthinfo, getAdminAuthinfo } from "@/app/api/module";
import { FormInstance, FormRules } from "element-plus";
import { useRoute } from "vue-router";
const route = useRoute()
const pageName = route.meta.title
const route = useRoute();
const pageName = route.meta.title;
const authinfo = ref('')
const loading = ref(true)
const saveLoading = ref(false)
const authinfo = ref("");
const loading = ref(true);
const saveLoading = ref(false);
const checkAppMange = () => {
getAuthinfo().then(res => {
loading.value = false
if (res.data.data && res.data.data.length != 0) {
authinfo.value = res.data.data
}
}).catch(() => {
loading.value = false
getAuthinfo()
.then((res) => {
loading.value = false;
if (res.data.data && res.data.data.length != 0) {
authinfo.value = res.data.data;
}
})
}
checkAppMange()
.catch(() => {
loading.value = false;
});
};
checkAppMange();
const formData = reactive<Record<string, string>>({
auth_code: '',
auth_secret: ''
})
const formRef = ref<FormInstance>()
auth_code: "",
auth_secret: "",
});
const formRef = ref<FormInstance>();
//
const formRules = reactive<FormRules>({
auth_code: [
{ required: true, message: t('authCodePlaceholder'), trigger: 'blur' }
],
auth_secret: [
{ required: true, message: t('authSecretPlaceholder'), trigger: 'blur' }
]
})
auth_code: [
{ required: true, message: t("authCodePlaceholder"), trigger: "blur" },
],
auth_secret: [
{ required: true, message: t("authSecretPlaceholder"), trigger: "blur" },
],
});
const setFormData = async () => {
const data = await (await getAdminAuthinfo()).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
setFormData()
const data = await (await getAdminAuthinfo()).data;
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key];
});
};
setFormData();
const save = async (formEl: FormInstance | undefined) => {
if (saveLoading.value || !formEl) return
if (saveLoading.value || !formEl) return;
await formEl.validate(async (valid) => {
if (valid) {
saveLoading.value = true
await formEl.validate(async (valid) => {
if (valid) {
saveLoading.value = true;
setAuthinfo(formData).then(() => {
saveLoading.value = false
checkAppMange()
}).catch(() => {
saveLoading.value = false
})
}
})
}
setAuthinfo(formData)
.then(() => {
saveLoading.value = false;
checkAppMange();
})
.catch(() => {
saveLoading.value = false;
});
}
});
};
const authEvent = () => {
authinfo.value = ''
}
authinfo.value = "";
};
const market = () => {
window.open('https://www.niucloud.com/product')
}
window.open("https://www.niucloud.com/product");
};
const visible = ref(false)
</script>
<style lang="scss" scoped>
.app-text {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
}
.main {
background-color: var(--el-bg-color-overlay);
background-color: var(--el-bg-color-overlay);
}
.app-item {
// box-shadow: 0px 6px 18px 0px rgba(82,129,187,0.1);
// box-shadow: 0px 6px 18px 0px rgba(82,129,187,0.1);
}
em{
font-style:normal
}
:deep(.btn1){
width: 154px;
height: 48px;
border: 1px solid #2454FF;
border-radius: 4px;
font-size: 18px;
}
:deep(.btn2){
width: 154px;
height: 48px;
border: 1px solid #2454FF;
border-radius: 4px;
font-size: 18px;
color: #2454FF;
}
:deep(.btn3){
border: 1px solid #2454FF;
border-radius: 4px;
font-size: 18px;
color: #2454FF;
}
:deep(.btn4){
border: 1px solid #2454FF;
border-radius: 4px;
font-size: 18px;
color: #2454FF;
}
</style>

View File

@ -91,8 +91,7 @@
<el-button v-else size="small" :loading="downloading == item.key"
:disabled="downloading != ''" round
class="!text-primary !border-primary !bg-transparent" @click.stop="downEvent(item)">{{
downloading == item.key ? t('downloading') : t('down')
}}</el-button>
t('down') }}</el-button>
</div>
</div>
@ -121,9 +120,7 @@
<el-button v-else size="small" :loading="downloading == item.key"
:disabled="downloading != ''" round
class="!text-primary !border-primary !bg-transparent"
@click.stop="downEvent(item)">{{ downloading == item.key ? t('downloading') :
t('down')
}}</el-button>
@click.stop="downEvent(item)">{{ t('down') }}</el-button>
</div>
</div>
</div>
@ -160,8 +157,7 @@
<el-button v-else size="small" :loading="downloading == item.key"
:disabled="downloading != ''" round
class="!text-primary !border-primary !bg-transparent" @click.stop="downEvent(item)">{{
downloading == item.key ? t('downloading') : t('down')
}}</el-button>
t('down') }}</el-button>
</div>
</div>
@ -193,9 +189,7 @@
<el-button v-else size="small" round :loading="downloading == item.key"
:disabled="downloading != ''"
class="!text-primary !border-primary !bg-transparent"
@click.stop="downEvent(item)">{{ downloading == item.key ? t('downloading') :
t('down')
}}</el-button>
@click.stop="downEvent(item)">{{ t('down') }}</el-button>
</div>
</div>
</div>
@ -231,14 +225,14 @@
</el-dialog>
<!-- 安装弹窗 -->
<el-dialog v-model="installShowDialog" :title="t('addonInstall')" width="60vw" :close-on-click-modal="false"
<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 == 0" v-loading="!installCheckResult.dir">
<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">
@ -292,7 +286,7 @@
</div>
</div>
</el-scrollbar>
<div class="flex justify-end" v-if="mode == 'development'">
<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">{{
@ -306,18 +300,12 @@
}}</el-button>
</el-tooltip>
</div>
<div class="flex justify-end" v-else>
<el-button type="primary" :disabled="!installCheckResult.is_pass" :loading="cloudInstalling"
@click="handleCloudInstall">{{
t('cloudInstall')
}}</el-button>
</div>
</div>
<div v-show="installStep == 1" class="h-[50vh] mt-[20px]">
<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 > 1" class="h-[50vh] mt-[20px] flex flex-col">
<div v-show="installStep == 3" class="h-[50vh] mt-[20px] flex flex-col">
<!-- 提示信息 -->
<div v-for="item in installWarning" class="mb-[10px]">
<el-alert :title="item" type="warning" :closable="false" />
@ -332,15 +320,16 @@
import { ref, watch, computed, h } from 'vue'
import { t } from '@/lang'
import { getAddonLocal, uninstallAddon, installAddon, preInstallCheck, cloudInstallAddon, getAddonInstalltask, getAddonCloudInstallLog } from '@/app/api/addon'
import { downloadVersion } from '@/app/api/module'
import { downloadVersion, getAuthinfo } from '@/app/api/module'
import { TabsPaneContext, ElMessageBox, ElNotification } from 'element-plus'
import { img } from '@/utils/common'
import { Terminal, api as terminalApi } from 'vue-web-terminal'
import { useRouter } from 'vue-router'
const router = useRouter()
const activeName = ref('installed')
const loading = ref<Boolean>(false)
const showType = ref('large')
const mode = ref(import.meta.env.MODE)
const downloading = ref('')
const downEvent = (param: Record<string, any>) => {
@ -374,6 +363,14 @@ const allLabel = computed(() => {
return text
})
const authCode = ref('')
getAuthinfo().then(res => {
if (res.data.data && res.data.data.auth_code) {
authCode.value = res.data.data.auth_code
}
}).catch(() => {
})
/**
* 本地下载的插件列表
*/
@ -422,7 +419,7 @@ const currAddon = ref('')
//
const installShowDialog = ref(false)
//
const installStep = ref(0)
const installStep = ref(1)
//
const installCheckResult = ref({})
//
@ -434,7 +431,7 @@ const installWarning = ref<string[]>([])
*/
const installAddonFn = (key: string) => {
currAddon.value = key
installStep.value = 0
installStep.value = 1
installWarning.value = []
installShowDialog.value = true
@ -488,7 +485,7 @@ getInstallTask()
const checkInstallTask = () => {
installShowDialog.value = true
installStep.value = 1
installStep.value = 2
}
const localInstalling = ref(false)
@ -513,11 +510,16 @@ const cloudInstalling = ref(false)
* 云安装插件
*/
const handleCloudInstall = () => {
if (!authCode.value) {
authElMessageBox()
return
}
if (!installCheckResult.value.is_pass || cloudInstalling.value) return
cloudInstalling.value = true
cloudInstallAddon({ addon: currAddon.value }).then(res => {
installStep.value = 1
installStep.value = 2
terminalApi.execute('my-terminal', 'clear')
terminalApi.pushMessage('my-terminal', { content: '开始安装插件', class: 'info' })
getInstallTask()
@ -527,6 +529,24 @@ const handleCloudInstall = () => {
})
}
const authElMessageBox = () => {
ElMessageBox.confirm(
t('authTips'),
t('warning'),
{
distinguishCancelAndClose: true,
confirmButtonText: t('toBind'),
cancelButtonText: t('toNiucloud')
}
).then(() => {
router.push({ path: '/app/authorize' })
}).catch((action: string) => {
if (action === 'cancel') {
window.open('https://www.niucloud.com/product')
}
})
}
let installLog: string[] = []
const getCloudInstallLog = () => {
getAddonCloudInstallLog(currAddon.value)
@ -576,7 +596,7 @@ const market = () => {
* @param done
*/
const installShowDialogClose = (done: () => {}) => {
if (installStep.value == 1) {
if (installStep.value == 2) {
ElMessageBox.confirm(
t('installShowDialogCloseTips'),
t('warning'),

View File

@ -18,7 +18,7 @@
</el-collapse>
<div class="mt-[50px]">
<el-button type="primary" @click="insert">{{ t('codeDownTwoDesc') }}</el-button>
<el-button type="primary" @click="insert" :loading="uploading">{{ t('codeDownTwoDesc') }}</el-button>
</div>
<el-table class="mt-[15px]" :data="weappTableData.data" v-loading="weappTableData.loading" size="default">
<template #empty>
@ -74,21 +74,22 @@
</template>
</el-dialog>
<el-dialog v-model="uploading" title="" width="300px" :show-close="false" :align-center="true"
<!-- <el-dialog v-model="uploading" title="" width="300px" :show-close="false" :align-center="true"
:close-on-click-modal="false">
<template #default>
<div v-loading="uploading" class="w-full h-[100px]" :element-loading-text="t('uploadingTips')"></div>
</template>
</el-dialog>
</el-dialog> -->
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { setWeappVersion, getWeappPreview, getWeappVersionList, addProcess } from '@/app/api/weapp'
import { setWeappVersion, getWeappPreview, getWeappVersionList, getWeappUploadLog, getWeappConfig } from '@/app/api/weapp'
import { t } from '@/lang'
import { useRoute, useRouter } from 'vue-router'
import { getAuthinfo } from '@/app/api/module'
import { ElMessageBox } from 'element-plus'
const route = useRoute()
const router = useRouter()
@ -115,6 +116,11 @@ getAuthinfo().then(res => {
}).catch(() => {
})
const weappConfig = ref({})
getWeappConfig().then(res => {
weappConfig.value = res.data
})
const activeName = ref('/website/channel/weapp/code')
const handleClick = (val: any) => {
router.push({ path: activeName.value })
@ -135,6 +141,7 @@ const getWeappVersionListFn = (page: number = 1) => {
weappTableData.loading = false
weappTableData.data = res.data.data
weappTableData.total = res.data.total
if (page == 1 && weappTableData.data.length && weappTableData.data[0].status == 0) getWeappUploadLogFn(weappTableData.data[0].task_key)
}).catch(() => {
weappTableData.loading = false
})
@ -142,13 +149,6 @@ const getWeappVersionListFn = (page: number = 1) => {
// loadWeappTemplateList()
getWeappVersionListFn()
const open = () => {
form.value = {
desc: ''
}
dialogVisible.value = true
}
const handleClose = () => {
ruleFormRef.value.clearValidate()
}
@ -156,27 +156,18 @@ const handleClose = () => {
const uploading = ref(false)
const insert = () => {
if (!authCode.value) {
ElMessageBox.confirm(
t('authTips'),
t('warning'),
{
distinguishCancelAndClose: true,
confirmButtonText: t('toBind'),
cancelButtonText: t('toNiucloud')
}
).then(() => {
router.push({ path: '/app/authorize' })
}).catch((action: string) => {
if (action === 'cancel') {
window.open('https://www.niucloud.com/product')
}
})
authElMessageBox()
return
}
if (!weappConfig.value.app_id) {
configElMessageBox()
return
}
if (uploading.value) return
uploading.value = true
setWeappVersion(form.value).then(() => {
setWeappVersion(form.value).then(res => {
getWeappVersionListFn()
uploading.value = false
}).catch(() => {
@ -194,8 +185,56 @@ const getWeappPreviewImage = () => {
.catch()
}
const processEvent = (item) => {
addProcess({ id: item.id })
const getWeappUploadLogFn = (key: string) => {
getWeappUploadLog(key).then(res => {
const data = res.data.data ?? []
if (data[0] && data[0].length) {
const last = data[0][data[0].length - 1]
if (last.code == 0) {
getWeappVersionListFn()
return
}
if (last.code == 1 && last.percent == 100) {
getWeappVersionListFn()
return
}
setTimeout(() => {
getWeappUploadLogFn(key)
}, 2000)
}
})
}
const authElMessageBox = () => {
ElMessageBox.confirm(
t('authTips'),
t('warning'),
{
distinguishCancelAndClose: true,
confirmButtonText: t('toBind'),
cancelButtonText: t('toNiucloud')
}
).then(() => {
router.push({ path: '/app/authorize' })
}).catch((action: string) => {
if (action === 'cancel') {
window.open('https://www.niucloud.com/product')
}
})
}
const configElMessageBox = () => {
ElMessageBox.confirm(
t('weappTips'),
t('warning'),
{
confirmButtonText: t('toSetting'),
cancelButtonText: t('cancel')
}
).then(() => {
router.push({ path: '/website/channel/weapp/config' })
}).catch((action: string) => {
})
}
</script>

View File

@ -14,7 +14,7 @@
</div>
<div class="flex flex-wrap plug-list pb-10 plug-large" v-if="applyList.list.length">
<div v-for="(item, index) in applyList.list" :key="index + 'b'">
<div v-if="appLink[item.key] && item.type == 'addon'" class="relative app-item cursor-pointer px-4 mr-4 mt-[20px] bg-[#f7f7f7] border-[1px] hover:border-primary">
<div class="relative app-item cursor-pointer px-4 mr-4 mt-[20px] bg-[#f7f7f7] border-[1px] hover:border-primary">
<div @click="toLink(item.key)" class="flex py-5 items-center">
<div class="flex justify-center items-center">
<el-image class="w-[40px] h-[40px]" :src="img(item.icon)" fit="contain">
@ -64,10 +64,12 @@ const applyList = reactive({
let loading = ref(true)
const getApplelist = async () => {
const res = await getApply({title: applyList.search.title})
applyList.list = res.data
applyList.list = res.data.filter(el=>{
return appLink.value[el.key] &&el.type == 'addon'
})
loading.value = false
}
getApplelist()
const appLink = ref({})
const getAppLink = () => {
@ -80,6 +82,7 @@ const getAppLink = () => {
}
}
})
getApplelist()
}
getAppLink()

View File

@ -9,7 +9,7 @@
</div>
<div class="flex flex-wrap mt-[28px]">
<template v-for="(item, index) in detail.appList" :key="index">
<div class="app-item w-[284px] box-border p-[18px] pb-[24px] bg-[#fff] rounded-[8px] cursor-pointer mr-[24px]"
<div class="app-item w-[284px] box-border p-[18px] pb-[24px] bg-[#fff] rounded-[8px] cursor-pointer mr-[24px] mb-[24px]"
@click="itemPath(item.key)">
<div class="flex items-center">
<el-image class="w-[40px] h-[40px] rounded-[8px]" :src="img(item.icon)" fit="contain">
@ -72,6 +72,10 @@ const itemPath = (key: any) => {
</script>
<style lang="scss" scoped>
.main-container{
background: linear-gradient(180deg, rgba(253,253,253,0.24) 0%, #FAFAFA 100%);
min-height: calc(100vh - 63px);
}
.overview-top {
background-image: url('@/app/assets/images/index/overview.png');
background-repeat: no-repeat;

View File

@ -1,13 +1,13 @@
<template>
<div class="main-container attachment-container" v-if="systemService">
<el-card class="box-card !border-none" shadow="never">
<div class="main-container attachment-container" v-loading="loadingArr.server_load">
<el-card class="box-card !border-none" shadow="never" v-if="systemService">
<div class="flex justify-between items-center">
<span class="text-[20px]">{{ pageName }}</span>
</div>
<div class="bg-[#fff] pb-[20px] mb-3">
<p class="pt-[20px] pb-[10px] text-sm">{{ t('serverInformation') }}</p>
<div class="text-[14px]">
<el-table :data="systemService.server" size="large" v-loading="loadingArr.server_load">
<el-table :data="systemService.server" size="large">
<el-table-column prop="name" :label="t('environment')" align="left" min-width="200" />
<el-table-column prop="server" :label="t('version')" align="left" min-width="140" />
</el-table>
@ -16,7 +16,7 @@
<div class="bg-[#fff] pb-[20px] mb-3">
<p class="py-[20px] text-sm">{{ t('systemDemand') }}</p>
<div class="text-[14px]">
<el-table :data="systemService.server_version" size="large" v-loading="loadingArr.server_version_load">
<el-table :data="systemService.server_version" size="large">
<el-table-column prop="name" :label="t('environment')" align="left" min-width="200" />
<el-table-column prop="demand" :label="t('demand')" align="left" min-width="140" />
<el-table-column prop="server" :label="t('version')" align="left" min-width="140" />
@ -26,7 +26,7 @@
<div class="bg-[#fff] pb-[20px] mb-3">
<p class="py-[20px] text-sm">{{ t('authorityStatus') }}</p>
<div class="text-[14px]">
<el-table :data="systemService.system_variables" size="large" v-loading="loadingArr.system_variables_load">
<el-table :data="systemService.system_variables" size="large">
<el-table-column prop="name" :label="t('name')" align="left" min-width="200" />
<el-table-column prop="need" :label="t('demand')" align="left" min-width="140" />
<el-table-column :label="t('status')" align="left" min-width="140">
@ -42,11 +42,10 @@
</el-table>
</div>
</div>
<div class="bg-[#fff] pb-[20px] mb-3">
<p class="py-[20px] text-sm">{{ t('process') }}</p>
<div class="text-[14px]">
<el-table :data="systemService.process" size="large" v-loading="loadingArr.process_load">
<el-table :data="systemService.process" size="large">
<el-table-column prop="name" :label="t('name')" align="left" min-width="200" />
<el-table-column prop="need" :label="t('demand')" align="left" min-width="140" />
<el-table-column :label="t('status')" align="left" min-width="140">
@ -78,21 +77,16 @@ const pageName = route.meta.title
const systemService = ref([])
let loadingArr = reactive({
"server_load": true,
"server_version_load": true,
"system_variables_load": true,
"process_load": true
})
const getSystemService = () => {
loadingArr.server_load = true;
loadingArr.server_version_load = true;
loadingArr.system_variables_load = true;
loadingArr.process_load = true;
getSystem().then(res => {
systemService.value = res.data
loadingArr.server_load = false;
loadingArr.server_version_load = false;
loadingArr.system_variables_load = false;
loadingArr.process_load = false;
})
.catch(()=>{
loadingArr.server_load = false;
})
}
getSystemService()

View File

@ -1,23 +1,11 @@
<template>
<div :class="['flex', { 'two-type': sidebar == 'twoType' }, { 'three-type': sidebar == 'threeType' }]">
<div :class="['flex', { 'two-type': sidebar == 'twoType' }, { 'three-type': sidebar == 'threeType' }]" v-if="isLoad">
<div class="w-[65px] overflow-hidden" v-if="!floatMenuStyle">
<el-aside
:class="['h-screen layout-aside w-[65px] pb-[30px] bg-[#F7F8FA] ease-in duration-200', { 'bright': !dark }]">
<!-- 一级菜单 -->
<div class="h-full flex flex-col relative">
<!-- <el-header class="logo-wrap h-auto mb-[10px]">
<div class="logo flex items-center m-auto max-w-[210px] h-[60px] justify-center"#19233C>
<span class="iconfont iconyun text-[#999] !text-[36px]"></span>
</div>
</el-header> -->
<!-- <template v-for="(item, index) in applyList" :key="index">
<div v-if="item.type == 'app'" @click="appToLink(item.key)"
class=" flex items-center justify-center h-[45px] mb-[5px] cursor-pointer text-[#6d7278] hover:bg-[#f1f2f6] menu-item hover:text-color whitespace-nowrap">
<img :src="img(item.icon)" class="w-[35px] h-[35px] rounded-full" alt="" :title="item.title">
</div>
</template> -->
<div class="h-full flex flex-col relative">
<div class=" flex items-center justify-center h-[64px] cursor-pointer cut-style"
@click="floatActive = !floatActive">
<span class="iconfont icontuodong !text-[30px] "></span>
@ -43,11 +31,9 @@
</div>
<!-- 浮动样式的应用菜单 -->
<div v-if="!floatMenuStyle && floatActive && applyList.filter(el => { return el.type === 'app' }).length"
class="flex absolute bg-[#fff] w-[640px] px-[28px] py-[20px] flex-wrap left-0 top-[65px] z-10 box-border shadow-lg">
class="flex absolute bg-[#fff] w-[640px] px-[28px] py-[20px] flex-wrap left-0 top-[65px] z-50 box-border shadow-lg">
<template v-for="(item, index) in applyList" :key="index">
<div v-if="item.type == 'app'" @click="appToLink(item.key)"
class="flex items-center cursor-pointer text-[#6d7278] hover:bg-[#f1f2f6] whitespace-nowrap py-[10px] px-[15px]">
<div v-if="item.type == 'app'" @click="toLink(item)" class="flex items-center cursor-pointer text-[#6d7278] hover:bg-[#f1f2f6] whitespace-nowrap py-[10px] px-[15px] box-border w-[165px]">
<img :src="img(item.icon)" class="w-[44px] h-[44px] rounded-full mr-[5px]" alt="" :title="item.title">
<span>{{ item.title }}</span>
</div>
@ -60,20 +46,19 @@
class="group flex flex-col items-center justify-center h-[64px] border-b-[1px] border-solid second-head cursor-pointer relative">
<div class="flex items-center">
<template v-if="floatMenuStyle">
<img v-if="appInfo.icon" :src="img(appInfo.icon)" class="w-[40px] h-[40px] mr-[8px]" alt="">
<div class="flex items-center justify-center w-[30px] h-[30px]"
v-else-if="Object.keys(appInfo).length">
<img v-if="item.meta.parentIcon" :src="img(item.meta.parentIcon)" class="w-[40px] h-[40px] mr-[8px]" alt="">
<div class="flex items-center justify-center w-[30px] h-[30px]" v-else>
<icon v-if="item.meta.icon" :name="item.meta.icon" class="!w-auto" size="24px" />
</div>
</template>
<span>{{ item.meta.app ? appInfo.title : item.meta.title }}</span>
<span>{{ item.meta.app ? item.meta.parentTitle : item.meta.title }}</span>
</div>
<!-- 浮动样式的应用菜单 -->
<div v-if="floatMenuStyle && applyList.filter(el => { return el.type === 'app' }).length"
class="hidden group-hover:flex absolute bg-[#fff] w-[640px] px-[28px] py-[20px] flex-wrap left-0 top-[65px] z-10 box-border shadow-lg">
class="hidden group-hover:flex absolute bg-[#fff] w-[640px] px-[28px] py-[20px] flex-wrap left-0 top-[65px] z-[5555] box-border shadow-lg">
<template v-for="(item, index) in applyList" :key="index">
<div v-if="item.type == 'app'" @click="appToLink(item.key)"
class="flex items-center justify-center cursor-pointer text-[#6d7278] hover:bg-[#f1f2f6] whitespace-nowrap py-[10px] px-[15px]">
<div v-if="item.type == 'app'" @click="toLink(item)"
class="flex items-center cursor-pointer text-[#6d7278] hover:bg-[#f1f2f6] whitespace-nowrap py-[10px] px-[15px] w-[165px] box-border">
<img :src="img(item.icon)" class="w-[44px] h-[44px] rounded-full mr-[5px]" alt=""
:title="item.title">
<span>{{ item.title }}</span>
@ -235,6 +220,7 @@
</template>
</el-menu-item>
</template>
<!-- 插件菜单 -->
<template v-if="otherTypeList.includes(localMenuKey) && plugMenuType">
<template v-for="(twoMenu, twoIndex) in menus">
@ -422,12 +408,12 @@ const globalAppKey = ref('') // 菜单类型
const localMenuKey = ref('') //
globalAppKey.value = storage.get('menuAppStorage')
localMenuKey.value = storage.get('menuAppStorage')
const isLoad = ref(false);
// start
const applyList = ref([])
const applyTypeList = ref([])
const otherTypeList = ref([]) // \\
// let aaa = ref(true)
const getApplelist = async () => {
const res = await getApply()
applyList.value = applyList.value.concat(res.data)
@ -435,58 +421,43 @@ const getApplelist = async () => {
if (item.type == 'app') { applyTypeList.value.push(item.key) }
if (item.type == 'addon') { otherTypeList.value.push(item.key) }
})
otherTypeList.value = otherTypeList.value.concat(['member', 'overview'])
// aaa.value = true;
otherTypeList.value = otherTypeList.value.concat(['member', 'app_center'])
isLoad.value = true;
}
getApplelist()
const floatActive = ref(false)
const appLink = ref({})
const getAppLink = () => {
userStore.routers.forEach((item, index) => {
if (item.meta.app != '') {
if (item.children && item.children.length) {
appLink.value[item.meta.app] = findFirstValidRoute(item.children)
} else {
appLink.value[item.meta.app] = item.name
}
}
})
}
getAppLink()
const appToLink = (addon: string) => {
globalAppKey.value = addon
localMenuKey.value = addon
storage.set({ key: 'menuAppStorage', data: addon })
storage.set({ key: 'plugMenuTypeStorage', data: '' })
const data = userStore.appMenuList
if (!data.length) {
data.push(addon)
} else if (!data.includes(addon)) {
data.push(addon)
}
userStore.setAppMenuList(data)
floatActive.value = false
router.push({ name: appLink.value[addon] })
}
const homeClick = () => {
const key = storage.get('menuAppStorage')
key ? router.push({ name: appLink.value[key] }) : router.push({ path: '/' })
}
// end
//
const appLink = ref({})
const menus = computed(() => {
const menus = []
userStore.routers.forEach((item, index) => {
if (item.children && item.children.length) {
item.name = findFirstValidRoute(item.children)
appLink.value[item.meta.app] = findFirstValidRoute(item.children)
menus.push(item)
} else {
appLink.value[item.meta.app] = item.name
menus.push(item)
}
})
if(applyList.value && applyList.value.length){
applyList.value.forEach((item,index) =>{
menus.forEach((menuItem,menuIndex)=>{
if(item.key == menuItem.meta.key){
menuItem.meta.parentTitle = item.title;
menuItem.meta.parentIcon = item.icon;
}
})
})
}
return menus
})
@ -494,14 +465,7 @@ const dark = computed(() => {
return systemStore.dark
})
//
const appInfo = ref({})
const getAppInfo = (type) => {
getAddonByKey(type).then(res => {
appInfo.value = res.data
})
}
//
let currMetaAppType = ''
const plugMenuType = ref('') //
const currentRoute = ref('') //
@ -512,28 +476,29 @@ watch(route, () => {
currentRoute.value = route.matched[1]
localMenuKey.value = data.meta.key
data.meta.app = !data.meta.app && !data.meta.attr ? 'member' : data.meta.app
// applist
setTimeout(() => {
//
if (data.meta.app && (!currMetaAppType || currMetaAppType != data.meta.app)) {
appInfo.value = {}
currMetaAppType = data.meta.app
const appInfoKey = otherTypeList.value.includes(data.meta.app) ? globalAppKey.value : data.meta.app
getAppInfo(appInfoKey)
}
}, 800)
systemStore.$patch(state => {
state.menuDrawer = false
})
}, { immediate: true })
//
const toLink = (data) => {
if (data.meta.key != 'official_market') {
router.push({ name: data.name })
if (!data.meta && data.type == 'app' || data.meta.key != 'official_market') {
let name = data.name;
if(data.type == 'app'){
globalAppKey.value = data.key
localMenuKey.value = data.key
storage.set({ key: 'menuAppStorage', data: data.key })
storage.set({ key: 'plugMenuTypeStorage', data: '' })
const appMenuList = userStore.appMenuList
appMenuList.push(data.key)
userStore.setAppMenuList(appMenuList)
floatActive.value = false
name = appLink.value[data.key];
}
router.push({ name: name })
} else {
window.open('https://www.niucloud.com/product/', '_blank')
}
@ -560,6 +525,7 @@ const isTwoMenuFn = (item) => {
|| (floatMenuStyle.value && applyTypeList.value.includes(localMenuKey.value) && (item.meta.key == localMenuKey.value || item.meta.app == localMenuKey.value))
|| (floatMenuStyle.value && !applyTypeList.value.length && (item.meta.key == localMenuKey.value || item.meta.app == localMenuKey.value))
|| (!floatMenuStyle.value && !otherTypeList.value.includes(localMenuKey.value) && (item.meta.key == localMenuKey.value || item.meta.app == localMenuKey.value))
return bool;
}
</script>

View File

@ -29,7 +29,7 @@
<icon name="iconfont-iconqiehuan" :title="t('indexSwitch')" />
</div>
<!-- 切换语言 -->
<div class="navbar-item flex items-center h-full cursor-pointer">
<div class="navbar-item !px-[0] flex items-center h-full cursor-pointer">
<switch-lang />
</div>
<!-- 切换全屏 -->
@ -38,7 +38,7 @@
<icon name="iconfont-iconquanping" v-else />
</div>
<!-- 布局设置 -->
<div class="navbar-item flex items-center h-full cursor-pointer">
<div class="navbar-item !px-[0] flex items-center h-full cursor-pointer">
<layout-setting />
</div>
<!-- 用户信息 -->

View File

@ -1,6 +1,8 @@
<template>
<div class="flex">
<icon name="element-Setting" @click="drawer = true" />
<div class="flex w-[100%] h-[100%]" @click="drawer = true">
<div class="h-[100%] w-[100%] flex items-center justify-center px-[8px]">
<icon name="element-Setting" />
</div>
<el-drawer v-model="drawer" :title="t('layout.layoutSetting')" size="300px">
<el-scrollbar>
<!-- 风格切换 -->

View File

@ -1,6 +1,9 @@
<template>
<el-dropdown @command="switchLang" :tabindex="1">
<icon name="iconfont-iconfanyi" />
<el-dropdown @command="switchLang" :tabindex="1" class="h-[100%] w-[100%]">
<div class="h-[100%] w-[100%] flex items-center justify-center px-[8px]">
<icon name="iconfont-iconfanyi" />
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="zh-cn" :disabled="systemStore.lang == 'zh-cn'">简体中文</el-dropdown-item>

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 3883393 */
src: url('//at.alicdn.com/t/c/font_3883393_0ym8w80fw9vi.woff2?t=1694854845443') format('woff2'),
url('//at.alicdn.com/t/c/font_3883393_0ym8w80fw9vi.woff?t=1694854845443') format('woff'),
url('//at.alicdn.com/t/c/font_3883393_0ym8w80fw9vi.ttf?t=1694854845443') format('truetype');
src: url('//at.alicdn.com/t/c/font_3883393_bq3in2lb5mh.woff2?t=1695086543767') format('woff2'),
url('//at.alicdn.com/t/c/font_3883393_bq3in2lb5mh.woff?t=1695086543767') format('woff'),
url('//at.alicdn.com/t/c/font_3883393_bq3in2lb5mh.ttf?t=1695086543767') format('truetype');
}
.iconfont {
@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale;
}
.iconicon_huojian:before {
content: "\e677";
}
.iconanzhuang:before {
content: "\e676";
}