mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2025-12-14 10:32:49 +00:00
fix admin
This commit is contained in:
parent
08d14372e1
commit
8cb683f8fe
2
admin/components.d.ts
vendored
2
admin/components.d.ts
vendored
@ -62,6 +62,8 @@ declare module '@vue/runtime-core' {
|
|||||||
ElRow: typeof import('element-plus/es')['ElRow']
|
ElRow: typeof import('element-plus/es')['ElRow']
|
||||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
||||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||||
|
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
|
||||||
|
ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
|
||||||
ElSlider: typeof import('element-plus/es')['ElSlider']
|
ElSlider: typeof import('element-plus/es')['ElSlider']
|
||||||
ElStatistic: typeof import('element-plus/es')['ElStatistic']
|
ElStatistic: typeof import('element-plus/es')['ElStatistic']
|
||||||
ElStep: typeof import('element-plus/es')['ElStep']
|
ElStep: typeof import('element-plus/es')['ElStep']
|
||||||
|
|||||||
@ -95,3 +95,10 @@ export function syncSiteWeapp(params: Record<string, any>) {
|
|||||||
export function getAuthRecord(params: Record<string, any>) {
|
export function getAuthRecord(params: Record<string, any>) {
|
||||||
return request.get('wxoplatform/authorization/record', { params })
|
return request.get('wxoplatform/authorization/record', { params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消授权
|
||||||
|
*/
|
||||||
|
export function cancelAuthorization(params: Record<string, any>) {
|
||||||
|
return request.post('wxoplatform/authorization/cancel', params, { showSuccessMessage: true })
|
||||||
|
}
|
||||||
|
|||||||
@ -45,5 +45,11 @@
|
|||||||
"failReason": "失败原因",
|
"failReason": "失败原因",
|
||||||
"appVersionReleaseTips": "发布后无法再对该版本进行修改,确定要发布该版本吗?",
|
"appVersionReleaseTips": "发布后无法再对该版本进行修改,确定要发布该版本吗?",
|
||||||
"appVersionDeleteTips": "确定要删除该版本吗?",
|
"appVersionDeleteTips": "确定要删除该版本吗?",
|
||||||
"upgradeType": "升级方式"
|
"upgradeType": "升级方式",
|
||||||
|
"seeBuildLog": "查看打包日志",
|
||||||
|
"buildLog": "打包日志",
|
||||||
|
"authTips": "上传代码需先绑定授权码,如果已有授权请先进行绑定,没有授权可到niucloud官网购买云服务之后再进行操作",
|
||||||
|
"toBind": "绑定授权",
|
||||||
|
"toNiucloud": "去niucloud官网",
|
||||||
|
"siteAuthTips": "上传代码需先绑定授权码,请联系平台管理员进行绑定"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
<el-button type="primary" class="w-[100px]" @click="addEvent">
|
<el-button type="primary" class="w-[100px]" @click="addEvent">
|
||||||
{{ t('addMenu') }}
|
{{ t('addMenu') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button class="w-[100px]" @click="refreshMenu">
|
<el-button class="w-[100px]" :loading="refreshLoading" @click="refreshMenu">
|
||||||
{{ t('initializeMenu') }}
|
{{ t('initializeMenu') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@ -82,6 +82,7 @@ const getMenuList = () => {
|
|||||||
}
|
}
|
||||||
getMenuList()
|
getMenuList()
|
||||||
// 重置菜单
|
// 重置菜单
|
||||||
|
const refreshLoading = ref(false)
|
||||||
const refreshMenu = () => {
|
const refreshMenu = () => {
|
||||||
ElMessageBox.confirm(h('div', null, [
|
ElMessageBox.confirm(h('div', null, [
|
||||||
h('p', null, t('initializeMenuTipsOne')),
|
h('p', null, t('initializeMenuTipsOne')),
|
||||||
@ -93,9 +94,11 @@ const refreshMenu = () => {
|
|||||||
// type: 'warning'
|
// type: 'warning'
|
||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
|
refreshLoading.value = true
|
||||||
menuRefresh({}).then(res => {
|
menuRefresh({}).then(res => {
|
||||||
location.reload()
|
refreshLoading.value = false
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
refreshLoading.value = false
|
||||||
})
|
})
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
})
|
})
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
</el-alert>
|
</el-alert>
|
||||||
|
|
||||||
<div class="mt-[20px]">
|
<div class="mt-[20px]">
|
||||||
<el-button type="primary" @click="addEvent">{{ t('addAppVersion') }}</el-button>
|
<el-button type="primary" @click="addEvent" :disabled="loading">{{ t('addAppVersion') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-[10px]">
|
<div class="mt-[10px]">
|
||||||
@ -41,7 +41,11 @@
|
|||||||
|
|
||||||
<el-table-column prop="platform_name" :label="t('platform')" min-width="120" :show-overflow-tooltip="true"/>
|
<el-table-column prop="platform_name" :label="t('platform')" min-width="120" :show-overflow-tooltip="true"/>
|
||||||
|
|
||||||
<el-table-column prop="status_name" :label="t('status')" min-width="120" :show-overflow-tooltip="true"/>
|
<el-table-column prop="status_name" :label="t('status')" min-width="120" align="center" :show-overflow-tooltip="true">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button link :loading="row.status == 'creating'">{{ row.status_name }}</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column prop="status" :label="t('isForcedUpgradeTitle')" min-width="120" align="center" :show-overflow-tooltip="true">
|
<el-table-column prop="status" :label="t('isForcedUpgradeTitle')" min-width="120" align="center" :show-overflow-tooltip="true">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
@ -63,7 +67,7 @@
|
|||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button type="primary" link v-if="row.release_time == 0" @click="editEvent(row)">{{ t('edit') }}</el-button>
|
<el-button type="primary" link v-if="row.release_time == 0" @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||||
<el-button type="primary" link v-if="row.status == 'upload_success'" @click="releaseEvent(row)">{{ t('release') }}</el-button>
|
<el-button type="primary" link v-if="row.status == 'upload_success'" @click="releaseEvent(row)">{{ t('release') }}</el-button>
|
||||||
<el-button type="primary" link v-if="row.status == 'create_fail'" @click="handleFailReason(row)">{{ t('failReason') }}</el-button>
|
<el-button type="primary" link v-if="row.status == 'creating'" @click="seeBuildLog(row)">{{ t('seeBuildLog') }}</el-button>
|
||||||
<el-button type="primary" link v-if="row.package_path && row.upgrade_type != 'market'" @click="downloadEvent(row)">{{ t('download') }}</el-button>
|
<el-button type="primary" link v-if="row.package_path && row.upgrade_type != 'market'" @click="downloadEvent(row)">{{ t('download') }}</el-button>
|
||||||
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
|
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
@ -86,21 +90,31 @@
|
|||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<el-dialog v-model="showDialog" :title="t('buildLog')" width="850px" :close-on-click-modal="false" :close-on-press-escape="false" :before-close="dialogClose">
|
||||||
|
<div class="h-[370px]">
|
||||||
|
<terminal ref="terminalRef" :name="`upgrade-${terminalId}`" context="" :init-log="null" :show-header="false" :show-log-time="true" @exec-cmd="onExecCmd" />
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
</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 { img } from '@/utils/common'
|
import { img, getAppType } from '@/utils/common'
|
||||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||||
import { getVersionList, getBuildLog, deleteVersion, releaseVersion } from '@/app/api/app'
|
import { getVersionList, getBuildLog, deleteVersion, releaseVersion } from '@/app/api/app'
|
||||||
import Edit from '@/app/views/channel/app/components/app-version-edit.vue'
|
import Edit from '@/app/views/channel/app/components/app-version-edit.vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
import { Terminal, TerminalFlash } from 'vue-web-terminal'
|
||||||
|
import 'vue-web-terminal/lib/theme/dark.css'
|
||||||
|
import { getAuthInfo } from '@/app/api/module'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const pageName = route.meta.title
|
const pageName = route.meta.title
|
||||||
const activeName = ref('/channel/app/version')
|
const activeName = ref('/channel/app/version')
|
||||||
|
const terminalRef: any = ref(null)
|
||||||
const appVersionTable = reactive({
|
const appVersionTable = reactive({
|
||||||
page: 1,
|
page: 1,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
@ -111,6 +125,18 @@ const appVersionTable = reactive({
|
|||||||
platfrom: ''
|
platfrom: ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const showDialog = ref(false)
|
||||||
|
const loading = ref(true)
|
||||||
|
const authCode = ref('')
|
||||||
|
|
||||||
|
getAuthInfo().then(res => {
|
||||||
|
if (res.data.data && res.data.data.auth_code) {
|
||||||
|
authCode.value = res.data.data.auth_code
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
|
||||||
const handleClick = (val: any) => {
|
const handleClick = (val: any) => {
|
||||||
router.push({ path: activeName.value })
|
router.push({ path: activeName.value })
|
||||||
@ -146,6 +172,10 @@ const editAppVersionDialog: Record<string, any> | null = ref(null)
|
|||||||
* 添加app版本管理
|
* 添加app版本管理
|
||||||
*/
|
*/
|
||||||
const addEvent = () => {
|
const addEvent = () => {
|
||||||
|
if (!authCode.value) {
|
||||||
|
authElMessageBox()
|
||||||
|
return
|
||||||
|
}
|
||||||
editAppVersionDialog.value.setFormData()
|
editAppVersionDialog.value.setFormData()
|
||||||
editAppVersionDialog.value.showDialog = true
|
editAppVersionDialog.value.showDialog = true
|
||||||
}
|
}
|
||||||
@ -192,20 +222,70 @@ const releaseEvent = (data: any) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let buildLog = []
|
||||||
const getAppBuildLogFn = (key: string) => {
|
const getAppBuildLogFn = (key: string) => {
|
||||||
getBuildLog(key).then(res => {
|
getBuildLog(key).then(res => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
if (res.data.status == '') {
|
if (res.data.status == '') {
|
||||||
|
if (showDialog.value) {
|
||||||
|
if (!buildLog.length) {
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
terminalRef.value.execute('开始打包')
|
||||||
|
}
|
||||||
|
res.data.build_log.data[0].forEach((item) => {
|
||||||
|
if (!buildLog.includes(item.action)) {
|
||||||
|
terminalRef.value.pushMessage({ content: `${item.action}` })
|
||||||
|
buildLog.push(item.action)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
getAppBuildLogFn(key)
|
getAppBuildLogFn(key)
|
||||||
}, 2000)
|
}, 2000)
|
||||||
} else {
|
} else {
|
||||||
|
if (res.data.status == 'fail' && showDialog.value) {
|
||||||
|
terminalRef.value.pushMessage({ content: res.data.fail_reason, class: 'error' })
|
||||||
|
} else {
|
||||||
|
showDialog.value = false
|
||||||
|
}
|
||||||
loadAppVersionList()
|
loadAppVersionList()
|
||||||
|
buildLog = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const seeBuildLog = () => {
|
||||||
|
showDialog.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 升级进度动画
|
||||||
|
*/
|
||||||
|
let flashInterval: any = null
|
||||||
|
const terminalFlash = new TerminalFlash()
|
||||||
|
const onExecCmd = (key, command, success, failed, name) => {
|
||||||
|
if (command == '开始打包') {
|
||||||
|
success(terminalFlash)
|
||||||
|
const frames = makeIterator(['/', '——', '\\', '|'])
|
||||||
|
flashInterval = setInterval(() => {
|
||||||
|
terminalFlash.flush('> ' + frames.next().value)
|
||||||
|
}, 150)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeIterator = (array: string[]) => {
|
||||||
|
let nextIndex = 0
|
||||||
|
return {
|
||||||
|
next () {
|
||||||
|
if (nextIndex + 1 == array.length) {
|
||||||
|
nextIndex = 0
|
||||||
|
}
|
||||||
|
return { value: array[nextIndex++] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const failReason = ref('')
|
const failReason = ref('')
|
||||||
const failReasonDialogVisible = ref(false)
|
const failReasonDialogVisible = ref(false)
|
||||||
const handleFailReason = (data: any) => {
|
const handleFailReason = (data: any) => {
|
||||||
@ -222,6 +302,28 @@ const resetForm = (formEl: FormInstance | undefined) => {
|
|||||||
formEl.resetFields()
|
formEl.resetFields()
|
||||||
loadAppVersionList()
|
loadAppVersionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const authElMessageBox = () => {
|
||||||
|
if (getAppType() == 'admin') {
|
||||||
|
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/app')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
ElMessageBox.alert(t('siteAuthTips'), t('warning'))
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@ -45,6 +45,24 @@
|
|||||||
<template v-if="oplatformConfig.app_id && oplatformConfig.app_secret">
|
<template v-if="oplatformConfig.app_id && oplatformConfig.app_secret">
|
||||||
<el-button type="primary" @click="router.push('/channel/weapp/config')">{{ weappConfig.app_id ? t("seeConfig") : t("weappSettingBtn") }}</el-button>
|
<el-button type="primary" @click="router.push('/channel/weapp/config')">{{ weappConfig.app_id ? t("seeConfig") : t("weappSettingBtn") }}</el-button>
|
||||||
<el-button type="primary" plain @click="authBindWeapp">{{ weappConfig.is_authorization ? t("refreshAuth") : t("authWeapp") }}</el-button>
|
<el-button type="primary" plain @click="authBindWeapp">{{ weappConfig.is_authorization ? t("refreshAuth") : t("authWeapp") }}</el-button>
|
||||||
|
<template v-if="weappConfig.is_authorization">
|
||||||
|
<el-button type="primary" plain @click="cencelAuth" >{{ t("取消授权") }}</el-button>
|
||||||
|
<el-tooltip class="box-item" effect="light" placement="top">
|
||||||
|
<el-icon color="#666" size="15px" class="ml-[5px]">
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
<template #content>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
非通过API创建的开放平台账号需要登录微信公众品平台进行取消授权操作
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
微信公众平台: <a class="ml-[3px] text-[var(--el-color-primary)]" target="_blank" href="https://mp.weixin.qq.com/cgi-bin/loginpage">https://mp.weixin.qq.com/cgi-bin/loginpage</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-button type="primary" @click="router.push('/channel/weapp/config')">{{ t("weappSettingBtn") }}</el-button>
|
<el-button type="primary" @click="router.push('/channel/weapp/config')">{{ t("weappSettingBtn") }}</el-button>
|
||||||
@ -107,9 +125,10 @@ import { onMounted, onUnmounted, ref } from 'vue'
|
|||||||
import { t } from '@/lang'
|
import { t } from '@/lang'
|
||||||
import { img } from '@/utils/common'
|
import { img } from '@/utils/common'
|
||||||
import { getWeappConfig } from '@/app/api/weapp'
|
import { getWeappConfig } from '@/app/api/weapp'
|
||||||
import { getAuthorizationUrl } from '@/app/api/wxoplatform'
|
import { getAuthorizationUrl ,cancelAuthorization} from '@/app/api/wxoplatform'
|
||||||
import { getWxoplatform } from '@/app/api/sys'
|
import { getWxoplatform } from '@/app/api/sys'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
import { ElMessageBox } from 'element-plus'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@ -158,6 +177,24 @@ const authBindWeapp = () => {
|
|||||||
window.open(data)
|
window.open(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const repeat = ref(false)
|
||||||
|
const cencelAuth = () => {
|
||||||
|
ElMessageBox.confirm(t('确认取消授权吗?'), t('warning'),
|
||||||
|
{
|
||||||
|
confirmButtonText: t('confirm'),
|
||||||
|
cancelButtonText: t('cancel'),
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
if (repeat.value) return
|
||||||
|
repeat.value = true
|
||||||
|
cancelAuthorization({}).then(() => {
|
||||||
|
repeat.value = false
|
||||||
|
}).catch(() => {
|
||||||
|
repeat.value = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@ -14,13 +14,32 @@
|
|||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
<div class="mt-[20px]" v-if="!weappConfig.is_authorization">
|
<div class="mt-[20px]" v-if="!weappConfig.is_authorization">
|
||||||
<el-button type="primary" @click="insert" :loading="uploading" :disabled="loading">{{ t('cloudRelease') }}</el-button>
|
<el-button type="primary" @click="openDialog" :loading="uploading" :disabled="loading">{{ t('cloudRelease') }}</el-button>
|
||||||
<el-button @click="localInsert" :disabled="loading">{{ t('localRelease') }}</el-button>
|
<el-button @click="localInsert" :disabled="loading">{{ t('localRelease') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[20px]" v-else>
|
<div class="mt-[20px]" v-else>
|
||||||
<el-button type="primary" @click="againUpload" :loading="uploading" :disabled="loading">{{ t('uploadWeapp') }}</el-button>
|
<el-button type="primary" @click="againUpload" :loading="uploading" :disabled="loading">{{ t('uploadWeapp') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="text-[14px] mt-[15px]">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div v-if="weappTableData.version_info.release_version">
|
||||||
|
线上版本: <span class="mr-10 text-primary">{{ weappTableData.version_info.release_version }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="weappTableData.version_info.release_time">
|
||||||
|
发布时间: <span >{{ weappTableData.version_info.release_time }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div v-if="weappTableData.version_info.exp_version" class="mt-2">
|
||||||
|
体验版本: <span class="mr-10 text-primary">{{ weappTableData.version_info.exp_version }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="weappTableData.version_info.exp_time" class="mt-2">
|
||||||
|
过期时间: <span >{{ weappTableData.version_info.exp_time }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<el-table class="mt-[15px]" :data="weappTableData.data" v-loading="weappTableData.loading" size="default">
|
<el-table class="mt-[15px]" :data="weappTableData.data" v-loading="weappTableData.loading" size="default">
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<span>{{ t('emptyData') }}</span>
|
<span>{{ t('emptyData') }}</span>
|
||||||
@ -75,6 +94,42 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<el-dialog v-model="cloudVersionDialogVisible" :title="t('codeDownTwoDesc')" width="600px" :before-close="handleCloseCloudVersion">
|
||||||
|
<el-form ref="cloudRuleFormRef" :model="form" :rules="formRules" label-width="120px">
|
||||||
|
<el-form-item prop="type" :label="t('版本号类型')">
|
||||||
|
<div>
|
||||||
|
<el-radio-group v-model="form.type">
|
||||||
|
<el-radio :label="1">{{ t('默认') }}</el-radio>
|
||||||
|
<el-radio :label="2">{{ t('自定义') }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<div class="mt-[10px] text-[12px] text-[#999] leading-[20px]">默认为列表版本号递增,自定义则为手动输入版本号进行上传,首位必须大于1</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="version" :label="t('code')" v-if="form.type == 2">
|
||||||
|
<div class="flex items-end">
|
||||||
|
<el-form-item prop="code1">
|
||||||
|
<el-input v-model.number="form.code1" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
||||||
|
</el-form-item>
|
||||||
|
<span class="mx-[10px]">.</span>
|
||||||
|
<el-form-item prop="code2">
|
||||||
|
<el-input v-model.number="form.code2" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
||||||
|
</el-form-item>
|
||||||
|
<span class="mx-[10px]">.</span>
|
||||||
|
<el-form-item prop="code3">
|
||||||
|
<el-input v-model.number="form.code3" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="handleCloseCloudVersion">{{ t('cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="save">
|
||||||
|
{{ t('confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog v-model="failReasonDialogVisible" :title="t('failReason')" width="60%">
|
<el-dialog v-model="failReasonDialogVisible" :title="t('failReason')" width="60%">
|
||||||
<el-scrollbar class="h-[60vh] w-full whitespace-pre-wrap p-[20px]">
|
<el-scrollbar class="h-[60vh] w-full whitespace-pre-wrap p-[20px]">
|
||||||
@ -116,19 +171,22 @@ const weappTableData:{
|
|||||||
limit: number,
|
limit: number,
|
||||||
total: number,
|
total: number,
|
||||||
loading: boolean,
|
loading: boolean,
|
||||||
data: AnyObject
|
data: AnyObject,
|
||||||
|
version_info: AnyObject
|
||||||
} = reactive({
|
} = reactive({
|
||||||
page: 1,
|
page: 1,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
data: []
|
data: [],
|
||||||
|
version_info: {}
|
||||||
})
|
})
|
||||||
const form = ref({
|
const form = ref({
|
||||||
desc: '',
|
type:1,
|
||||||
code: '',
|
version: '',
|
||||||
path: '',
|
code1: '1',
|
||||||
content: ''
|
code2: '0',
|
||||||
|
code3: '0'
|
||||||
})
|
})
|
||||||
const uploadSuccessShowDialog = ref(false)
|
const uploadSuccessShowDialog = ref(false)
|
||||||
const authCode = ref('')
|
const authCode = ref('')
|
||||||
@ -161,7 +219,62 @@ const handleClick = (val: any) => {
|
|||||||
router.push({ path: activeName.value })
|
router.push({ path: activeName.value })
|
||||||
}
|
}
|
||||||
const ruleFormRef = ref<any>(null)
|
const ruleFormRef = ref<any>(null)
|
||||||
|
const cloudRuleFormRef = ref<any>(null)
|
||||||
|
// 表单校验规则
|
||||||
|
const formRules = reactive({
|
||||||
|
code1: [
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: number, callback: any) => {
|
||||||
|
if (value < 1) {
|
||||||
|
callback(new Error(t('必须大于1')));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
code2: [
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: number, callback: any) => {
|
||||||
|
if (value < 0) {
|
||||||
|
callback(new Error(t('必须大于0')));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
code3: [
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: number, callback: any) => {
|
||||||
|
if (value < 0) {
|
||||||
|
callback(new Error(t('必须大于0')));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
version:[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: string, callback: any) => {
|
||||||
|
if(form.value.type == 2){
|
||||||
|
if(!form.value.code1 || !form.value.code2 || !form.value.code3){
|
||||||
|
callback(new Error(t('请填写版本号')));
|
||||||
|
}else{
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
/**
|
/**
|
||||||
* 获取版本列表
|
* 获取版本列表
|
||||||
*/
|
*/
|
||||||
@ -177,6 +290,7 @@ const getWeappVersionListFn = (page: number = 1) => {
|
|||||||
weappTableData.data = res.data.data
|
weappTableData.data = res.data.data
|
||||||
weappTableData.total = res.data.total
|
weappTableData.total = res.data.total
|
||||||
if (page == 1 && weappTableData.data.length && weappTableData.data[0].status == 0) getWeappUploadLogFn(weappTableData.data[0].task_key)
|
if (page == 1 && weappTableData.data.length && weappTableData.data[0].status == 0) getWeappUploadLogFn(weappTableData.data[0].task_key)
|
||||||
|
weappTableData.version_info = res.data.version_info
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
weappTableData.loading = false
|
weappTableData.loading = false
|
||||||
})
|
})
|
||||||
@ -184,10 +298,56 @@ const getWeappVersionListFn = (page: number = 1) => {
|
|||||||
|
|
||||||
getWeappVersionListFn()
|
getWeappVersionListFn()
|
||||||
|
|
||||||
|
const openDialog = () => {
|
||||||
|
if (!authCode.value) {
|
||||||
|
authElMessageBox()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!weappConfig.value.app_id) {
|
||||||
|
configElMessageBox()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
form.value = {
|
||||||
|
type:1,
|
||||||
|
version: '',
|
||||||
|
code1: '1',
|
||||||
|
code2: '0',
|
||||||
|
code3: '0'
|
||||||
|
}
|
||||||
|
cloudVersionDialogVisible.value = true
|
||||||
|
}
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
ruleFormRef.value.clearValidate()
|
ruleFormRef.value.clearValidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cloudVersionDialogVisible = ref(false)
|
||||||
|
const handleCloseCloudVersion = () => {
|
||||||
|
cloudVersionDialogVisible.value = false
|
||||||
|
form.value = {
|
||||||
|
type:1,
|
||||||
|
version: '',
|
||||||
|
code1: '1',
|
||||||
|
code2: '0',
|
||||||
|
code3: '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const save = () => {
|
||||||
|
cloudRuleFormRef.value.validate((valid: boolean) => {
|
||||||
|
if (valid) {
|
||||||
|
if (form.value.type == 2) {
|
||||||
|
form.value.version = `${form.value.code1}.${form.value.code2}.${form.value.code3}`
|
||||||
|
}
|
||||||
|
delete form.value.code1
|
||||||
|
delete form.value.code2
|
||||||
|
delete form.value.code3
|
||||||
|
delete form.value.type
|
||||||
|
cloudVersionDialogVisible.value = false
|
||||||
|
insert()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const uploading = ref(false)
|
const uploading = ref(false)
|
||||||
const insert = () => {
|
const insert = () => {
|
||||||
if (!authCode.value) {
|
if (!authCode.value) {
|
||||||
|
|||||||
@ -63,6 +63,20 @@
|
|||||||
<el-switch v-model="diyStore.global.bottomTabBar.isShow" />
|
<el-switch v-model="diyStore.global.bottomTabBar.isShow" />
|
||||||
<div class="text-sm text-gray-400">{{ t('tabbarSwitchTips') }}</div>
|
<div class="text-sm text-gray-400">{{ t('tabbarSwitchTips') }}</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('选择导航')">
|
||||||
|
<tabbar-select-popup v-model="diyStore.global.bottomTabBar.designNav" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="edit-attr-item-wrap" v-if="diyStore.global.copyright.control">
|
||||||
|
<h3 class="mb-[10px]">{{ t('版权信息内容') }}</h3>
|
||||||
|
<el-form label-width="80px" class="px-[10px]">
|
||||||
|
<el-form-item :label="t('版权信息')" class="display-block">
|
||||||
|
<el-switch v-model="diyStore.global.copyright.isShow" />
|
||||||
|
<div class="text-sm text-gray-400">{{ t('此处控制当前页面版权信息是否显示') }}</div>
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
<div class="edit-attr-item-wrap">
|
<div class="edit-attr-item-wrap">
|
||||||
@ -178,6 +192,7 @@ import { t } from '@/lang'
|
|||||||
import { watch, ref } from 'vue'
|
import { watch, ref } from 'vue'
|
||||||
import useDiyStore from '@/stores/modules/diy'
|
import useDiyStore from '@/stores/modules/diy'
|
||||||
import { img } from '@/utils/common'
|
import { img } from '@/utils/common'
|
||||||
|
import tabbarSelectPopup from './tabbar-select-popup.vue'
|
||||||
|
|
||||||
const diyStore = useDiyStore()
|
const diyStore = useDiyStore()
|
||||||
|
|
||||||
|
|||||||
211
admin/src/app/views/diy/components/tabbar-select-popup.vue
Normal file
211
admin/src/app/views/diy/components/tabbar-select-popup.vue
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div @click="show">
|
||||||
|
<slot>
|
||||||
|
<el-input v-model="selectData.title" :placeholder="t('请选择底部导航')" readonly class="link-input">
|
||||||
|
<template #suffix>
|
||||||
|
<div @click.stop="clear">
|
||||||
|
<el-icon v-if="selectData.key">
|
||||||
|
<Close />
|
||||||
|
</el-icon>
|
||||||
|
<el-icon v-else>
|
||||||
|
<ArrowRight />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<el-dialog v-model="showDialog" :title="t('底部导航选择')" width="850px" :destroy-on-close="true" :close-on-click-modal="false">
|
||||||
|
<el-table class="" :data="tableData.data" size="large" v-loading="tableData.loading" height="400px">
|
||||||
|
<template #empty>
|
||||||
|
<span>{{ !tableData.loading ? t('emptyData') : '' }}</span>
|
||||||
|
</template>
|
||||||
|
<el-table-column min-width="7%">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-checkbox v-model="row.checked" @change="handleCheckChange($event,row)" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="title" :label="t('title')" min-width="30%" >
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span>{{ row.info.title }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column prop="key" :label="t('key')" min-width="30%"/>
|
||||||
|
|
||||||
|
<el-table-column :label="t('type')" min-width="30%">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span>{{ row.info.type === 'app' ? t('app') : t('addon') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="mt-[16px] flex justify-end">
|
||||||
|
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.limit"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper" :total="tableData.total"
|
||||||
|
@size-change="loadBottomNavList()" @current-change="loadBottomNavList" />
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="save">{{ t('confirm') }}</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { t } from '@/lang'
|
||||||
|
import { ref, reactive, nextTick,computed } from 'vue'
|
||||||
|
import { FormInstance, ElMessage } from "element-plus";
|
||||||
|
import { getDiyBottomList } from '@/app/api/diy'
|
||||||
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
|
||||||
|
const prop = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
key: '',
|
||||||
|
title: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ignore: {
|
||||||
|
type: Array,
|
||||||
|
default: []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
selectData.value = {
|
||||||
|
key: '',
|
||||||
|
title: ''
|
||||||
|
}
|
||||||
|
setTimesSelected()
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue', 'confirm', 'success'])
|
||||||
|
|
||||||
|
const selectData: any = computed({
|
||||||
|
get() {
|
||||||
|
return prop.modelValue
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
emit('update:modelValue', value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const searchFormRef = ref<FormInstance>()
|
||||||
|
|
||||||
|
const timeListTableRef = ref()
|
||||||
|
const showDialog = ref(false)
|
||||||
|
const show = () => {
|
||||||
|
showDialog.value = true
|
||||||
|
loadBottomNavList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const tableData: any = reactive({
|
||||||
|
page: 1,
|
||||||
|
limit: 10,
|
||||||
|
total: 0,
|
||||||
|
loading: true,
|
||||||
|
data: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取自定义页面列表
|
||||||
|
const loadBottomNavList = (page: number = 1) => {
|
||||||
|
tableData.loading = true
|
||||||
|
tableData.page = page
|
||||||
|
|
||||||
|
getDiyBottomList({}).then(res => {
|
||||||
|
tableData.loading = false
|
||||||
|
|
||||||
|
const len = Math.ceil(res.data.length / tableData.limit)
|
||||||
|
const data = cloneDeep(res.data)
|
||||||
|
const dataGather = []
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
dataGather[i] = data.splice(0, tableData.limit)
|
||||||
|
}
|
||||||
|
tableData.data = dataGather[tableData.page - 1]
|
||||||
|
tableData.data.forEach((item: any) => {
|
||||||
|
item.checked = item.key == selectData.value.key
|
||||||
|
})
|
||||||
|
tableData.total = res.data.length
|
||||||
|
setTimesSelected();
|
||||||
|
}).catch(() => {
|
||||||
|
tableData.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
loadBottomNavList()
|
||||||
|
const handleCheckChange = (isSelect: any, row: any) => {
|
||||||
|
if (isSelect) {
|
||||||
|
selectData.value = {
|
||||||
|
key: row.key,
|
||||||
|
title: row.info.title
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
selectData.value = {
|
||||||
|
key: '',
|
||||||
|
title: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
setTimesSelected()
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 表格设置选中状态
|
||||||
|
const setTimesSelected = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
for (let i = 0; i < tableData.data.length; i++) {
|
||||||
|
tableData.data[i].checked = false
|
||||||
|
if (selectData.value.key == tableData.data[i].key) {
|
||||||
|
tableData.data[i].checked = true
|
||||||
|
selectData.value.key = tableData.data[i].key
|
||||||
|
selectData.value.title = tableData.data[i].info.title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetForm = (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return
|
||||||
|
formEl.resetFields()
|
||||||
|
|
||||||
|
loadBottomNavList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const save = () => {
|
||||||
|
if (selectData.value.key == '') {
|
||||||
|
ElMessage({
|
||||||
|
type: 'warning',
|
||||||
|
message: `${ t('请选择底部导航') }`
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selectData.value = {
|
||||||
|
key: selectData.value.key,
|
||||||
|
title: selectData.value.title
|
||||||
|
}
|
||||||
|
showDialog.value = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show,
|
||||||
|
showDialog,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.form-item-wrap {
|
||||||
|
margin-right: 10px !important;
|
||||||
|
margin-bottom: 10px !important;
|
||||||
|
|
||||||
|
&.last-child {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center justify-center">
|
<div class="flex items-center justify-center">
|
||||||
<el-card class="box-card !border-none profile-data w-[1280px] mt-[20px] loading-box" shadow="never" v-loading="loading" >
|
<el-card class="box-card !border-none profile-data w-[1280px] mt-[20px] loading-box" shadow="never">
|
||||||
<!-- <div> -->
|
<!-- <div> -->
|
||||||
<div class="box-border">
|
<div class="box-border">
|
||||||
<div class="bg-[#fff] mb-[20px] rounded-[6px] relative banner-box" v-if="showBanner" @mouseenter="hovering = 'banner'" @mouseleave="hovering = ''">
|
<div class="bg-[#fff] mb-[20px] rounded-[6px] relative banner-box" v-if="showBanner" @mouseenter="hovering = 'banner'" @mouseleave="hovering = ''">
|
||||||
@ -11,7 +11,21 @@
|
|||||||
</span>
|
</span>
|
||||||
<div class="flex h-[156px]">
|
<div class="flex h-[156px]">
|
||||||
<div class="w-full h-full ">
|
<div class="w-full h-full ">
|
||||||
<el-carousel :interval="3000" height="156px" class="rounded-[6px]">
|
<!-- 轮播图加载中 -->
|
||||||
|
<div v-if="loading" class="skeleton-loading h-full flex items-center justify-center">
|
||||||
|
<el-skeleton
|
||||||
|
style="width: 100%"
|
||||||
|
:loading="loading"
|
||||||
|
animated
|
||||||
|
:throttle="{ leading: 500, initVal: true }"
|
||||||
|
>
|
||||||
|
<template #template>
|
||||||
|
<el-skeleton-item variant="image" style="width: 100%; height: 156px;" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</el-skeleton>
|
||||||
|
</div>
|
||||||
|
<el-carousel v-else :interval="3000" height="156px" class="rounded-[6px]">
|
||||||
<!-- <el-carousel-item >
|
<!-- <el-carousel-item >
|
||||||
<div class="h-full index-carousel" @click="toApplication">
|
<div class="h-full index-carousel" @click="toApplication">
|
||||||
<img :src="img('static/resource/images/banner_1.png')" alt="" class="w-full h-full cursor-pointer">
|
<img :src="img('static/resource/images/banner_1.png')" alt="" class="w-full h-full cursor-pointer">
|
||||||
@ -99,22 +113,55 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<template v-if="loading">
|
||||||
<div v-if="showNiuCloud && appList.length > 0" class="mt-[50px] relative" @mouseenter="hovering = 'niuCloud'" @mouseleave="hovering = ''">
|
<div v-if="showNiuCloud" class="mt-[50px] relative" @mouseenter="hovering = 'niuCloud'" @mouseleave="hovering = ''">
|
||||||
<span class="absolute right-0 top-[-5px] text-[#999] hover:text-red-500 cursor-pointer z-10" v-if="hovering === 'niuCloud'">
|
<span class="absolute right-0 top-[-5px] text-[#999] hover:text-red-500 cursor-pointer z-10" v-if="hovering === 'niuCloud'">
|
||||||
<el-icon class="icon" :size="20" color="#7b7b7b" @click="closeModule('niuCloud')">
|
<el-icon class="icon" :size="20" color="#7b7b7b" @click="closeModule('niuCloud')">
|
||||||
<CircleCloseFilled />
|
<CircleCloseFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</span>
|
</span>
|
||||||
<p class="text-[18px] text-[#1D1F3A]">NIUCLOUD生态精选应用推荐</p>
|
<p class="text-[18px] text-[#1D1F3A]">NIUCLOUD生态精选应用推荐</p>
|
||||||
<!-- <div class="flex justify-between mt-[20px]">
|
<!-- 应用列表加载中 -->
|
||||||
<div class="flex">
|
<div v-if="loading" class="mt-[20px] grid grid-cols-5 gap-4">
|
||||||
<div :class="['flex items-center text-[14px] h-[32px] rounded-full px-[20px] mr-[24px] text-[#fff] bg-[#AFB1C8] hover:bg-[#7B7E9A] cursor-pointer', { '!text-[#fff] !bg-[#7B7E9A]': activeName === 'installed' }]" @click="activeNameTabFn('installed')">{{ t("全部") }}</div>
|
<div v-for="i in 5" :key="i" class="bg-[#EDEEF4] rounded-[8px] overflow-hidden">
|
||||||
<div :class="['flex items-center text-[14px] h-[32px] rounded-full px-[20px] mr-[24px] text-[#fff] bg-[#AFB1C8] hover:bg-[#7B7E9A] cursor-pointer', { '!text-[#fff] !bg-[#7B7E9A]': activeName === 'uninstalled' }]" @click="activeNameTabFn('uninstalled')">{{ t("商城") }}</div>
|
<el-skeleton
|
||||||
<div :class="['flex items-center text-[14px] h-[32px] rounded-full px-[20px] mr-[24px] text-[#fff] bg-[#AFB1C8] hover:bg-[#7B7E9A] cursor-pointer', { '!text-[#fff] !bg-[#7B7E9A]': activeName === 'all' }]" @click="activeNameTabFn('all')">{{ t("数字人") }}</div>
|
style="width: 240px"
|
||||||
<div :class="['flex items-center text-[14px] h-[32px] rounded-full px-[20px] mr-[24px] text-[#fff] bg-[#AFB1C8] hover:bg-[#7B7E9A] cursor-pointer', { '!text-[#fff] !bg-[#7B7E9A]': activeName === 'all1' }]" @click="activeNameTabFn('all1')">{{ t("拼团") }}</div>
|
:loading="loading"
|
||||||
|
animated
|
||||||
|
:throttle="{ leading: 500, initVal: true }"
|
||||||
|
>
|
||||||
|
<template #template>
|
||||||
|
<el-skeleton-item variant="image" style="width: 240px; height: 265px" />
|
||||||
|
<div style="padding: 14px">
|
||||||
|
<el-skeleton-item variant="h3" style="width: 50%" />
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: space-between;
|
||||||
|
margin-top: 16px;
|
||||||
|
height: 16px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<el-skeleton-item variant="text" style="margin-right: 16px" />
|
||||||
|
<el-skeleton-item variant="text" style="width: 30%" />
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</el-skeleton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div v-if="showNiuCloud && appList.length >0" class="mt-[50px] relative" @mouseenter="hovering = 'niuCloud'" @mouseleave="hovering = ''">
|
||||||
|
<span class="absolute right-0 top-[-5px] text-[#999] hover:text-red-500 cursor-pointer z-10" v-if="hovering === 'niuCloud'">
|
||||||
|
<el-icon class="icon" :size="20" color="#7b7b7b" @click="closeModule('niuCloud')">
|
||||||
|
<CircleCloseFilled />
|
||||||
|
</el-icon>
|
||||||
|
</span>
|
||||||
|
<p class="text-[18px] text-[#1D1F3A]">NIUCLOUD生态精选应用推荐</p>
|
||||||
<div class="mt-[20px]">
|
<div class="mt-[20px]">
|
||||||
<div class="grid grid-cols-5 gap-4">
|
<div class="grid grid-cols-5 gap-4">
|
||||||
<div v-for="(item,index) in appList.slice(0,5)" :key="index" @click="toApplicationDetail(item)" class="bg-[#EDEEF4] rounded-[8px] overflow-hidden text-[#666] cursor-pointer hover:shadow-xl transition-shadow duration-300 border-[1px] border-[#EDEEF4]">
|
<div v-for="(item,index) in appList.slice(0,5)" :key="index" @click="toApplicationDetail(item)" class="bg-[#EDEEF4] rounded-[8px] overflow-hidden text-[#666] cursor-pointer hover:shadow-xl transition-shadow duration-300 border-[1px] border-[#EDEEF4]">
|
||||||
@ -148,37 +195,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<div class="text-[18px] mt-[50px] mb-[15px]">{{ t("dataSummarize") }}</div>
|
<div class="text-[18px] mt-[50px] mb-[15px]">{{ t("dataSummarize") }}</div>
|
||||||
<el-card class="box-card !border-none profile-data" shadow="never">
|
<el-card class="box-card !border-none profile-data" shadow="never">
|
||||||
<el-row :gutter="20" class="top">
|
<el-row :gutter="20" class="top">
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-card shadow="never" @click="toHref('site/manage','1')" class="cursor-pointer min-w-[180px] first-con">
|
<el-card shadow="never" @click="toHref('site/manage','1')" class="cursor-pointer min-w-[180px] first-con">
|
||||||
<div class="text-[20px] font-bold">{{ statInfo.today_data.norma_site_count }}</div>
|
<div class="text-[20px] font-bold">{{ statInfo.today_data.norma_site_count || 0 }}</div>
|
||||||
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("normalSiteSum") }}</div>
|
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("normalSiteSum") }}</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-card shadow="never" @click="toHref('site/manage','1')" class="cursor-pointer min-w-[180px] first-con">
|
<el-card shadow="never" @click="toHref('site/manage','1')" class="cursor-pointer min-w-[180px] first-con">
|
||||||
<div class="text-[20px] font-bold">{{ statInfo.today_data.week_expire_site_count }}</div>
|
<div class="text-[20px] font-bold">{{ statInfo.today_data.week_expire_site_count|| 0 }}</div>
|
||||||
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("weekExpireSiteCount") }}</div>
|
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("weekExpireSiteCount") }}</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-card shadow="never" @click="toHref('site/manage','2')" class="cursor-pointer min-w-[180px] first-con">
|
<el-card shadow="never" @click="toHref('site/manage','2')" class="cursor-pointer min-w-[180px] first-con">
|
||||||
<div class="text-[20px] font-bold">{{ statInfo.today_data.expire_site_count }}</div>
|
<div class="text-[20px] font-bold">{{ statInfo.today_data.expire_site_count|| 0 }}</div>
|
||||||
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("expireSiteSum") }}</div>
|
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("expireSiteSum") }}</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-card shadow="never" @click="toHref('/app_manage/app_store','uninstalled')" class="cursor-pointer min-w-[180px] first-con">
|
<el-card shadow="never" @click="toHref('/app_manage/app_store','uninstalled')" class="cursor-pointer min-w-[180px] first-con">
|
||||||
<div class="text-[20px] font-bold">{{ statInfo.app.app_no_installed_count }}</div>
|
<div class="text-[20px] font-bold">{{ statInfo.app.app_no_installed_count|| 0 }}</div>
|
||||||
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("noInstallAppSun") }}</div>
|
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("noInstallAppSun") }}</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-card shadow="never" @click="toHref('/app_manage/app_store','installed')" class="cursor-pointer min-w-[180px] first-con">
|
<el-card shadow="never" @click="toHref('/app_manage/app_store','installed')" class="cursor-pointer min-w-[180px] first-con">
|
||||||
<div class="text-[20px] font-bold">{{ statInfo.app.app_installed_count }}</div>
|
<div class="text-[20px] font-bold">{{ statInfo.app.app_installed_count|| 0 }}</div>
|
||||||
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("installAppSun") }}</div>
|
<div class="text-[14px] mb-[9px] text-[#4F516D]">{{ t("installAppSun") }}</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|||||||
@ -76,9 +76,7 @@ const formRules = computed(() => {
|
|||||||
const setFormData = async () => {
|
const setFormData = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const service_data = await (await getMap()).data
|
const service_data = await (await getMap()).data
|
||||||
formData.key = service_data.key
|
Object.assign(formData, service_data)
|
||||||
formData.is_open = service_data.is_open
|
|
||||||
formData.valid_time = service_data.valid_time
|
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
setFormData()
|
setFormData()
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter , useRoute} from 'vue-router'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { img } from '@/utils/common'
|
import { img } from '@/utils/common'
|
||||||
import menuItem from './menu-item.vue'
|
import menuItem from './menu-item.vue'
|
||||||
@ -32,6 +32,8 @@ import useUserStore from '@/stores/modules/user'
|
|||||||
import storage from '@/utils/storage'
|
import storage from '@/utils/storage'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
routes: {
|
routes: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -70,8 +72,13 @@ const handleJump = (routeName: string) => {
|
|||||||
if (specialMenuNamesLevel1.includes(routeName)) {
|
if (specialMenuNamesLevel1.includes(routeName)) {
|
||||||
routeName = 'addon_list'
|
routeName = 'addon_list'
|
||||||
}
|
}
|
||||||
|
// 跳转时添加随机查询参数(用于触发页面感知)
|
||||||
|
const query = route.name === routeName
|
||||||
|
? { refresh: Date.now() } // 相同路由时添加随机参数
|
||||||
|
: {};
|
||||||
|
|
||||||
// 执行跳转
|
// 执行跳转
|
||||||
router.push({ name: routeName })
|
router.push({ name: routeName, query });
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -190,9 +190,13 @@ const handleJump = (routeName: string) => {
|
|||||||
if (specialMenuNamesLevel1.value.includes(routeName)) {
|
if (specialMenuNamesLevel1.value.includes(routeName)) {
|
||||||
routeName = 'addon_list'
|
routeName = 'addon_list'
|
||||||
}
|
}
|
||||||
|
// 跳转时添加随机查询参数(用于触发页面感知)
|
||||||
|
const query = route.name === routeName
|
||||||
|
? { refresh: Date.now() } // 相同路由时添加随机参数
|
||||||
|
: {};
|
||||||
|
|
||||||
// 执行跳转
|
// 执行跳转
|
||||||
router.push({ name: routeName })
|
router.push({ name: routeName, query });
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(route, () => {
|
watch(route, () => {
|
||||||
|
|||||||
@ -43,7 +43,7 @@ const addonIndexRoute = userStore.addonIndexRoute
|
|||||||
const menuData = ref<Record<string, any>[]>([])
|
const menuData = ref<Record<string, any>[]>([])
|
||||||
const addonRouters: Record<string, any> = {}
|
const addonRouters: Record<string, any> = {}
|
||||||
const logoUrl = computed(() => {
|
const logoUrl = computed(() => {
|
||||||
return userStore.siteInfo.icon ? userStore.siteInfo.icon : systemStore.website.icon
|
return userStore.siteInfo.logo ? userStore.siteInfo.logo : systemStore.website.logo
|
||||||
})
|
})
|
||||||
|
|
||||||
const appList = ref<Record<string, any>[]>([])
|
const appList = ref<Record<string, any>[]>([])
|
||||||
|
|||||||
@ -183,9 +183,13 @@ const handleJump = (routeName: string) => {
|
|||||||
if (specialMenuNamesLevel1.value.includes(routeName)) {
|
if (specialMenuNamesLevel1.value.includes(routeName)) {
|
||||||
routeName = 'addon_list'
|
routeName = 'addon_list'
|
||||||
}
|
}
|
||||||
|
// 跳转时添加随机查询参数(用于触发页面感知)
|
||||||
|
const query = route.name === routeName
|
||||||
|
? { refresh: Date.now() } // 相同路由时添加随机参数
|
||||||
|
: {};
|
||||||
|
|
||||||
// 执行跳转
|
// 执行跳转
|
||||||
router.push({ name: routeName })
|
router.push({ name: routeName, query });
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(route, () => {
|
watch(route, () => {
|
||||||
|
|||||||
@ -44,7 +44,7 @@ const addonIndexRoute = userStore.addonIndexRoute
|
|||||||
const menuData = ref<Record<string, any>[]>([])
|
const menuData = ref<Record<string, any>[]>([])
|
||||||
const addonRouters: Record<string, any> = {}
|
const addonRouters: Record<string, any> = {}
|
||||||
const logoUrl = computed(() => {
|
const logoUrl = computed(() => {
|
||||||
return userStore.siteInfo.icon ? userStore.siteInfo.icon : systemStore.website.icon
|
return userStore.siteInfo.logo ? userStore.siteInfo.logo : systemStore.website.logo
|
||||||
})
|
})
|
||||||
|
|
||||||
const appList = ref<Record<string, any>[]>([])
|
const appList = ref<Record<string, any>[]>([])
|
||||||
|
|||||||
@ -24,13 +24,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter ,useRoute } from 'vue-router'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import menuItem from './menu-item.vue'
|
import menuItem from './menu-item.vue'
|
||||||
import useUserStore from '@/stores/modules/user'
|
import useUserStore from '@/stores/modules/user'
|
||||||
import storage from '@/utils/storage'
|
import storage from '@/utils/storage'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
routes: {
|
routes: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -69,8 +70,13 @@ const handleJump = (routeName: string) => {
|
|||||||
if (specialMenuNamesLevel1.includes(routeName)) {
|
if (specialMenuNamesLevel1.includes(routeName)) {
|
||||||
routeName = 'addon_list'
|
routeName = 'addon_list'
|
||||||
}
|
}
|
||||||
|
// 跳转时添加随机查询参数(用于触发页面感知)
|
||||||
|
const query = route.name === routeName
|
||||||
|
? { refresh: Date.now() } // 相同路由时添加随机参数
|
||||||
|
: {};
|
||||||
|
|
||||||
// 执行跳转
|
// 执行跳转
|
||||||
router.push({ name: routeName })
|
router.push({ name: routeName, query });
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -77,8 +77,17 @@ const useDiyStore = defineStore('diy', {
|
|||||||
bottomTabBar: {
|
bottomTabBar: {
|
||||||
control: true, // 是否允许展示编辑
|
control: true, // 是否允许展示编辑
|
||||||
isShow: true, // 是否显示
|
isShow: true, // 是否显示
|
||||||
|
designNav:{ //类型
|
||||||
|
title: "", // 标题
|
||||||
|
key: "", // 组件标识
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 版权信息
|
||||||
|
copyright: {
|
||||||
|
control: true, // 是否允许展示编辑
|
||||||
|
isShow: false, // 是否显示
|
||||||
|
},
|
||||||
// 弹框 count:不弹出 -1,首次弹出 1,每次弹出 0
|
// 弹框 count:不弹出 -1,首次弹出 1,每次弹出 0
|
||||||
popWindow: {
|
popWindow: {
|
||||||
imgUrl: "",
|
imgUrl: "",
|
||||||
@ -171,6 +180,16 @@ const useDiyStore = defineStore('diy', {
|
|||||||
bottomTabBar: {
|
bottomTabBar: {
|
||||||
control: true, // 是否允许展示编辑
|
control: true, // 是否允许展示编辑
|
||||||
isShow: true, // 是否显示
|
isShow: true, // 是否显示
|
||||||
|
designNav:{ //类型
|
||||||
|
title: "", // 标题
|
||||||
|
key: "", // 组件标识
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 版权信息
|
||||||
|
copyright: {
|
||||||
|
control: true, // 是否允许展示编辑
|
||||||
|
isShow: true, // 是否显示
|
||||||
},
|
},
|
||||||
|
|
||||||
// 弹框 count:不弹出 -1,首次弹出 1,每次弹出 0
|
// 弹框 count:不弹出 -1,首次弹出 1,每次弹出 0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user