mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2026-02-01 23:18:10 +00:00
同步admin
This commit is contained in:
parent
7581ceb5a9
commit
5a2da25c9c
19
admin/package-lock.json
generated
19
admin/package-lock.json
generated
@ -47,6 +47,7 @@
|
||||
"@typescript-eslint/eslint-plugin": "5.53.0",
|
||||
"@vitejs/plugin-vue": "4.0.0",
|
||||
"autoprefixer": "10.4.13",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "8.34.0",
|
||||
"eslint-config-standard-with-typescript": "34.0.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
@ -2616,6 +2617,24 @@
|
||||
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/cross-env/-/cross-env-7.0.3.tgz",
|
||||
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"cross-env": "src/bin/cross-env.js",
|
||||
"cross-env-shell": "src/bin/cross-env-shell.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.14",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build && node publish.cjs",
|
||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 && vite build && node publish.cjs",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -60,6 +60,7 @@
|
||||
"unplugin-auto-import": "0.13.0",
|
||||
"unplugin-vue-components": "0.23.0",
|
||||
"vite": "4.1.0",
|
||||
"vue-tsc": "1.0.24"
|
||||
"vue-tsc": "1.0.24",
|
||||
"cross-env": "^7.0.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,6 +60,13 @@ export function getWeappLastCommitRecord() {
|
||||
return request.get('wxoplatform/weapp/commit/last')
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除版本
|
||||
*/
|
||||
export function delVersion(id: number) {
|
||||
return request.delete(`wxoplatform/weapp/version/${id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序代码提交
|
||||
* @returns
|
||||
|
||||
@ -34,37 +34,14 @@
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<div v-if="step == 2">
|
||||
<el-steps :active="numberOfSteps" align-center class="number-of-steps" process-status="process" v-if="!errorDialog && active != 'complete'">
|
||||
<div v-show="step == 2">
|
||||
<el-steps :active="numberOfSteps" align-center class="number-of-steps" process-status="process">
|
||||
<el-step :title="t('testDirectoryPermissions')" />
|
||||
<el-step :title="t('upgrade.option')" />
|
||||
<el-step :title="t('startUpgrade')" />
|
||||
<el-step :title="t('upgradeEnd')" />
|
||||
</el-steps>
|
||||
<div class="h-[400px]" style="overflow: auto">
|
||||
<!-- <div class="time-dialog-wrap mt-[30px]" v-show="active == 'content'">-->
|
||||
<!-- <el-timeline style="width: 100%">-->
|
||||
<!-- <el-timeline-item v-for="(item, index) in upgradeContent.version_list" :key="index" placement="left">-->
|
||||
<!-- <div class="relative">-->
|
||||
<!-- <span class="text-[#333333] text-[16px] absolute">{{ timeSplit(item.release_time)[0] }}</span>-->
|
||||
<!-- <br />-->
|
||||
<!-- <span class="text-[#999999] text-[14px] w-[78px] block mt-[10px] absolute" style="text-align: right"> {{ timeSplit(item.release_time)[1] }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- <el-collapse v-model="activeName" accordion>-->
|
||||
<!-- <el-collapse-item :name="index">-->
|
||||
<!-- <template #title>-->
|
||||
<!-- <span class="text-[#333] text-[16px]"> v{{ item.version_no }} </span>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<!-- <div class="px-[20px] py-[20px] bg-overlay timeline-log-wrap whitespace-pre-wrap rounded-[4px]" style="background: rgba(25, 103, 249, 0.03);" v-if="item['upgrade_log']">-->
|
||||
<!-- <div v-html="item['upgrade_log']"></div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-collapse-item>-->
|
||||
<!-- </el-collapse>-->
|
||||
<!-- </el-timeline-item>-->
|
||||
<!-- </el-timeline>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- 判断文件权限 -->
|
||||
<div v-show="active == 'upgrade'">
|
||||
<div class="flex flex-col" v-if="upgradeCheck && !upgradeTask">
|
||||
@ -132,7 +109,6 @@
|
||||
<div class="h-[370px] mt-[30px]" v-show="showTerminal && upgradeTask && !errorDialog">
|
||||
<terminal ref="terminalRef" :name="`upgrade-${terminalId}`" :context="upgradeTask ? upgradeTask.upgrade.app_key : ''" :init-log="null" :show-header="false" :show-log-time="true" @exec-cmd="onExecCmd" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- 是否备份选择 -->
|
||||
<div class="flex flex-col" v-show="active == 'backup'">
|
||||
@ -156,36 +132,63 @@
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="mt-[20px] h-[370px]" v-show="errorDialog">
|
||||
<el-result icon="error" :title="t('升级失败')">
|
||||
<template #icon>
|
||||
<img src="@/app/assets/images/error_icon.png" alt="" />
|
||||
</template>
|
||||
<template #extra>
|
||||
<el-scrollbar class="max-h-[120px] !overflow-auto text-[15px] text-[#4F516D] mb-[15px] mt-[-15px]">
|
||||
{{errorMsg}}
|
||||
</el-scrollbar>
|
||||
<el-button @click="handleBack()" class="!w-[90px]">错误信息</el-button>
|
||||
<el-button @click="showDialog=false" type="primary" class="!w-[90px]">完成</el-button>
|
||||
</template>
|
||||
</el-result>
|
||||
</div>
|
||||
<div class="mt-[20px]" v-show="active == 'complete'">
|
||||
<el-result icon="success" :title="t('upgrade.upgradeSuccess')">
|
||||
<template #icon>
|
||||
<img src="@/app/assets/images/success_icon.png" alt="">
|
||||
</template>
|
||||
<template #extra>
|
||||
<div class="text-[16px] text-[#4F516D] mt-[-5px]" v-show="upgradeTask && upgradeTask.executed && !upgradeTask.executed.includes('cloudBuild')">{{ t('upgrade.upgradeCompleteTips') }}</div>
|
||||
<div class="text-[16px] text-[#9699B6] mt-[10px]">本次升级用时{{ formatUpgradeDuration }}</div>
|
||||
<div class="mt-[20px]">
|
||||
<el-button @click="handleBack()" class="!w-[90px]">返回</el-button>
|
||||
<el-button @click="showDialog=false" type="primary" class="!w-[90px]">完成</el-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="step == 3">
|
||||
<div class="mt-[10px]" v-show="active == 'complete'">
|
||||
<el-result icon="success" :title="t('upgrade.upgradeSuccess')">
|
||||
<template #icon>
|
||||
<img src="@/app/assets/images/success_icon.png" alt="">
|
||||
</template>
|
||||
<template #extra>
|
||||
<div class="text-[16px] text-[#4F516D] mt-[-5px]" v-show="upgradeTask && upgradeTask.executed && !upgradeTask.executed.includes('cloudBuild')">{{ t('upgrade.upgradeCompleteTips') }}</div>
|
||||
<!-- <div class="text-[16px] text-[#9699B6] mt-[10px]">本次升级用时{{ formatUpgradeDuration }}</div> -->
|
||||
<div class="w-[750px]" v-if="upgradeTask.cloud_build_error">
|
||||
<el-alert class="!w-[750px] border-warning !border-[1px] !rounded-[0px] border-solid" type="warning" :closable="false">
|
||||
<template #title>
|
||||
<span class="text-error">警告:</span>
|
||||
<span class="text-black">升级过程中发生云编译错误</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
<div class="text-left mt-[10px] leading-8">
|
||||
<div class="font-bold">为了保证系统稳定,建议您做以下处理:</div>
|
||||
<div><span class="w-[6px] h-[6px] rounded-[6px] bg-black inline-block mr-[10px]"></span>如果您是开发者,安装的框架或者插件二开过或者正在开发中,可能是因为您的本地代码不完整导致的云编译失败,需要自己调试并重新进行编译才算升级完成(云编译会把本地插件前端代码上传编译)。</div>
|
||||
<div><span class="w-[6px] h-[6px] rounded-[6px] bg-black inline-block mr-[10px]"></span>如果您没有二开过任何代码,可能是本地插件存在兼容性问题,请联系插件开发者或者官方客服解决。</div>
|
||||
<div><span class="w-[6px] h-[6px] rounded-[6px] bg-black inline-block mr-[10px]"></span>如果您的项目已经投入正式运营中,请立即回滚。</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-result>
|
||||
<!-- <el-alert :title="t('upgrade.upgradeCompleteTips')" type="error" :closable="false" v-show="upgradeTask && upgradeTask.executed && !upgradeTask.executed.includes('cloudBuild')"/> -->
|
||||
</div>
|
||||
<div class="text-left mt-[10px]">
|
||||
<div class="font-bold">编译信息错误</div>
|
||||
<div class="mt-[10px] text-secondary overflow-hidden line-clamp-4">
|
||||
{{ upgradeTask.cloud_build_error }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[20px]">
|
||||
<el-button @click="handleBack()" class="!w-[90px]">更多信息</el-button>
|
||||
<el-button @click="showDialog=false" type="primary" plain class="!w-[90px]">我已知晓</el-button>
|
||||
<el-button @click="cloudBuildError('cloud_build_error_rollback')" type="primary" class="!w-[90px]">回滚</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[20px]" v-else>
|
||||
<el-button @click="handleBack()" class="!w-[90px]">返回</el-button>
|
||||
<el-button @click="showDialog=false" type="primary" class="!w-[90px]">完成</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-result>
|
||||
</div>
|
||||
<div class="mt-[20px] h-[370px]" v-show="active == 'fail'">
|
||||
<el-result icon="error" :title="t('升级失败')">
|
||||
<template #icon>
|
||||
<img src="@/app/assets/images/error_icon.png" alt="" />
|
||||
</template>
|
||||
<template #extra>
|
||||
<el-scrollbar class="max-h-[120px] !overflow-auto text-[15px] text-[#4F516D] mb-[15px] mt-[-15px]">
|
||||
{{errorMsg}}
|
||||
</el-scrollbar>
|
||||
<el-button @click="handleBack()" class="!w-[90px]">错误信息</el-button>
|
||||
<el-button @click="showDialog=false" type="primary" class="!w-[90px]">完成</el-button>
|
||||
</template>
|
||||
</el-result>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -354,8 +357,6 @@ const getUpgradeTaskFn = () => {
|
||||
errorMsg.value = item
|
||||
}
|
||||
})
|
||||
errorDialog.value = true
|
||||
showTerminal.value = false
|
||||
if (upgradeTimer) {
|
||||
clearInterval(upgradeTimer)
|
||||
upgradeTimer = null
|
||||
@ -365,12 +366,17 @@ const getUpgradeTaskFn = () => {
|
||||
// 恢复完毕
|
||||
if (data.step == 'restoreComplete') {
|
||||
flashInterval && clearInterval(flashInterval)
|
||||
step.value = 3
|
||||
active.value = 'fail'
|
||||
return
|
||||
}
|
||||
// 升级完成
|
||||
if (data.step == 'upgradeComplete') {
|
||||
if (data.cloud_build_error) {
|
||||
terminalRef.value.pushMessage({ content: data.cloud_build_error, class: 'error' })
|
||||
}
|
||||
step.value = 3
|
||||
active.value = 'complete'
|
||||
showTerminal.value = false
|
||||
numberOfSteps.value = 4
|
||||
notificationEl && notificationEl.close()
|
||||
emits('complete')
|
||||
@ -379,12 +385,13 @@ const getUpgradeTaskFn = () => {
|
||||
upgradeTimer = null
|
||||
}
|
||||
timeloading.value = false
|
||||
clearUpgradeTask()
|
||||
return
|
||||
}
|
||||
numberOfSteps.value = 2
|
||||
active.value = 'upgrade'
|
||||
executeUpgradeFn()
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
|
||||
@ -395,6 +402,7 @@ const handleBack = () => {
|
||||
isBack.value = true
|
||||
showTerminal.value = true
|
||||
errorDialog.value = false // 隐藏错误弹窗
|
||||
step.value = 2
|
||||
}
|
||||
|
||||
const formatUpgradeDuration = computed(() => {
|
||||
@ -646,6 +654,12 @@ const cloudBuildError = (event: string) => {
|
||||
getUpgradeTaskFn()
|
||||
})
|
||||
break
|
||||
case 'cloud_build_error_rollback':
|
||||
upgradeUserOperate(event).then(() => {
|
||||
handleBack()
|
||||
executeUpgradeFn()
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -45,5 +45,6 @@
|
||||
"againUpload": "重新上传",
|
||||
"uploadWeapp": "上传小程序",
|
||||
"undoAudit" : "撤回审核",
|
||||
"undoAuditTips" : "撤回代码审核,单个账号每天审核撤回次数最多不超过 5 次(每天的额度从0点开始生效),一个月不超过 10 次。是否要继续撤回?"
|
||||
"undoAuditTips" : "撤回代码审核,单个账号每天审核撤回次数最多不超过 5 次(每天的额度从0点开始生效),一个月不超过 10 次。是否要继续撤回?",
|
||||
"helpInfo": "查看帮助"
|
||||
}
|
||||
|
||||
@ -32,5 +32,5 @@
|
||||
"safeModeTips": "安全模式下,消息包为纯密文,需要开发者加密和解密,安全系数高",
|
||||
"wechatBaseUri": "借权域名",
|
||||
"wechatBaseUriPlaceholder": "",
|
||||
"wechatBaseUriTips": "默认留空,填写后将替换https://open.weixin.gg.com/获取授权!"
|
||||
"wechatBaseUriTips": "默认留空,填写后将替换https://open.weixin.qq.com/获取授权!"
|
||||
}
|
||||
|
||||
@ -243,7 +243,7 @@
|
||||
"carouselSearchSwiperSet": "轮播图设置",
|
||||
"carouselSearchSwiperControl": "展示开关",
|
||||
"carouselSearchSwiperInterval": "切换间隔 / 秒",
|
||||
"carouselSearchSwiperTips": "建议上传尺寸相同的图片,推荐尺寸750*350;鼠标拖拽可调整图片顺序",
|
||||
"carouselSearchSwiperTips": "建议上传尺寸相同的图片,推荐尺寸750*580;鼠标拖拽可调整图片顺序",
|
||||
"carouselSearchTabStyle": "选项卡样式",
|
||||
"carouselSearchStyle": "搜索框样式",
|
||||
"noColor": "常规颜色",
|
||||
|
||||
@ -244,7 +244,7 @@
|
||||
"carouselSearchSwiperSet": "轮播图设置",
|
||||
"carouselSearchSwiperControl": "展示开关",
|
||||
"carouselSearchSwiperInterval": "切换间隔 / 秒",
|
||||
"carouselSearchSwiperTips": "建议上传尺寸相同的图片,推荐尺寸750*350;鼠标拖拽可调整图片顺序",
|
||||
"carouselSearchSwiperTips": "建议上传尺寸相同的图片,推荐尺寸750*580;鼠标拖拽可调整图片顺序",
|
||||
"carouselSearchTabStyle": "选项卡样式",
|
||||
"carouselSearchStyle": "搜索框样式",
|
||||
"noColor": "常规颜色",
|
||||
|
||||
@ -4,5 +4,9 @@
|
||||
"admin": "平台端",
|
||||
"adminBgImgTip": "建议上传尺寸为450*400px",
|
||||
"site": "站点端",
|
||||
"siteBgImgTip": "建议上传尺寸为620*980px"
|
||||
"siteBgImgTip": "建议上传尺寸为620*980px",
|
||||
"siteLoginLogo": "站点登录Logo",
|
||||
"siteLoginLogoTips": "站点端登录Logo,建议图片尺寸:132*40像素;图片格式:jpg、png、jpeg。",
|
||||
"siteLoginBgImg": "站点登录背景图",
|
||||
"siteLoginBgImgTips": "站点端登录背景图,建议图片尺寸:1920*1280像素;图片格式:jpg、png、jpeg。"
|
||||
}
|
||||
|
||||
@ -48,5 +48,6 @@
|
||||
"publicType": "公众平台类型",
|
||||
"siteName": "站点名称",
|
||||
"authTime": "授权时间",
|
||||
"qrcode": "二维码"
|
||||
"qrcode": "二维码",
|
||||
"delWeappVersionTips": "是否确定要删除该版本?"
|
||||
}
|
||||
|
||||
@ -74,5 +74,9 @@
|
||||
"foldText":"展开/折叠",
|
||||
"appName": "套餐内含应用",
|
||||
"addonName": "套餐内含插件",
|
||||
"siteInitTips":"确定要初始化站点吗?该操作将删除站点内所有数据,该操作无法退回,确定要继续初始化吗?"
|
||||
"siteInitTips":"确定要初始化站点吗?该操作将删除站点内所有数据,该操作无法退回,确定要继续初始化吗?",
|
||||
"createTimeStartDate": "开始时间(创建时间)",
|
||||
"createTimeEndDate": "结束时间(创建时间)",
|
||||
"expireTimeStartDate": "开始时间(到期时间)",
|
||||
"expireTimeEndDate": "结束时间(到期时间)"
|
||||
}
|
||||
|
||||
@ -24,5 +24,6 @@
|
||||
"startBackUp": "开始备份",
|
||||
"backUpEnd": "备份完成",
|
||||
"remark": "备注",
|
||||
"remarkEmpty": "无"
|
||||
"remarkEmpty": "无",
|
||||
"status": "状态"
|
||||
}
|
||||
|
||||
@ -13,5 +13,6 @@
|
||||
"syncTemplateError": "未能同步到模板库",
|
||||
"templateID": "模板ID",
|
||||
"siteWeappSync": "站点小程序同步",
|
||||
"syncSiteWeappTips": "是否要给该套餐下已授权小程序的站点提交代码?"
|
||||
"syncSiteWeappTips": "是否要给该套餐下已授权小程序的站点提交代码?",
|
||||
"helpInfo": "查看帮助"
|
||||
}
|
||||
|
||||
@ -70,7 +70,13 @@ getAppList()
|
||||
|
||||
const toLink = (item: any) => {
|
||||
if (item.url) {
|
||||
router.push(item.url)
|
||||
// 判断如果携带is_target=true就通过新窗口打开
|
||||
if (item.url.indexOf('is_target=true') != -1) {
|
||||
const url = router.resolve(item.url)
|
||||
window.open(url.href)
|
||||
} else {
|
||||
router.push(item.url)
|
||||
}
|
||||
} else {
|
||||
addonIndexRoute[item.key] && router.push({ name: addonIndexRoute[item.key] })
|
||||
}
|
||||
|
||||
@ -24,10 +24,10 @@
|
||||
|
||||
<el-form-item :label="t('parentMenu')" prop="parent_key">
|
||||
<el-tree-select class="input-width" v-if="formData.addon != ''" v-model="formData.parent_key"
|
||||
:props="{ label: 'menu_name', value: 'menu_key' }" :data="addonMenuList" check-strictly
|
||||
:props="{ label: 'menu_name', value: 'menu_key' }" :data="addonMenuListWithDisabled" check-strictly
|
||||
:render-after-expand="false" />
|
||||
<el-tree-select class="input-width" v-else v-model="formData.parent_key"
|
||||
:props="{ label: 'menu_name', value: 'menu_key' }" :data="sysMenuList" check-strictly
|
||||
:props="{ label: 'menu_name', value: 'menu_key' }" :data="sysMenuListWithDisabled" check-strictly
|
||||
:render-after-expand="false" />
|
||||
</el-form-item>
|
||||
|
||||
@ -184,6 +184,38 @@ const getAddonMenuFn = async (key: any) => {
|
||||
addonMenuList.value = data
|
||||
}
|
||||
|
||||
const markMenuDisabled = (menuList: any[], menuType: number): any[] => {
|
||||
return menuList.map(item => {
|
||||
const newItem = { ...item }
|
||||
// 判断当前节点是否可选
|
||||
if (item.menu_key === '') {
|
||||
// “顶级”节点(仅存在于 sysMenuList)
|
||||
newItem.disabled = menuType === 2 // 按钮不能选顶级
|
||||
} else {
|
||||
if (menuType === 2) {
|
||||
// 当前要创建的是按钮 → 只允许选择 menu_type === 1(菜单)
|
||||
newItem.disabled = item.menu_type !== 1
|
||||
} else {
|
||||
// 当前要创建的是目录/菜单 → 只允许选择 menu_type === 0(目录)
|
||||
newItem.disabled = item.menu_type !== 0
|
||||
}
|
||||
}
|
||||
// 递归处理 children
|
||||
if (Array.isArray(item.children) && item.children.length > 0) {
|
||||
newItem.children = markMenuDisabled(item.children, menuType)
|
||||
}
|
||||
return newItem
|
||||
})
|
||||
}
|
||||
|
||||
const sysMenuListWithDisabled = computed(() => {
|
||||
return markMenuDisabled(sysMenuList.value, formData.menu_type)
|
||||
})
|
||||
|
||||
const addonMenuListWithDisabled = computed(() => {
|
||||
return markMenuDisabled(addonMenuList.value, formData.menu_type)
|
||||
})
|
||||
|
||||
// 选择应用
|
||||
const addonChange = async (val: any) => {
|
||||
formData.parent_key = ''
|
||||
|
||||
@ -19,13 +19,19 @@
|
||||
<el-form-item :label="t('url')" prop="url">
|
||||
<el-input v-model.trim="sysUserLogTableData.searchParam.url" :placeholder="t('urlPlaceholder')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('操作时间')" prop="create_time">
|
||||
<el-date-picker v-model="sysUserLogTableData.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="loadSysUserLogList()">{{ t('search') }}</el-button>
|
||||
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="flex justify-end items-center w-[20%]">
|
||||
<div class="flex justify-end items-center w-[10%]">
|
||||
<div>
|
||||
<el-button type="primary" class="w-[100px]" @click="clearEvent()">{{ t('清空日志') }}</el-button>
|
||||
</div>
|
||||
@ -83,7 +89,8 @@ const sysUserLogTableData = reactive({
|
||||
searchParam: {
|
||||
ip: '',
|
||||
username: '',
|
||||
url: ''
|
||||
url: '',
|
||||
create_time:''
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@ -135,6 +135,14 @@
|
||||
<el-scrollbar class="h-[60vh] w-full whitespace-pre-wrap p-[20px]">
|
||||
<div v-html="failReason"></div>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button type="primary" @click="helpInfo">{{ t('helpInfo') }}</el-button>
|
||||
<el-button @click="failReasonDialogVisible = false">
|
||||
{{ t('close') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="uploadSuccessShowDialog" :title="t('warning')" width="500px" draggable>
|
||||
@ -470,6 +478,10 @@ const handleFailReason = (data: any) => {
|
||||
failReasonDialogVisible.value = true
|
||||
}
|
||||
|
||||
const helpInfo = () => {
|
||||
window.open('https://doc.niucloud.com/saasUse.html?keywords=/configFAQ/minWaChatUpload')
|
||||
}
|
||||
|
||||
const knownToKnow = () => {
|
||||
Storage.set({ key: 'weappUploadTipsLock', data: true })
|
||||
uploadSuccessShowDialog.value = false
|
||||
|
||||
@ -30,8 +30,8 @@
|
||||
|
||||
<div class="w-[700px]">
|
||||
<div class="flex flex-wrap">
|
||||
<!-- 多应用切换启动页 -->
|
||||
<el-button type="primary" @click="showDialog = true" v-if="siteApps.length > 1">{{ t('changePage') }}</el-button>
|
||||
<!-- 多应用切换启动页 v-if="siteApps.length > 1" -->
|
||||
<el-button type="primary" @click="showDialog = true">{{ t('changePage') }}</el-button>
|
||||
<el-button type="primary" @click="toDecorate()" v-show="page.use_template.action == 'decorate'" class="ml-[12px]">{{ t('decorate') }}</el-button>
|
||||
</div>
|
||||
|
||||
|
||||
@ -115,7 +115,7 @@
|
||||
<div class="mt-[16px] flex justify-end">
|
||||
<el-pagination v-model:current-page="formMemberList.page" v-model:page-size="formMemberList.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="formMemberList.total"
|
||||
@size-change="getFormRecordsMemberFn()" @current-change="getFormRecordsMemberFn()" />
|
||||
@size-change="getFormRecordsMemberFn()" @current-change="getFormRecordsMemberFn" />
|
||||
</div>
|
||||
|
||||
</el-tab-pane>
|
||||
|
||||
@ -203,11 +203,11 @@
|
||||
{{ item.site_group.group_name }}
|
||||
</div>
|
||||
<el-scrollbar class="flex pb-[20px] pt-[4px] box-border !h-[260px] w-[100%] scrollbarBox">
|
||||
<div class="flex mx-[30px] mt-[14px] leading-[1] items-center w-full" v-for="app in item.site_group.app_name">
|
||||
<div class="flex mx-[30px] mt-[14px] leading-[1] items-center" v-for="app in item.site_group.app_name">
|
||||
<div class="nc-iconfont nc-icon-duiV6mm text-[#466CEA]"></div>
|
||||
<div class="text-[14px] text-[#666666] ml-[3px] truncate">{{ app }}</div>
|
||||
</div>
|
||||
<div class="flex mx-[30px] mt-[14px] leading-[1] text-center w-full" v-for="addon in item.site_group.addon_name">
|
||||
<div class="flex mx-[30px] mt-[14px] leading-[1] text-center" v-for="addon in item.site_group.addon_name">
|
||||
<div class="nc-iconfont nc-icon-duiV6mm text-[#466CEA]"></div>
|
||||
<div class="text-[14px] text-[#666666] ml-[3px] truncate">{{ addon }}</div>
|
||||
</div>
|
||||
@ -363,6 +363,7 @@ const selectSite = (site: any) => {
|
||||
}
|
||||
|
||||
const toHome = () => {
|
||||
window.localStorage.setItem('admin.siteId', 0)
|
||||
if (!window.localStorage.getItem('admin.token')) {
|
||||
window.localStorage.setItem('admin.token', getToken())
|
||||
window.localStorage.setItem('admin.comparisonTokenStorage', getToken())
|
||||
|
||||
@ -62,9 +62,9 @@
|
||||
</el-card>
|
||||
|
||||
<div class="flex mb-4 flex-wrap" v-show="showType == 'card'" v-if="localList[activeName].length && !loading">
|
||||
<div class="rounded-md border p-[16px] pr-[20px] app-card mb-[20px] ml-[20px] cursor-pointer"
|
||||
<div class="rounded-md border p-[16px] app-card mb-[20px] ml-[20px] cursor-pointer"
|
||||
@click="appKeySingleSelect($event, row.key)"
|
||||
:class="{'border-primary': batchUpgradeApp.includes(row.key)}" v-for="row in localList[activeName]" :key="row.key">
|
||||
:class="{'selected': batchUpgradeApp.includes(row.key)}" v-for="row in localList[activeName]" :key="row.key">
|
||||
|
||||
<div class="flex justify-between mb-2">
|
||||
<div class="flex items-center flex-1 w-0">
|
||||
@ -87,9 +87,24 @@
|
||||
<p class="text-xs text-gray-500 truncate" :title="row.key">{{ row.key }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<el-checkbox @click.stop :model-value="batchUpgradeApp.includes(row.key)" :value="row.key" @change="appKeySingleSelect($event, row.key)" class="!w-[14px] !h-[14px]" v-if="activeName == 'recentlyUpdated' || activeName == 'uninstalled'"></el-checkbox>
|
||||
<view class="w-[60px]">
|
||||
<template v-if="!row.is_download">
|
||||
<el-button type="primary" class="flex-1" :loading="downloading == row.key" :disabled="downloading != ''" @click.stop="downEvent(row)">下载</el-button>
|
||||
</template>
|
||||
<template v-else-if="!row.install_info || Object.keys(row.install_info).length == 0">
|
||||
<el-button type="primary" class="flex-1" @click.stop="installAddonFn(row.key)">安装</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button type="warning" class="flex-1" @click.stop="upgradeAddonFn(row.key)" v-if="row.install_info.version != row.version">
|
||||
更新
|
||||
</el-button>
|
||||
<el-button class="flex-1" :disabled="true" v-else>
|
||||
最新
|
||||
</el-button>
|
||||
</template>
|
||||
</view>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="text-base">
|
||||
<span>版本: </span>
|
||||
<span>{{ row.install_info && Object.keys(row.install_info)?.length ? row.install_info.version : row.version }}</span>
|
||||
@ -98,26 +113,17 @@
|
||||
<span class="text-warning">{{ row.version }}</span>
|
||||
</template>
|
||||
</div>
|
||||
<el-button type="primary" link @click.stop="updateInformationFn(row)">更新记录</el-button>
|
||||
</div>
|
||||
|
||||
<div class="flex mt-[20px]">
|
||||
<template v-if="!row.is_download">
|
||||
<el-button type="primary" class="flex-1" :loading="downloading == row.key" :disabled="downloading != ''" @click.stop="downEvent(row)"><i class="iconfont iconanzhuang1 mr-[5px]"></i>立即下载</el-button>
|
||||
</template>
|
||||
<template v-else-if="!row.install_info || Object.keys(row.install_info).length == 0">
|
||||
<el-button type="primary" class="flex-1" @click.stop="installAddonFn(row.key)"><i class="iconfont iconanzhuang1 mr-[5px]"></i>立即安装</el-button>
|
||||
<el-button plain @click.stop="deleteAddonFn(row.key)">删除</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button type="warning" class="flex-1" @click.stop="upgradeAddonFn(row.key)" v-if="row.install_info.version != row.version">
|
||||
<i class="iconfont icongengxin mr-[5px]"></i>立即更新
|
||||
</el-button>
|
||||
<el-button class="flex-1" :disabled="true" v-else>
|
||||
<el-icon class="mr-[5px]"><Check /></el-icon>已是最新
|
||||
</el-button>
|
||||
<el-button plain @click.stop="uninstallAddonFn(row.key)">卸载</el-button>
|
||||
</template>
|
||||
<el-dropdown class="ml-[12px]">
|
||||
<i class="iconfont iconzhankai !text-xs"></i>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="getAddonDetailFn(row)">{{ t("detail") }}</el-dropdown-item>
|
||||
<el-dropdown-item @click="updateInformationFn(row)">更新记录</el-dropdown-item>
|
||||
<el-dropdown-item v-if="row.is_download && (!row.install_info || !Object.keys(row.install_info).length)" @click="deleteAddonFn(row.key)">删除</el-dropdown-item>
|
||||
<el-dropdown-item v-if="row.is_download && row.install_info && Object.keys(row.install_info).length" @click="uninstallAddonFn(row.key)">卸载</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -446,7 +452,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="installStep == 1 && !errorDialog" class="h-[50vh] mt-[20px]">
|
||||
<terminal ref="terminalRef" :name="`install-${terminalId}`" :context="currAddon" :init-log="null" :show-header="false" :show-log-time="true" @exec-cmd="onExecCmd" />
|
||||
<div class="flex flex-col h-full">
|
||||
<div class="flex-1 h-0">
|
||||
<terminal ref="terminalRef" :name="`install-${terminalId}`" :context="currAddon" :init-log="null" :show-header="false" :show-log-time="true" @exec-cmd="onExecCmd" />
|
||||
</div>
|
||||
<div class="flex justify-end mt-[20px]">
|
||||
<el-button type="primary" :loading="true" class="!w-[140px]">已用时 {{ formatUpgradeDuration }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="installStep == 2" class="h-[50vh] mt-[20px] flex flex-col">
|
||||
<!-- <el-result icon="success" :title="t('addonInstallSuccess')"></el-result> -->
|
||||
@ -639,6 +652,8 @@ const downEventHintFn = () => {
|
||||
downEvent(currDownData.value, true)
|
||||
}
|
||||
|
||||
const batchUpgradeApp = ref<String[]>([])
|
||||
|
||||
const activeNameTabFn = (data: any) => {
|
||||
activeName.value = data
|
||||
storage.set({ key: 'storeActiveName', data })
|
||||
@ -873,12 +888,6 @@ let notificationEl = null
|
||||
const getInstallTask = (first: boolean = true) => {
|
||||
getAddonInstalltask().then((res) => {
|
||||
if (res.data) {
|
||||
upgradeStartTime.value = Date.now()
|
||||
upgradeDuration.value = 0
|
||||
if (upgradeTimer) clearInterval(upgradeTimer)
|
||||
upgradeTimer = setInterval(() => {
|
||||
upgradeDuration.value++
|
||||
}, 1000)
|
||||
if (first) {
|
||||
installLog = []
|
||||
currAddon.value = res.data.addon
|
||||
@ -894,9 +903,14 @@ const getInstallTask = (first: boolean = true) => {
|
||||
showClose: false
|
||||
})
|
||||
}
|
||||
if (upgradeTimer) clearInterval(upgradeTimer)
|
||||
upgradeDuration.value = parseInt(Date.now() / 1000) - res.data.timestamp
|
||||
upgradeTimer = setInterval(() => {
|
||||
upgradeDuration.value++
|
||||
}, 1000)
|
||||
}
|
||||
if (res.data.error) {
|
||||
terminalRef.value.pushMessage({ content: res.data.error, class: 'error' })
|
||||
terminalRef.value?.pushMessage({ content: res.data.error, class: 'error' })
|
||||
errorMsg.value = res.data.error
|
||||
errorDialog.value = true
|
||||
if (upgradeTimer) {
|
||||
@ -912,7 +926,6 @@ const getInstallTask = (first: boolean = true) => {
|
||||
setTimeout(() => {
|
||||
getInstallTask(false)
|
||||
}, 2000)
|
||||
|
||||
} else {
|
||||
if (!first) {
|
||||
installStep.value = 2
|
||||
@ -922,11 +935,12 @@ const getInstallTask = (first: boolean = true) => {
|
||||
}
|
||||
localListFn()
|
||||
userStore.clearRouters()
|
||||
notificationEl.close()
|
||||
notificationEl?.close()
|
||||
}
|
||||
}
|
||||
}).catch((e) => {
|
||||
terminalRef.value.pushMessage({ content: e.message, class: 'error' })
|
||||
console.log(e)
|
||||
terminalRef.value?.pushMessage({ content: e.message, class: 'error' })
|
||||
})
|
||||
}
|
||||
|
||||
@ -1252,8 +1266,6 @@ const versionJudge = (row: any) => {
|
||||
return false
|
||||
}
|
||||
|
||||
const batchUpgradeApp = ref<String[]>([])
|
||||
|
||||
const appKeyAllSelect = () => {
|
||||
if (localList.value[activeName.value].length) {
|
||||
if (localList.value[activeName.value].length == batchUpgradeApp.value.length) {
|
||||
@ -1583,6 +1595,11 @@ html.dark .table-head-bg {
|
||||
.app-card {
|
||||
width: calc((100% - 120px) / 5);
|
||||
min-width: 260px;
|
||||
|
||||
&.selected {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
border-color: var(--el-color-primary-light-9);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@ -33,8 +33,8 @@
|
||||
<el-main class="login-main w-full mt-[120px] justify-center h-0" v-else-if="!imgLoading && loginType == 'site'">
|
||||
<div>
|
||||
<div class="login-main-left flex flex-col items-center justify-center">
|
||||
<div class="w-[130px] h-[40px] overflow-hidden" v-if="webSite.site_login_logo">
|
||||
<el-image class="w-full h-full" :src="img(webSite.site_login_logo)" fit="contain">
|
||||
<div class="w-[130px] h-[40px] overflow-hidden" v-if="loginConfig.site_login_logo">
|
||||
<el-image class="w-full h-full" :src="img(loginConfig.site_login_logo)" fit="contain">
|
||||
<template #error>
|
||||
<div class="flex justify-center items-center w-full h-full">
|
||||
<img class="max-w-[130px]" src="@/app/assets/images/white_logo.png" alt="" object-fit="contain" />
|
||||
@ -119,7 +119,7 @@ route.redirectedFrom && (route.query.redirect = route.redirectedFrom.path)
|
||||
const webSite: any = computed(() => useSystemStore().website)
|
||||
|
||||
const siteBackgroundStyle = computed(() => ({
|
||||
backgroundImage: webSite.value?.site_login_bg_img ? `url(${img(webSite.value.site_login_bg_img)})` : '',
|
||||
backgroundImage: loginConfig.value?.site_login_bg_img ? `url(${img(loginConfig.value.site_login_bg_img)})` : '',
|
||||
backgroundSize: 'cover',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundPosition: 'center'
|
||||
|
||||
@ -279,6 +279,8 @@ const previewPoster = (data: any) => {
|
||||
previewDialogVisible.value = true
|
||||
}
|
||||
isRepeat.value = false
|
||||
}).catch(() => {
|
||||
isRepeat.value = false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,18 @@
|
||||
<upload-image v-model="formData.site_bg" />
|
||||
<div class="form-tip">{{t('siteBgImgTip')}}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('siteLoginLogo')">
|
||||
<div>
|
||||
<upload-image v-model="formData.site_login_logo" />
|
||||
<p class="text-[12px] text-[#a9a9a9]">{{ t('siteLoginLogoTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('siteLoginBgImg')">
|
||||
<div>
|
||||
<upload-image v-model="formData.site_login_bg_img" />
|
||||
<p class="text-[12px] text-[#a9a9a9]">{{ t('siteLoginBgImgTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-form>
|
||||
@ -51,7 +63,9 @@ const formData = reactive<Record<string, number | string>>({
|
||||
is_captcha: 0,
|
||||
is_site_captcha: 0,
|
||||
bg: '',
|
||||
site_bg: ''
|
||||
site_bg: '',
|
||||
site_login_logo: '',
|
||||
site_login_bg_img: ''
|
||||
})
|
||||
|
||||
const getFormData = async () => {
|
||||
|
||||
@ -1,80 +1,80 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-[20px]">
|
||||
<el-table :data="addonList" size="large" v-loading="loading">
|
||||
<template #empty>
|
||||
<span>{{ !loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<div class="mt-[20px]">
|
||||
<el-table :data="addonList" size="large" v-loading="loading">
|
||||
<template #empty>
|
||||
<span>{{ !loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
|
||||
<el-table-column prop="title" :label="t('app')" min-width="120" >
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center">
|
||||
<el-image class="w-[40px] h-[40px] rounded-md overflow-hidden" :src="row.icon" fit="contain">
|
||||
<template #error>
|
||||
<div class="flex items-center w-full h-full">
|
||||
<img class="w-full h-full" src="@/app/assets/images/icon-addon-one.png" alt="">
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div class="flex-1 ml-2 truncate">{{ row.title }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="openSettingLayer(row.key)">{{ t('setting') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="showDialog" :title="t('selectLayout')" width="800" :destroy-on-close="true">
|
||||
<div class="h-[300px]">
|
||||
<el-scrollbar >
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<h3 class="!text-sm !text-[#444]">{{ t('layout') }}</h3>
|
||||
<div class="flex items-center cursor-pointer" @click="toDiyLayout">
|
||||
<span class="iconfont iconwenhao text-[#999] !text-[14px]"></span>
|
||||
<div class="ml-[2px] text-[12px] text-[#999]">如何开发自定义布局</div>
|
||||
<el-table-column prop="title" :label="t('app')" min-width="120" >
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center">
|
||||
<el-image class="w-[40px] h-[40px] rounded-md overflow-hidden" :src="row.icon" fit="contain">
|
||||
<template #error>
|
||||
<div class="flex items-center w-full h-full">
|
||||
<img class="w-full h-full" src="@/app/assets/images/icon-addon-one.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-items-stretch">
|
||||
<div class="w-[180px] h-[130px] mr-[10px] mb-[10px] border hover:border-primary cursor-pointer"
|
||||
:class="{'border-primary': ((!layoutConfig[currAddon] && item.layout == 'default') || (layoutConfig[currAddon] == item.layout)) }"
|
||||
@click="layoutConfig[currAddon] = item.layout"
|
||||
v-for="item in systemLayout">
|
||||
<img :src="img(item.cover)" class="w-full h-full" />
|
||||
</div>
|
||||
<div class="w-[180px] h-[130px] mr-[20px] border hover:border-primary cursor-pointer"
|
||||
:class="{'border-primary': ((!layoutConfig[currAddon] && addonLayout.layout == 'default') || (layoutConfig[currAddon] == addonLayout.layout)) }"
|
||||
@click="layoutConfig[currAddon] = addonLayout.layout"
|
||||
v-if="addonLayout">
|
||||
<img :src="img(addonLayout.cover)" class="w-full h-full" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- <h3 class="panel-title !text-sm">{{ t('themeColor') }}</h3>
|
||||
<div>
|
||||
<el-color-picker v-model="themeColor[currAddon]" size="large" />
|
||||
<div class="form-tip text-[#999] mt-2">设置的色调会在前端站点列表体现[home/index],用于区分不同的应用</div>
|
||||
</div> -->
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
</el-image>
|
||||
<div class="flex-1 ml-2 truncate">{{ row.title }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="openSettingLayer(row.key)">{{ t('setting') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="showDialog" :title="t('selectLayout')" width="800" :destroy-on-close="true">
|
||||
<div class="h-[300px]">
|
||||
<el-scrollbar >
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<h3 class="!text-sm !text-[#444]">{{ t('layout') }}</h3>
|
||||
<div class="flex items-center cursor-pointer" @click="toDiyLayout">
|
||||
<span class="iconfont iconwenhao text-[#999] !text-[14px]"></span>
|
||||
<div class="ml-[2px] text-[12px] text-[#999]">如何开发自定义布局</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex justify-items-stretch">
|
||||
<div class="w-[180px] h-[130px] mr-[10px] mb-[10px] border hover:border-primary cursor-pointer"
|
||||
:class="{'border-primary': ((!layoutConfig[currAddon] && item.layout == 'default') || (layoutConfig[currAddon] == item.layout)) }"
|
||||
@click="layoutConfig[currAddon] = item.layout"
|
||||
v-for="item in systemLayout">
|
||||
<img :src="img(item.cover)" class="w-full h-full" />
|
||||
</div>
|
||||
<div class="w-[180px] h-[130px] mr-[20px] border hover:border-primary cursor-pointer"
|
||||
:class="{'border-primary': ((!layoutConfig[currAddon] && addonLayout.layout == 'default') || (layoutConfig[currAddon] == addonLayout.layout)) }"
|
||||
@click="layoutConfig[currAddon] = addonLayout.layout"
|
||||
v-if="addonLayout">
|
||||
<img :src="img(addonLayout.cover)" class="w-full h-full" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- <h3 class="panel-title !text-sm">{{ t('themeColor') }}</h3>
|
||||
<div>
|
||||
<el-color-picker v-model="themeColor[currAddon]" size="large" />
|
||||
<div class="form-tip text-[#999] mt-2">设置的色调会在前端站点列表体现[home/index],用于区分不同的应用</div>
|
||||
</div> -->
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" :loading="loading" @click="confirm()">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -93,67 +93,67 @@ const systemLayout = ref([])
|
||||
const addonLayout = ref(null)
|
||||
const themeColor = ref({})
|
||||
const addonList = ref([
|
||||
{
|
||||
title: t('manyApp'),
|
||||
key: 'system',
|
||||
icon: ''
|
||||
}
|
||||
{
|
||||
title: t('manyApp'),
|
||||
key: 'system',
|
||||
icon: ''
|
||||
}
|
||||
])
|
||||
|
||||
const layouts = import.meta.globEager('@/layout/**/layout.json')
|
||||
for (const key in layouts) {
|
||||
const layout = layouts[key]
|
||||
systemLayout.value.push(layout.default)
|
||||
const layout = layouts[key]
|
||||
systemLayout.value.push(layout.default)
|
||||
}
|
||||
const addonLayouts = import.meta.globEager('@/addon/**/layout/layout.json')
|
||||
|
||||
getInstalledAddonList().then(({ data }) => {
|
||||
Object.keys(data).forEach((key) => {
|
||||
const item = data[key]
|
||||
item.type == 'app' && addonList.value.push(item)
|
||||
})
|
||||
loading.value = false
|
||||
Object.keys(data).forEach((key) => {
|
||||
const item = data[key]
|
||||
item.type == 'app' && addonList.value.push(item)
|
||||
})
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
const getLayoutConfig = () => {
|
||||
getLayout().then(({ data }) => {
|
||||
layoutConfig.value = data
|
||||
})
|
||||
getThemecolor().then(({ data }) => {
|
||||
themeColor.value = data
|
||||
})
|
||||
getLayout().then(({ data }) => {
|
||||
layoutConfig.value = data
|
||||
})
|
||||
getThemecolor().then(({ data }) => {
|
||||
themeColor.value = data
|
||||
})
|
||||
}
|
||||
getLayoutConfig()
|
||||
|
||||
const currAddon = ref('')
|
||||
const showDialog = ref(false)
|
||||
const openSettingLayer = async (key: string) => {
|
||||
if (key != 'system') {
|
||||
addonLayout.value = null
|
||||
Object.keys(addonLayouts).forEach((path) => {
|
||||
path.indexOf(`/addon/${key}/`) != -1 && (addonLayout.value = addonLayouts[path].default)
|
||||
})
|
||||
}
|
||||
currAddon.value = key
|
||||
showDialog.value = true
|
||||
if (key != 'system') {
|
||||
addonLayout.value = null
|
||||
Object.keys(addonLayouts).forEach((path) => {
|
||||
path.indexOf(`/addon/${key}/`) != -1 && (addonLayout.value = addonLayouts[path].default)
|
||||
})
|
||||
}
|
||||
currAddon.value = key
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
const confirm = () => {
|
||||
setThemecolor({
|
||||
key: currAddon.value,
|
||||
value: themeColor.value[currAddon.value] ? themeColor.value[currAddon.value] : ''
|
||||
})
|
||||
setLayout({
|
||||
key: currAddon.value,
|
||||
value: layoutConfig.value[currAddon.value] ? layoutConfig.value[currAddon.value] : 'default'
|
||||
})
|
||||
showDialog.value = false
|
||||
setThemecolor({
|
||||
key: currAddon.value,
|
||||
value: themeColor.value[currAddon.value] ? themeColor.value[currAddon.value] : ''
|
||||
})
|
||||
setLayout({
|
||||
key: currAddon.value,
|
||||
value: layoutConfig.value[currAddon.value] ? layoutConfig.value[currAddon.value] : 'default'
|
||||
})
|
||||
showDialog.value = false
|
||||
}
|
||||
|
||||
// 跳转自定义布局
|
||||
const toDiyLayout = () => {
|
||||
let url = 'https://doc.niucloud.com/saas.html?keywords=/ru-he-kai-fa-zi-ding-yi-bu-ju-hou-tai-bu-ju';
|
||||
window.open(url)
|
||||
let url = 'https://doc.niucloud.com/saas.html?keywords=/pluginDev/diyLayoutDev';
|
||||
window.open(url)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -20,18 +20,6 @@
|
||||
<p class="text-[12px] text-[#a9a9a9]">{{ t('iconPlaceholder') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('siteLoginLogo')" v-if="appType == 'admin'">
|
||||
<div>
|
||||
<upload-image v-model="formData.site_login_logo" />
|
||||
<p class="text-[12px] text-[#a9a9a9]">{{ t('siteLoginLogoTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('siteLoginBgImg')" v-if="appType == 'admin'">
|
||||
<div>
|
||||
<upload-image v-model="formData.site_login_bg_img" />
|
||||
<p class="text-[12px] text-[#a9a9a9]">{{ t('siteLoginBgImgTips') }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('keywords')">
|
||||
<el-input v-model.trim="formData.keywords" :placeholder="t('keywordsPlaceholder')" class="input-width" clearable maxlength="20" show-word-limit />
|
||||
</el-form-item>
|
||||
|
||||
@ -36,14 +36,14 @@
|
||||
|
||||
<el-form-item prop="create_time" v-if="isShow">
|
||||
<el-date-picker v-model="siteTableData.searchParam.create_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('createTimeStartDate')"
|
||||
:end-placeholder="t('createTimeEndDate')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="expire_time" v-if="isShow">
|
||||
<el-date-picker v-model="siteTableData.searchParam.expire_time" type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
|
||||
:end-placeholder="t('endDate')" />
|
||||
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('expireTimeStartDate')"
|
||||
:end-placeholder="t('expireTimeEndDate')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
@ -53,7 +53,7 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="flex justify-end items-center flex-1">
|
||||
<div class="right-btn-group ">
|
||||
<div class="right-btn-group ">
|
||||
<tempalte class="flex items-center">
|
||||
<el-tooltip
|
||||
class="box-item"
|
||||
@ -392,7 +392,7 @@ const getSiteAllowChangeFn = ()=>{
|
||||
let isAllowChange = allowChange.value ? true : false
|
||||
localStorage.setItem('isAllowChange',isAllowChange.toString())
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
getSiteAllowChangeFn()
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ const type = ref(attachmentType[0])
|
||||
|
||||
.el-tabs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: column-reverse;
|
||||
height: calc(100% - 40px);
|
||||
}
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="330">
|
||||
<template #default="{ row }">
|
||||
<div class="flex flex-col items-end">
|
||||
<el-button type="primary" link @click="commit(row.group_id)">{{ t('weappVersionUpdate') }}</el-button>
|
||||
<el-button type="primary" link :loading="uploading == row.group_id" @click="commit(row.group_id)">{{ t('weappVersionUpdate') }}</el-button>
|
||||
<el-button type="primary" link @click="showCommitRecordDialog(row.group_id)">{{ t('weappVersionUpdateRecord') }}</el-button>
|
||||
<el-button type="primary" link @click="syncSiteWeappFn(row.group_id)">{{ t('siteWeappSync') }}</el-button>
|
||||
</div>
|
||||
@ -82,6 +82,7 @@
|
||||
<el-table-column prop="create_time" :label="t('createTime')"></el-table-column>
|
||||
<el-table-column :label="t('operation')" align="right" fixed="right" width="130">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link v-if="row.status == 0 || row.status == -1" @click="deleteVersion(row)">{{ t('delete') }}</el-button>
|
||||
<el-button type="primary" link v-if="row.status == -1" @click="handleFailReason(row)">{{ t('failReason') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -96,19 +97,27 @@
|
||||
<el-scrollbar class="h-[60vh] w-full whitespace-pre-wrap p-[20px]">
|
||||
{{ failReason }}
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button type="primary" @click="helpInfo">{{ t('helpInfo') }}</el-button>
|
||||
<el-button @click="failReasonDialogVisible = false">
|
||||
{{ t('close') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { getWeappLastCommitRecord, weappCommit, getWeappCommitRecord, getSiteGroupCommitRecord, syncSiteWeapp } from '@/app/api/wxoplatform'
|
||||
import { getWeappLastCommitRecord, weappCommit, getWeappCommitRecord, getSiteGroupCommitRecord, syncSiteWeapp, delVersion } from '@/app/api/wxoplatform'
|
||||
import { t } from '@/lang'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
const uploading = ref(false)
|
||||
const uploading = ref(0)
|
||||
const lastRecord = ref({})
|
||||
const commitRecordDialogShow = ref(false)
|
||||
const commitRecordTableData = reactive({
|
||||
@ -136,19 +145,36 @@ const handleFailReason = (data: any) => {
|
||||
failReason.value = data.fail_reason
|
||||
failReasonDialogShow.value = true
|
||||
}
|
||||
const helpInfo = () => {
|
||||
window.open('https://doc.niucloud.com/saasUse.html?keywords=/configFAQ/minWaChatUpload')
|
||||
}
|
||||
|
||||
const deleteVersion = (data: any) => {
|
||||
ElMessageBox.confirm(t('delWeappVersionTips'), t('warning'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
delVersion(data.id).then(() => {
|
||||
loadCommitRecordList()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
getWeappLastCommitRecord().then(({ data }) => {
|
||||
lastRecord.value = data
|
||||
})
|
||||
|
||||
const commit = (siteGroupId = '') => {
|
||||
if (uploading.value) return
|
||||
uploading.value = true
|
||||
if (uploading.value != 0) return
|
||||
uploading.value = siteGroupId
|
||||
|
||||
weappCommit({ site_group_id: siteGroupId }).then(() => {
|
||||
uploading.value = false
|
||||
uploading.value = 0
|
||||
}).catch(() => {
|
||||
uploading.value = false
|
||||
uploading.value = 0
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -60,11 +60,11 @@
|
||||
<el-input v-model="attachmentParam.real_name" class="m-0 !w-[200px]" clearable :placeholder="t('upload.placeholder' + type + 'Name')" prefix-icon="Search" @input="getAttachmentList()" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="flex-1 my-[15px] h-0" v-loading="attachment.loading">
|
||||
<div class="flex-1 mb-[15px] mt-[10px] h-0" v-loading="attachment.loading">
|
||||
<el-scrollbar>
|
||||
<!-- 选择弹出框 -->
|
||||
<div class="flex flex-wrap" v-if="attachment.data.length && (operate === true || scene != 'attachment')">
|
||||
<div class="attachment-item mr-[10px]" :class="scene == 'select' ? 'w-[100px]' : 'w-[120px]'" v-for="(item, index) in attachment.data" :key="index">
|
||||
<div class="attachment-item relative mr-[10px] mt-[6px]" :class="scene == 'select' ? 'w-[100px]' : 'w-[120px]'" v-for="(item, index) in attachment.data" :key="index">
|
||||
<div class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center" :class="scene == 'select' ? 'h-[100px]' : 'h-[120px]'" @click="selectFile(item)">
|
||||
|
||||
<el-image :src="img(item.thumb)" fit="contain" v-if="type == 'image'"/>
|
||||
@ -76,9 +76,10 @@
|
||||
<span class="absolute bottom-[2px] right-[2px] text-white z-[2] leading-none">{{ getFileIndex(item.att_id) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<icon name="element CircleCloseFilled" v-if="type != 'icon' && !operate" @click="deleteAttachmentEvent(index)" class="top-[-6px] right-[-6px] absolute z-[3] del-icon hidden cursor-pointer opacity-[0.8]" />
|
||||
|
||||
<div class="flex items-center">
|
||||
<el-tooltip placement="top">
|
||||
<template #content>{{ item.real_name }}</template>
|
||||
@ -110,7 +111,7 @@
|
||||
|
||||
<!-- 素材管理 -->
|
||||
<div class="flex flex-wrap" v-else-if="attachment.data.length && operate === false">
|
||||
<div class="attachment-item mr-[10px] w-[120px]" v-for="(item, index) in attachment.data" :key="index">
|
||||
<div class="attachment-item relative mr-[10px] mt-[6px] w-[120px]" v-for="(item, index) in attachment.data" :key="index">
|
||||
<div class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center h-[120px]">
|
||||
<el-image :src="img(item.thumb)" fit="contain" v-if="type == 'image'" :preview-src-list="item.image_list"/>
|
||||
<video :src="img(item.thumb)" v-else-if="type == 'video'" @click="previewVideo(index)"></video>
|
||||
@ -122,6 +123,7 @@
|
||||
<div class="truncate my-[10px] cursor-pointer text-base flex-1 text-center">{{ item.real_name }}</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<icon name="element CircleCloseFilled" v-if="type != 'icon'" @click="deleteAttachmentEvent(index)" class="top-[-6px] right-[-6px] absolute z-[3] del-icon hidden cursor-pointer opacity-[0.8]" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex absolute top-0 left-0 right-0 bottom-0 items-center justify-center" v-else>
|
||||
@ -669,6 +671,9 @@ defineExpose({
|
||||
.attachment-action {
|
||||
display: block;
|
||||
}
|
||||
.del-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.attachment-list-wrap {
|
||||
|
||||
@ -79,7 +79,7 @@ routers.forEach(item => {
|
||||
|
||||
const oneMenuActive = ref(oneMenuData.value[0].name)
|
||||
watch(route, () => {
|
||||
twoMenuData.value = route.matched[1].children ?? []
|
||||
twoMenuData.value = route.matched[2].children ?? []
|
||||
oneMenuActive.value = route.matched[1].name == ADMIN_ROUTE.children[0].name ? route.matched[2].name : route.matched[1].name
|
||||
defaultOpeneds.value = twoMenuData.value.map(item => item.name)
|
||||
}, { immediate: true })
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<el-scrollbar>
|
||||
<div class="p-[15px]">
|
||||
<router-view v-slot="{ Component, route }" v-if="appStore.routeRefreshTag">
|
||||
<keep-alive :include="tabbarStore.tabNames">
|
||||
<keep-alive :include="tabbarStore.tabNames" :max="15">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
@ -25,7 +25,7 @@
|
||||
<!-- 主体 end -->
|
||||
</el-container>
|
||||
</el-container>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<el-scrollbar>
|
||||
<div class="p-[15px]">
|
||||
<router-view v-slot="{ Component, route }" v-if="appStore.routeRefreshTag">
|
||||
<keep-alive :include="tabbarStore.tabNames">
|
||||
<keep-alive :include="tabbarStore.tabNames" :max="15">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
@ -25,7 +25,7 @@
|
||||
<!-- 主体 end -->
|
||||
</el-container>
|
||||
</el-container>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<el-scrollbar v-if="twoMenuData.length" class="two-menu w-[190px]">
|
||||
<div class="w-[190px] h-[64px] flex items-center justify-center text-[16px] border-0 border-b-[1px] border-solid border-[#eee]">{{ route.matched[1].meta.title }}</div>
|
||||
<div class="w-[190px] h-[64px] flex items-center justify-center text-[16px] border-0 border-b-[1px] border-solid border-[#eee]">{{ route.matched[2].meta.title }}</div>
|
||||
<el-menu :default-active="route.name" :router="true" class="aside-menu" :collapse="systemStore.menuIsCollapse">
|
||||
<menu-item v-for="(route, index) in twoMenuData" :routes="route" :key="index" />
|
||||
</el-menu>
|
||||
@ -307,21 +307,21 @@ watch(route, () => {
|
||||
} else {
|
||||
// 多应用
|
||||
if (siteInfo?.apps.length > 1) {
|
||||
twoMenuData.value = route.matched[1].children
|
||||
oneMenuActive.value = route.matched[1].name
|
||||
twoMenuData.value = route.matched[2].children
|
||||
oneMenuActive.value = route.matched[2].name
|
||||
} else {
|
||||
// 单应用
|
||||
const oneMenu = route.matched[1]
|
||||
const oneMenu = route.matched[2]
|
||||
if (oneMenu.meta.addon == '') {
|
||||
oneMenuActive.value = route.matched[1].name
|
||||
twoMenuData.value = route.matched[1].children ?? []
|
||||
oneMenuActive.value = route.matched[2].name
|
||||
twoMenuData.value = route.matched[2].children ?? []
|
||||
} else {
|
||||
if (oneMenu.meta.addon == siteInfo?.apps[0].key) {
|
||||
oneMenuActive.value = route.matched[3].name
|
||||
twoMenuData.value = route.matched[3].children ?? []
|
||||
} else {
|
||||
oneMenuActive.value = route.matched[2].name
|
||||
twoMenuData.value = route.matched[2].children ?? []
|
||||
} else {
|
||||
oneMenuActive.value = route.matched[1].name
|
||||
twoMenuData.value = route.matched[1].children ?? []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
<el-scrollbar>
|
||||
<div class="p-[15px]">
|
||||
<router-view v-slot="{ Component, route }" v-if="appStore.routeRefreshTag">
|
||||
<keep-alive :include="tabbarStore.tabNames">
|
||||
<keep-alive :include="tabbarStore.tabNames" :max="15">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
<el-scrollbar>
|
||||
<div class="p-[15px]">
|
||||
<router-view v-slot="{ Component, route }" v-if="appStore.routeRefreshTag">
|
||||
<keep-alive :include="tabbarStore.tabNames">
|
||||
<keep-alive :include="tabbarStore.tabNames" :max="15">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
<el-scrollbar>
|
||||
<div class="p-[15px]">
|
||||
<router-view v-slot="{ Component, route }" v-if="appStore.routeRefreshTag">
|
||||
<keep-alive :include="tabbarStore.tabNames">
|
||||
<keep-alive :include="tabbarStore.tabNames" :max="15">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
|
||||
<el-scrollbar v-if="twoMenuData.length" class="two-menu w-[152px]">
|
||||
<div class="w-[152px] h-[64px] flex items-center justify-center text-[16px] border-b-[1px] border-solid border-[var(--el-border-color-lighter)]">
|
||||
{{ route.matched[1].meta.title }}
|
||||
{{ route.matched[2].meta.title }}
|
||||
</div>
|
||||
|
||||
<el-menu class="aside-menu" :default-active="route.name" :default-openeds="menuOption" :router="true" :collapse="systemStore.menuIsCollapse">
|
||||
@ -327,21 +327,21 @@ watch(route, () => {
|
||||
} else {
|
||||
// 多应用
|
||||
if (siteInfo?.apps.length > 1) {
|
||||
twoMenuData.value = route.matched[1].children
|
||||
oneMenuActive.value = route.matched[1].name
|
||||
twoMenuData.value = route.matched[2].children
|
||||
oneMenuActive.value = route.matched[2].name
|
||||
} else {
|
||||
// 单应用
|
||||
const oneMenu = route.matched[1]
|
||||
const oneMenu = route.matched[2]
|
||||
if (oneMenu.meta.addon == '') {
|
||||
oneMenuActive.value = route.matched[1].name
|
||||
twoMenuData.value = route.matched[1].children ?? []
|
||||
oneMenuActive.value = route.matched[2].name
|
||||
twoMenuData.value = route.matched[2].children ?? []
|
||||
} else {
|
||||
if (oneMenu.meta.addon == siteInfo?.apps[0].key) {
|
||||
oneMenuActive.value = route.matched[3].name
|
||||
twoMenuData.value = route.matched[3].children ?? []
|
||||
} else {
|
||||
oneMenuActive.value = route.matched[2].name
|
||||
twoMenuData.value = route.matched[2].children ?? []
|
||||
} else {
|
||||
oneMenuActive.value = route.matched[1].name
|
||||
twoMenuData.value = route.matched[1].children ?? []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
<el-scrollbar>
|
||||
<div class="p-[15px]">
|
||||
<router-view v-slot="{ Component, route }" v-if="appStore.routeRefreshTag">
|
||||
<keep-alive :include="tabbarStore.tabNames">
|
||||
<keep-alive :include="tabbarStore.tabNames" :max="15">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
</router-view>
|
||||
|
||||
@ -134,20 +134,11 @@ router.beforeEach(async (to: any, from, next) => {
|
||||
|
||||
// 添加动态路由
|
||||
userStore.routers.forEach(route => {
|
||||
if (!route.children) {
|
||||
if (route.meta.app == 'admin') {
|
||||
router.addRoute(ADMIN_ROUTE.children[0].name, route)
|
||||
} else {
|
||||
router.addRoute(SITE_ROUTE.children[0].name, route)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 动态添加可访问路由表
|
||||
if (route.meta.app == 'admin') {
|
||||
router.addRoute(ADMIN_ROUTE.name, route)
|
||||
router.addRoute(ADMIN_ROUTE.children[0].name, route)
|
||||
} else {
|
||||
router.addRoute(SITE_ROUTE.name, route)
|
||||
router.addRoute(SITE_ROUTE.children[0].name, route)
|
||||
}
|
||||
})
|
||||
next(to)
|
||||
|
||||
@ -25,12 +25,13 @@ export const ROOT_ROUTER: RouteRecordRaw = {
|
||||
// 平台端根路由
|
||||
export const ADMIN_ROUTE: RouteRecordRaw = {
|
||||
path: '/admin',
|
||||
name: Symbol('admin'),
|
||||
name: 'admin',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: Symbol('adminRoot'),
|
||||
component: Default
|
||||
name: 'adminRoot',
|
||||
component: Default,
|
||||
children: []
|
||||
},
|
||||
{
|
||||
path: 'login',
|
||||
@ -46,16 +47,16 @@ export const ADMIN_ROUTE: RouteRecordRaw = {
|
||||
// HOME端根路由
|
||||
export const HOME_ROUTE: RouteRecordRaw = {
|
||||
path: '/home',
|
||||
name: Symbol('home'),
|
||||
name: 'home',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: Symbol('homeRoot'),
|
||||
name: 'homeRoot',
|
||||
component: Default
|
||||
},
|
||||
{
|
||||
path: 'index',
|
||||
name: Symbol('homeIndex'),
|
||||
name: 'homeIndex',
|
||||
meta: {
|
||||
type: 1,
|
||||
title: '站点管理'
|
||||
@ -68,12 +69,13 @@ export const HOME_ROUTE: RouteRecordRaw = {
|
||||
// 站点端根路由
|
||||
export const SITE_ROUTE: RouteRecordRaw = {
|
||||
path: '/site',
|
||||
name: Symbol('site'),
|
||||
name: 'site',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: Symbol('siteRoot'),
|
||||
component: Default
|
||||
name: 'siteRoot',
|
||||
component: Default,
|
||||
children: []
|
||||
},
|
||||
{
|
||||
path: 'wxoplatform/callback',
|
||||
@ -98,7 +100,7 @@ export const SITE_ROUTE: RouteRecordRaw = {
|
||||
export const DECORATE_ROUTER: RouteRecordRaw = {
|
||||
path: '/decorate',
|
||||
component: Decorate,
|
||||
name: Symbol('decorate'),
|
||||
name: 'decorate',
|
||||
children: []
|
||||
}
|
||||
|
||||
@ -144,12 +146,11 @@ const createRoute = function (route: Route, parentRoute: RouteRecordRaw | null =
|
||||
addon: route.addon,
|
||||
attr: route.menu_attr,
|
||||
parent_route: parentRoute ? parentRoute.meta : parentRoute,
|
||||
sort: route.sort
|
||||
sort: route.sort,
|
||||
componentName: route.menu_key
|
||||
}
|
||||
}
|
||||
if (route.menu_type == 0) {
|
||||
record.component = parentRoute ? RouterView : () => Promise.resolve(Default)
|
||||
} else {
|
||||
if (route.menu_type == 1) {
|
||||
record.component = route.addon ? addonModules[`/src/addon/${ route.addon }/views/${ route.view_path }.vue`] : modules[`/src/app/views/${ route.view_path }.vue`]
|
||||
}
|
||||
return record
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { RouteLocationNormalizedLoaded, RouteRecordName } from 'vue-router'
|
||||
import useSystemStore from '@/stores/modules/system'
|
||||
|
||||
interface Tabbar {
|
||||
curr: string,
|
||||
@ -26,7 +27,8 @@ const useTabbarStore = defineStore('tabbar', {
|
||||
path: roter.path,
|
||||
title: roter.meta ? roter.meta.title : '',
|
||||
name: roter.name,
|
||||
query: roter.query || {}
|
||||
query: roter.query || {},
|
||||
compomentName: roter.matched.at(-1).components.default.__name
|
||||
}
|
||||
},
|
||||
removeTab(path: string) {
|
||||
@ -40,8 +42,9 @@ const useTabbarStore = defineStore('tabbar', {
|
||||
tabLength: (state) => Object.keys(state.tabs).length,
|
||||
tabNames: (state) => {
|
||||
const name: any[] = []
|
||||
if (!useSystemStore().tab) return name
|
||||
Object.keys(state.tabs).forEach(key => {
|
||||
name.push(state.tabs[key].name)
|
||||
name.push(state.tabs[key].compomentName)
|
||||
})
|
||||
return name
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "nc-iconfont"; /* Project id 4567203 */
|
||||
src: url('//at.alicdn.com/t/c/font_4567203_9qmfc2elgrt.woff2?t=1741345195504') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_4567203_9qmfc2elgrt.woff?t=1741345195504') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_4567203_9qmfc2elgrt.ttf?t=1741345195504') format('truetype');
|
||||
src: url('//at.alicdn.com/t/c/font_4567203_mq3zv60st5a.woff2?t=1767940264104') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_4567203_mq3zv60st5a.woff?t=1767940264104') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_4567203_mq3zv60st5a.ttf?t=1767940264104') format('truetype');
|
||||
}
|
||||
|
||||
.nc-iconfont {
|
||||
@ -13,6 +13,578 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.nc-icon-huiyuangaikuang:before {
|
||||
content: "\e91b";
|
||||
}
|
||||
|
||||
.nc-icon-jiaoyigaikuang:before {
|
||||
content: "\e91a";
|
||||
}
|
||||
|
||||
.nc-icon-zhanghuruzhushenqing:before {
|
||||
content: "\e919";
|
||||
}
|
||||
|
||||
.nc-icon-jiesuanzhanghu1:before {
|
||||
content: "\e918";
|
||||
}
|
||||
|
||||
.nc-icon-zhanghuguanli:before {
|
||||
content: "\e917";
|
||||
}
|
||||
|
||||
.nc-icon-banbenhao:before {
|
||||
content: "\e8ff";
|
||||
}
|
||||
|
||||
.nc-icon-shangjiashoujiduan:before {
|
||||
content: "\e8fd";
|
||||
}
|
||||
|
||||
.nc-icon-xinxi:before {
|
||||
content: "\e900";
|
||||
}
|
||||
|
||||
.nc-icon-a-gongyingshangzhangdanpc30:before {
|
||||
content: "\e771";
|
||||
}
|
||||
|
||||
.nc-icon-a-jifenshangchengzhangdanpc30:before {
|
||||
content: "\e772";
|
||||
}
|
||||
|
||||
.nc-icon-a-shangchengzhangdanpc30:before {
|
||||
content: "\e773";
|
||||
}
|
||||
|
||||
.nc-icon-a-chongzhizhangdanpc30:before {
|
||||
content: "\e774";
|
||||
}
|
||||
|
||||
.nc-icon-gongzuotai:before {
|
||||
content: "\e8ec";
|
||||
}
|
||||
|
||||
.nc-icon-shoujiV6xx1:before {
|
||||
content: "\e8ed";
|
||||
}
|
||||
|
||||
.nc-icon-shoujiV6xxmm:before {
|
||||
content: "\e8fe";
|
||||
}
|
||||
|
||||
.nc-icon-xuanfuanniu:before {
|
||||
content: "\e8e5";
|
||||
}
|
||||
|
||||
.nc-icon-pintuanguanli:before {
|
||||
content: "\e8e0";
|
||||
}
|
||||
|
||||
.nc-icon-huodongliebiao1:before {
|
||||
content: "\e8e1";
|
||||
}
|
||||
|
||||
.nc-icon-pintuanliebiao:before {
|
||||
content: "\e8e2";
|
||||
}
|
||||
|
||||
.nc-icon-pintuandingdan:before {
|
||||
content: "\e8e3";
|
||||
}
|
||||
|
||||
.nc-icon-pintuanpeizhi:before {
|
||||
content: "\e8e4";
|
||||
}
|
||||
|
||||
.nc-icon-xia:before {
|
||||
content: "\e8de";
|
||||
}
|
||||
|
||||
.nc-icon-shang:before {
|
||||
content: "\e8df";
|
||||
}
|
||||
|
||||
.nc-icon-shoujiV6xx:before {
|
||||
content: "\e7a1";
|
||||
}
|
||||
|
||||
.nc-icon-ditumichi:before {
|
||||
content: "\e8ca";
|
||||
}
|
||||
|
||||
.nc-icon-qiehuanV6xx:before {
|
||||
content: "\e8eb";
|
||||
}
|
||||
|
||||
.nc-icon-dingdanbianhaoV6xx:before {
|
||||
content: "\e8ea";
|
||||
}
|
||||
|
||||
.nc-icon-dingdanbianhaoV6mm:before {
|
||||
content: "\e8e9";
|
||||
}
|
||||
|
||||
.nc-icon-dianpuzhandianV6xx2:before {
|
||||
content: "\e8e6";
|
||||
}
|
||||
|
||||
.nc-icon-huocheV6mm:before {
|
||||
content: "\e8e7";
|
||||
}
|
||||
|
||||
.nc-icon-huocheV6xx:before {
|
||||
content: "\e8e8";
|
||||
}
|
||||
|
||||
.nc-icon-wannengbiaodanV6xx:before {
|
||||
content: "\e8d9";
|
||||
}
|
||||
|
||||
.nc-icon-shujudaochuV6xx:before {
|
||||
content: "\e8da";
|
||||
}
|
||||
|
||||
.nc-icon-shujudaochuV6xx-1:before {
|
||||
content: "\e8db";
|
||||
}
|
||||
|
||||
.nc-icon-dayinjiV6xx:before {
|
||||
content: "\e8dc";
|
||||
}
|
||||
|
||||
.nc-icon-dayinV6xx:before {
|
||||
content: "\e8dd";
|
||||
}
|
||||
|
||||
.nc-icon-fenzuguanliV6xx:before {
|
||||
content: "\e8d6";
|
||||
}
|
||||
|
||||
.nc-icon-shangpinliebiaoV6xx:before {
|
||||
content: "\e8d7";
|
||||
}
|
||||
|
||||
.nc-icon-dingdanliebiaoV6xx:before {
|
||||
content: "\e8d4";
|
||||
}
|
||||
|
||||
.nc-icon-tuikuanV6xx2:before {
|
||||
content: "\e8d8";
|
||||
}
|
||||
|
||||
.nc-icon-jifenshangchengV6xx:before {
|
||||
content: "\e8d5";
|
||||
}
|
||||
|
||||
.nc-icon-chakandituV6xx:before {
|
||||
content: "\e8d2";
|
||||
}
|
||||
|
||||
.nc-icon-a-peisongguanliPC30:before {
|
||||
content: "\e6ed";
|
||||
}
|
||||
|
||||
.nc-icon-a-tongchengpeisongPC30:before {
|
||||
content: "\e6ec";
|
||||
}
|
||||
|
||||
.nc-icon-a-wuliupeisongPC30:before {
|
||||
content: "\e6ee";
|
||||
}
|
||||
|
||||
.nc-icon-a-shangjiapeisongPC30:before {
|
||||
content: "\e6f2";
|
||||
}
|
||||
|
||||
.nc-icon-xianshiV6mm:before {
|
||||
content: "\e8ac";
|
||||
}
|
||||
|
||||
.nc-icon-a-dianneifenrun34:before {
|
||||
content: "\e811";
|
||||
}
|
||||
|
||||
.nc-icon-xiaochengxu:before {
|
||||
content: "\e8a8";
|
||||
}
|
||||
|
||||
.nc-icon-qianV6xx:before {
|
||||
content: "\e784";
|
||||
}
|
||||
|
||||
.nc-icon-mimaV6xx:before {
|
||||
content: "\e8a6";
|
||||
}
|
||||
|
||||
.nc-icon-yanzhengmaV6xx:before {
|
||||
content: "\e8a7";
|
||||
}
|
||||
|
||||
.nc-icon-bianjiV6xx2:before {
|
||||
content: "\e8a4";
|
||||
}
|
||||
|
||||
.nc-icon-fenxiangV6mm-1:before {
|
||||
content: "\e89c";
|
||||
}
|
||||
|
||||
.nc-icon-a-Group1036V6xx:before {
|
||||
content: "\e77b";
|
||||
}
|
||||
|
||||
.nc-icon-shanchu-yuangaiV6xx:before {
|
||||
content: "\e6eb";
|
||||
}
|
||||
|
||||
.nc-icon-hezuogonghuoshangV6xx:before {
|
||||
content: "\e88b";
|
||||
}
|
||||
|
||||
.nc-icon-hezuodianpu:before {
|
||||
content: "\e85b";
|
||||
}
|
||||
|
||||
.nc-icon-gongyingshangxitong:before {
|
||||
content: "\e852";
|
||||
}
|
||||
|
||||
.nc-icon-shangchengxitong:before {
|
||||
content: "\e858";
|
||||
}
|
||||
|
||||
.nc-icon-fenzhangshezhi:before {
|
||||
content: "\e843";
|
||||
}
|
||||
|
||||
.nc-icon-xuanpinpingtai:before {
|
||||
content: "\e845";
|
||||
}
|
||||
|
||||
.nc-icon-a-Maskgroup:before {
|
||||
content: "\e840";
|
||||
}
|
||||
|
||||
.nc-icon-fenzhangguanli:before {
|
||||
content: "\e84b";
|
||||
}
|
||||
|
||||
.nc-icon-gongyingshangdingdan:before {
|
||||
content: "\e84d";
|
||||
}
|
||||
|
||||
.nc-icon-gongyingshangshangpin:before {
|
||||
content: "\e84e";
|
||||
}
|
||||
|
||||
.nc-icon-shuaxinV6mm2:before {
|
||||
content: "\e889";
|
||||
}
|
||||
|
||||
.nc-icon-yitiaohuo:before {
|
||||
content: "\e888";
|
||||
}
|
||||
|
||||
.nc-icon-shangchengdingdan:before {
|
||||
content: "\e837";
|
||||
}
|
||||
|
||||
.nc-icon-shangchengshangpin:before {
|
||||
content: "\e83f";
|
||||
}
|
||||
|
||||
.nc-icon-gouwudaiV6xx1:before {
|
||||
content: "\e886";
|
||||
}
|
||||
|
||||
.nc-icon-dianpuV6xx1:before {
|
||||
content: "\e880";
|
||||
}
|
||||
|
||||
.nc-icon-youhuiquanV6xx2:before {
|
||||
content: "\e87a";
|
||||
}
|
||||
|
||||
.nc-icon-yinhangka2:before {
|
||||
content: "\e83e";
|
||||
}
|
||||
|
||||
.nc-icon-huiyuantixian:before {
|
||||
content: "\e839";
|
||||
}
|
||||
|
||||
.nc-icon-a-Financing-tworongzi2:before {
|
||||
content: "\e825";
|
||||
}
|
||||
|
||||
.nc-icon-a-Weixin-marketweixindianshang:before {
|
||||
content: "\e821";
|
||||
}
|
||||
|
||||
.nc-icon-a-Repairbianji:before {
|
||||
content: "\e818";
|
||||
}
|
||||
|
||||
.nc-icon-a-Diskcipan:before {
|
||||
content: "\e81c";
|
||||
}
|
||||
|
||||
.nc-icon-a-Historylishijilu:before {
|
||||
content: "\e81b";
|
||||
}
|
||||
|
||||
.nc-icon-a-Deliveryjiaohuo:before {
|
||||
content: "\e81a";
|
||||
}
|
||||
|
||||
.nc-icon-dianpuV6xx:before {
|
||||
content: "\e871";
|
||||
}
|
||||
|
||||
.nc-icon-Frame:before {
|
||||
content: "\e816";
|
||||
}
|
||||
|
||||
.nc-icon-zhifujianshu1:before {
|
||||
content: "\e815";
|
||||
}
|
||||
|
||||
.nc-icon-jiagoushuliang:before {
|
||||
content: "\e814";
|
||||
}
|
||||
|
||||
.nc-icon-xiadanshu:before {
|
||||
content: "\e813";
|
||||
}
|
||||
|
||||
.nc-icon-shangpinliulanliang:before {
|
||||
content: "\e812";
|
||||
}
|
||||
|
||||
.nc-icon-fenxiaodengji:before {
|
||||
content: "\e807";
|
||||
}
|
||||
|
||||
.nc-icon-fenxiaoguanli:before {
|
||||
content: "\e809";
|
||||
}
|
||||
|
||||
.nc-icon-dianzimiandan:before {
|
||||
content: "\e806";
|
||||
}
|
||||
|
||||
.nc-icon-fenxiaodingdan:before {
|
||||
content: "\e804";
|
||||
}
|
||||
|
||||
.nc-icon-fenxiaoshang:before {
|
||||
content: "\e808";
|
||||
}
|
||||
|
||||
.nc-icon-hexiaoyuan:before {
|
||||
content: "\e805";
|
||||
}
|
||||
|
||||
.nc-icon-shangpintongji:before {
|
||||
content: "\e80a";
|
||||
}
|
||||
|
||||
.nc-icon-fenxiaogaikuang:before {
|
||||
content: "\e802";
|
||||
}
|
||||
|
||||
.nc-icon-fenxiaoshangpin:before {
|
||||
content: "\e801";
|
||||
}
|
||||
|
||||
.nc-icon-yingyongliebiao:before {
|
||||
content: "\e80b";
|
||||
}
|
||||
|
||||
.nc-icon-huodongliebiao:before {
|
||||
content: "\e80c";
|
||||
}
|
||||
|
||||
.nc-icon-hexiaojilu:before {
|
||||
content: "\e80d";
|
||||
}
|
||||
|
||||
.nc-icon-piliangfahuo:before {
|
||||
content: "\e80e";
|
||||
}
|
||||
|
||||
.nc-icon-fenxiaoshezhi:before {
|
||||
content: "\e80f";
|
||||
}
|
||||
|
||||
.nc-icon-dianpu:before {
|
||||
content: "\e800";
|
||||
}
|
||||
|
||||
.nc-icon-caozuorizhi1:before {
|
||||
content: "\e7ef";
|
||||
}
|
||||
|
||||
.nc-icon-dingdanliebiao:before {
|
||||
content: "\e7f0";
|
||||
}
|
||||
|
||||
.nc-icon-hexiaoguanli:before {
|
||||
content: "\e7ee";
|
||||
}
|
||||
|
||||
.nc-icon-fapiaoguanli:before {
|
||||
content: "\e7ed";
|
||||
}
|
||||
|
||||
.nc-icon-dingdanshezhi:before {
|
||||
content: "\e7ea";
|
||||
}
|
||||
|
||||
.nc-icon-huiyuanbiaoqian:before {
|
||||
content: "\e7eb";
|
||||
}
|
||||
|
||||
.nc-icon-huishouzhan:before {
|
||||
content: "\e7db";
|
||||
}
|
||||
|
||||
.nc-icon-jiesuanzhanghu:before {
|
||||
content: "\e7f1";
|
||||
}
|
||||
|
||||
.nc-icon-guanliyuan1:before {
|
||||
content: "\e7e6";
|
||||
}
|
||||
|
||||
.nc-icon-huiyuanliebiao:before {
|
||||
content: "\e7da";
|
||||
}
|
||||
|
||||
.nc-icon-shangpinfenlei:before {
|
||||
content: "\e7dd";
|
||||
}
|
||||
|
||||
.nc-icon-jiaoseguanli:before {
|
||||
content: "\e7e3";
|
||||
}
|
||||
|
||||
.nc-icon-shangpinliebiao:before {
|
||||
content: "\e7e8";
|
||||
}
|
||||
|
||||
.nc-icon-shangpinpingjia:before {
|
||||
content: "\e7e9";
|
||||
}
|
||||
|
||||
.nc-icon-dianpushezhi:before {
|
||||
content: "\e7e7";
|
||||
}
|
||||
|
||||
.nc-icon-sucaiguanli1:before {
|
||||
content: "\e7f2";
|
||||
}
|
||||
|
||||
.nc-icon-tixianjilu:before {
|
||||
content: "\e7e4";
|
||||
}
|
||||
|
||||
.nc-icon-xiaopiaodayin:before {
|
||||
content: "\e7f3";
|
||||
}
|
||||
|
||||
.nc-icon-shangjiadizhiku:before {
|
||||
content: "\e7e1";
|
||||
}
|
||||
|
||||
.nc-icon-shujudaochu:before {
|
||||
content: "\e7de";
|
||||
}
|
||||
|
||||
.nc-icon-shangpincanshu:before {
|
||||
content: "\e7e0";
|
||||
}
|
||||
|
||||
.nc-icon-tuikuanweiquan:before {
|
||||
content: "\e7f4";
|
||||
}
|
||||
|
||||
.nc-icon-weiyemian:before {
|
||||
content: "\e7f5";
|
||||
}
|
||||
|
||||
.nc-icon-shouyezhuangxiu:before {
|
||||
content: "\e7d9";
|
||||
}
|
||||
|
||||
.nc-icon-xianshizhekou:before {
|
||||
content: "\e7d8";
|
||||
}
|
||||
|
||||
.nc-icon-youhuiquan:before {
|
||||
content: "\e7d7";
|
||||
}
|
||||
|
||||
.nc-icon-zichangaikuang:before {
|
||||
content: "\e7d6";
|
||||
}
|
||||
|
||||
.nc-icon-yunfeimoban:before {
|
||||
content: "\e7f6";
|
||||
}
|
||||
|
||||
.nc-icon-daifukuandingdan:before {
|
||||
content: "\e7fa";
|
||||
}
|
||||
|
||||
.nc-icon-cangkushangpinshuliang:before {
|
||||
content: "\e7f9";
|
||||
}
|
||||
|
||||
.nc-icon-daishouhuodingdan:before {
|
||||
content: "\e7f8";
|
||||
}
|
||||
|
||||
.nc-icon-tuikuan:before {
|
||||
content: "\e7f7";
|
||||
}
|
||||
|
||||
.nc-icon-tuikuandingdan:before {
|
||||
content: "\e7fb";
|
||||
}
|
||||
|
||||
.nc-icon-chushoushangpinshuliang:before {
|
||||
content: "\e7fc";
|
||||
}
|
||||
|
||||
.nc-icon-daifahuodingdan:before {
|
||||
content: "\e7fd";
|
||||
}
|
||||
|
||||
.nc-icon-dingdanliang:before {
|
||||
content: "\e7fe";
|
||||
}
|
||||
|
||||
.nc-icon-xiaoshoue:before {
|
||||
content: "\e7ff";
|
||||
}
|
||||
|
||||
.nc-icon-paihangbangV6xx1:before {
|
||||
content: "\e7e2";
|
||||
}
|
||||
|
||||
.nc-icon-bangdanguanliV6xx:before {
|
||||
content: "\e86d";
|
||||
}
|
||||
|
||||
.nc-icon-bangdanshezhiV6xx:before {
|
||||
content: "\e86e";
|
||||
}
|
||||
|
||||
.nc-icon-zhuanzhangV6xx-1:before {
|
||||
content: "\e86a";
|
||||
}
|
||||
|
||||
.nc-icon-qingliV6xx:before {
|
||||
content: "\e865";
|
||||
}
|
||||
|
||||
@ -401,3 +401,12 @@ export function getTablePageStorage(where: any = {}) {
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
// 距离显示
|
||||
|
||||
export function distance(distance: string | number): string {
|
||||
const dist = typeof distance === 'string' ? parseFloat(distance) : distance;
|
||||
if (isNaN(dist)) return distance.toString();
|
||||
return dist < 1 ? parseInt((dist * 1000).toString()) + 'm' : dist.toFixed(1) + 'km'
|
||||
}
|
||||
@ -134,6 +134,9 @@ export const createPolygon = (map: any, geometriesData: any) => {
|
||||
* @param key
|
||||
*/
|
||||
export const deleteGeometry = (key: string) => {
|
||||
if (!geometry[key]) {
|
||||
return
|
||||
}
|
||||
geometry[key].graphical.remove(key)
|
||||
geometry[key].editor.delete()
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user