mirror of
https://gitee.com/niucloud-team/niucloud-admin.git
synced 2026-03-29 16:50:52 +00:00
up admin
This commit is contained in:
parent
52e3ea6cc5
commit
b2a30f1172
@ -35,7 +35,8 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped></style>
|
||||||
|
<style>
|
||||||
.el-page-header__header .el-page-header__left .el-page-header__content{
|
.el-page-header__header .el-page-header__left .el-page-header__content{
|
||||||
font-size: 14px !important;
|
font-size: 14px !important;
|
||||||
font-weight: 500 !important;
|
font-weight: 500 !important;
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export function getSmsList() {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function getSmsInfo(sms_type: string) {
|
export function getSmsInfo(sms_type: string) {
|
||||||
return request.get(`notice/notice/sms/${ sms_type }`,)
|
return request.get(`notice/notice/sms/${ sms_type }`)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -151,7 +151,7 @@ export function deleteSign(username: string, params: Record<string, any>) {
|
|||||||
* @param params
|
* @param params
|
||||||
*/
|
*/
|
||||||
export function editAccount(username: string, params: Record<string, any>) {
|
export function editAccount(username: string, params: Record<string, any>) {
|
||||||
return request.post(`notice/niusms/account/edit/${username}`, params, { showSuccessMessage: true });
|
return request.post(`notice/niusms/account/edit/${username}`, params, { showSuccessMessage: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -162,7 +162,7 @@ export function refreshPrinterToken(printer_id: number) {
|
|||||||
return request.put(`sys/printer/refreshtoken/${ printer_id }`, {}, {
|
return request.put(`sys/printer/refreshtoken/${ printer_id }`, {}, {
|
||||||
showErrorMessage: true,
|
showErrorMessage: true,
|
||||||
showSuccessMessage: true
|
showSuccessMessage: true
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -171,7 +171,7 @@ export function refreshPrinterToken(printer_id: number) {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function testPrint(printer_id: number) {
|
export function testPrint(printer_id: number) {
|
||||||
return request.put(`sys/printer/testprint/${ printer_id }`, {},{ showErrorMessage: true, showSuccessMessage: true });
|
return request.put(`sys/printer/testprint/${ printer_id }`, {}, { showErrorMessage: true, showSuccessMessage: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -573,21 +573,21 @@ export function setPatConfig(params: Record<string, any>) {
|
|||||||
/**
|
/**
|
||||||
* 刷新菜单
|
* 刷新菜单
|
||||||
*/
|
*/
|
||||||
export function menuRefresh(params: Record<string, any>) {
|
export function menuRefresh() {
|
||||||
return request.post(`sys/menu/refresh`, {})
|
return request.post(`sys/menu/refresh`, {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理数据字段缓存
|
* 清理数据字段缓存
|
||||||
*/
|
*/
|
||||||
export function clearSchemaCache(params: Record<string, any>) {
|
export function clearSchemaCache() {
|
||||||
return request.post(`sys/schema/clear`, {}, { showSuccessMessage: true })
|
return request.post(`sys/schema/clear`, {}, { showSuccessMessage: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理缓存
|
* 清理缓存
|
||||||
*/
|
*/
|
||||||
export function clearCache(params: Record<string, any>) {
|
export function clearCache() {
|
||||||
return request.post(`sys/cache/clear`, {}, { showSuccessMessage: true })
|
return request.post(`sys/cache/clear`, {}, { showSuccessMessage: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,3 +734,11 @@ export function getInstallConfig() {
|
|||||||
export function getQrcode(params: Record<string, any>) {
|
export function getQrcode(params: Record<string, any>) {
|
||||||
return request.get(`sys/qrcode`, { params, showErrorMessage: false })
|
return request.get(`sys/qrcode`, { params, showErrorMessage: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验消息队列
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function checkJobStatus() {
|
||||||
|
return request.get(`sys/job`)
|
||||||
|
}
|
||||||
|
|||||||
@ -377,7 +377,7 @@ const dialogCancel = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const cloudBuildCheckDirFn = () => {
|
const cloudBuildCheckDirFn = () => {
|
||||||
window.open('https://doc.niucloud.com/v6.html?keywords=/chang-jian-wen-ti-chu-li/er-shi-wu-3001-sheng-7ea7-yun-bian-yi-mu-lu-du-xie-quan-xian-zhuang-tai-bu-tong-guo-ru-he-chu-li')
|
window.open('https://doc.press.niucloud.com/php/v6-shop/use/chang-jian-wen-ti-chu-li/er-shi-wu-3001-sheng-7ea7-yun-bian-yi-mu-lu-du-xie-quan-xian-zhuang-tai-bu-tong-guo-ru-he-chu-li.html')
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => showDialog.value, () => {
|
watch(() => showDialog.value, () => {
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, defineProps, nextTick } from "vue"
|
import { computed, ref, defineProps, nextTick } from "vue"
|
||||||
import { t } from "@/lang"
|
import { t } from "@/lang"
|
||||||
|
import { ElMessage } from "element-plus"
|
||||||
import { getAppVersionList, getFrameworkVersionList } from "@/app/api/module"
|
import { getAppVersionList, getFrameworkVersionList } from "@/app/api/module"
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@ -34,37 +34,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="step == 2">
|
<div v-show="step == 2">
|
||||||
<el-steps :active="numberOfSteps" align-center class="number-of-steps" process-status="process" v-if="!errorDialog && active != 'complete'">
|
<el-steps :active="numberOfSteps" align-center class="number-of-steps" process-status="process">
|
||||||
<el-step :title="t('testDirectoryPermissions')" />
|
<el-step :title="t('testDirectoryPermissions')" />
|
||||||
<el-step :title="t('upgrade.option')" />
|
<el-step :title="t('upgrade.option')" />
|
||||||
<el-step :title="t('startUpgrade')" />
|
<el-step :title="t('startUpgrade')" />
|
||||||
<el-step :title="t('upgradeEnd')" />
|
<el-step :title="t('upgradeEnd')" />
|
||||||
</el-steps>
|
</el-steps>
|
||||||
<div class="h-[400px]" style="overflow: auto">
|
<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 v-show="active == 'upgrade'">
|
||||||
<div class="flex flex-col" v-if="upgradeCheck && !upgradeTask">
|
<div class="flex flex-col" v-if="upgradeCheck && !upgradeTask">
|
||||||
@ -132,7 +109,6 @@
|
|||||||
<div class="h-[370px] mt-[30px]" v-show="showTerminal && upgradeTask && !errorDialog">
|
<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" />
|
<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>
|
</div>
|
||||||
<!-- 是否备份选择 -->
|
<!-- 是否备份选择 -->
|
||||||
<div class="flex flex-col" v-show="active == 'backup'">
|
<div class="flex flex-col" v-show="active == 'backup'">
|
||||||
@ -156,7 +132,51 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[20px] h-[370px]" v-show="errorDialog">
|
|
||||||
|
</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>
|
||||||
|
<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('升级失败')">
|
<el-result icon="error" :title="t('升级失败')">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<img src="@/app/assets/images/error_icon.png" alt="" />
|
<img src="@/app/assets/images/error_icon.png" alt="" />
|
||||||
@ -170,23 +190,6 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-result>
|
</el-result>
|
||||||
</div>
|
</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>
|
|
||||||
</template>
|
|
||||||
</el-result>
|
|
||||||
<!-- <el-alert :title="t('upgrade.upgradeCompleteTips')" type="error" :closable="false" v-show="upgradeTask && upgradeTask.executed && !upgradeTask.executed.includes('cloudBuild')"/> -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@ -226,6 +229,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<el-dialog v-model="dialogUpgradePrompt" title="升级提示" width="500" :before-close="handleClose">
|
||||||
|
<p>您当前使用的{{applicationType == 'app' ? '应用' : '插件'}}版本是 {{applicationVersion}},若想升级到 {{newApplicationVersion}} 版本,需要先把框架从 v{{frameworkVersion}} 升级到 v{{ newFrameworkVersion }} 。</p>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span>如需升级框架,请点击升级框架操作。</span>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="upgradePromptConfirm">升级框架</el-button>
|
||||||
|
<el-button @click="dialogUpgradePrompt = false">取消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -354,8 +369,6 @@ const getUpgradeTaskFn = () => {
|
|||||||
errorMsg.value = item
|
errorMsg.value = item
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
errorDialog.value = true
|
|
||||||
showTerminal.value = false
|
|
||||||
if (upgradeTimer) {
|
if (upgradeTimer) {
|
||||||
clearInterval(upgradeTimer)
|
clearInterval(upgradeTimer)
|
||||||
upgradeTimer = null
|
upgradeTimer = null
|
||||||
@ -365,12 +378,17 @@ const getUpgradeTaskFn = () => {
|
|||||||
// 恢复完毕
|
// 恢复完毕
|
||||||
if (data.step == 'restoreComplete') {
|
if (data.step == 'restoreComplete') {
|
||||||
flashInterval && clearInterval(flashInterval)
|
flashInterval && clearInterval(flashInterval)
|
||||||
|
step.value = 3
|
||||||
|
active.value = 'fail'
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 升级完成
|
// 升级完成
|
||||||
if (data.step == 'upgradeComplete') {
|
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'
|
active.value = 'complete'
|
||||||
showTerminal.value = false
|
|
||||||
numberOfSteps.value = 4
|
numberOfSteps.value = 4
|
||||||
notificationEl && notificationEl.close()
|
notificationEl && notificationEl.close()
|
||||||
emits('complete')
|
emits('complete')
|
||||||
@ -379,22 +397,29 @@ const getUpgradeTaskFn = () => {
|
|||||||
upgradeTimer = null
|
upgradeTimer = null
|
||||||
}
|
}
|
||||||
timeloading.value = false
|
timeloading.value = false
|
||||||
clearUpgradeTask()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
numberOfSteps.value = 2
|
numberOfSteps.value = 2
|
||||||
active.value = 'upgrade'
|
active.value = 'upgrade'
|
||||||
executeUpgradeFn()
|
executeUpgradeFn()
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getUpgradeTaskFn()
|
getUpgradeTaskFn()
|
||||||
|
|
||||||
|
const upgradePromptConfirm = ()=>{
|
||||||
|
dialogUpgradePrompt.value = false
|
||||||
|
open('niucloud-admin')
|
||||||
|
}
|
||||||
|
|
||||||
const isBack = ref(false)
|
const isBack = ref(false)
|
||||||
const handleBack = () => {
|
const handleBack = () => {
|
||||||
active.value = 'upgrade'
|
active.value = 'upgrade'
|
||||||
isBack.value = true
|
isBack.value = true
|
||||||
showTerminal.value = true
|
showTerminal.value = true
|
||||||
errorDialog.value = false // 隐藏错误弹窗
|
errorDialog.value = false // 隐藏错误弹窗
|
||||||
|
step.value = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
const formatUpgradeDuration = computed(() => {
|
const formatUpgradeDuration = computed(() => {
|
||||||
@ -505,8 +530,11 @@ const upgradeAddonFn = () => {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const dialogUpgradePrompt = ref(false)
|
||||||
const open = (addonKey: string = '', callback = null) => {
|
const applicationVersion = ref('')
|
||||||
|
const newApplicationVersion = ref('')
|
||||||
|
const applicationType = ref('app')
|
||||||
|
const open = (addonKey: string = '', callback = null, otherData: any = {}) => {
|
||||||
errorDialog.value = false // 隐藏错误弹窗
|
errorDialog.value = false // 隐藏错误弹窗
|
||||||
if (upgradeTask.value) {
|
if (upgradeTask.value) {
|
||||||
ElMessage({ message: '已有正在执行中的升级任务', type: 'error' })
|
ElMessage({ message: '已有正在执行中的升级任务', type: 'error' })
|
||||||
@ -517,7 +545,10 @@ const open = (addonKey: string = '', callback = null) => {
|
|||||||
if (callback) callback()
|
if (callback) callback()
|
||||||
} else {
|
} else {
|
||||||
if (addonKey && addonKey.indexOf('niucloud-admin') == -1 && frameworkVersion.value != newFrameworkVersion.value) {
|
if (addonKey && addonKey.indexOf('niucloud-admin') == -1 && frameworkVersion.value != newFrameworkVersion.value) {
|
||||||
ElMessage({ message: '存在新版本框架,请先升级框架', type: 'error' })
|
applicationVersion.value = otherData.install_info.version
|
||||||
|
newApplicationVersion.value = otherData.version
|
||||||
|
applicationType.value = otherData.type
|
||||||
|
dialogUpgradePrompt.value = true
|
||||||
if (callback) callback()
|
if (callback) callback()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -646,6 +677,12 @@ const cloudBuildError = (event: string) => {
|
|||||||
getUpgradeTaskFn()
|
getUpgradeTaskFn()
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
case 'cloud_build_error_rollback':
|
||||||
|
upgradeUserOperate(event).then(() => {
|
||||||
|
handleBack()
|
||||||
|
executeUpgradeFn()
|
||||||
|
})
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,5 +32,5 @@
|
|||||||
"safeModeTips": "安全模式下,消息包为纯密文,需要开发者加密和解密,安全系数高",
|
"safeModeTips": "安全模式下,消息包为纯密文,需要开发者加密和解密,安全系数高",
|
||||||
"wechatBaseUri": "借权域名",
|
"wechatBaseUri": "借权域名",
|
||||||
"wechatBaseUriPlaceholder": "",
|
"wechatBaseUriPlaceholder": "",
|
||||||
"wechatBaseUriTips": "默认留空,填写后将替换https://open.weixin.gg.com/获取授权!"
|
"wechatBaseUriTips": "默认留空,填写后将替换https://open.weixin.qq.com/获取授权!"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -243,7 +243,7 @@
|
|||||||
"carouselSearchSwiperSet": "轮播图设置",
|
"carouselSearchSwiperSet": "轮播图设置",
|
||||||
"carouselSearchSwiperControl": "展示开关",
|
"carouselSearchSwiperControl": "展示开关",
|
||||||
"carouselSearchSwiperInterval": "切换间隔 / 秒",
|
"carouselSearchSwiperInterval": "切换间隔 / 秒",
|
||||||
"carouselSearchSwiperTips": "建议上传尺寸相同的图片,推荐尺寸750*350;鼠标拖拽可调整图片顺序",
|
"carouselSearchSwiperTips": "建议上传尺寸相同的图片,推荐尺寸750*580;鼠标拖拽可调整图片顺序",
|
||||||
"carouselSearchTabStyle": "选项卡样式",
|
"carouselSearchTabStyle": "选项卡样式",
|
||||||
"carouselSearchStyle": "搜索框样式",
|
"carouselSearchStyle": "搜索框样式",
|
||||||
"noColor": "常规颜色",
|
"noColor": "常规颜色",
|
||||||
|
|||||||
@ -244,7 +244,7 @@
|
|||||||
"carouselSearchSwiperSet": "轮播图设置",
|
"carouselSearchSwiperSet": "轮播图设置",
|
||||||
"carouselSearchSwiperControl": "展示开关",
|
"carouselSearchSwiperControl": "展示开关",
|
||||||
"carouselSearchSwiperInterval": "切换间隔 / 秒",
|
"carouselSearchSwiperInterval": "切换间隔 / 秒",
|
||||||
"carouselSearchSwiperTips": "建议上传尺寸相同的图片,推荐尺寸750*350;鼠标拖拽可调整图片顺序",
|
"carouselSearchSwiperTips": "建议上传尺寸相同的图片,推荐尺寸750*580;鼠标拖拽可调整图片顺序",
|
||||||
"carouselSearchTabStyle": "选项卡样式",
|
"carouselSearchTabStyle": "选项卡样式",
|
||||||
"carouselSearchStyle": "搜索框样式",
|
"carouselSearchStyle": "搜索框样式",
|
||||||
"noColor": "常规颜色",
|
"noColor": "常规颜色",
|
||||||
|
|||||||
@ -2,6 +2,5 @@
|
|||||||
"isCaptcha": "是否启用验证码",
|
"isCaptcha": "是否启用验证码",
|
||||||
"bgImg": "登录页广告图",
|
"bgImg": "登录页广告图",
|
||||||
"admin": "平台端",
|
"admin": "平台端",
|
||||||
"adminBgImgTip": "建议上传尺寸为450*400px",
|
"adminBgImgTip": "建议上传尺寸为450*400px"
|
||||||
"siteBgImgTip": "建议上传尺寸为620*980px"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
"mobileOrUsernameNoEmpty": "普通注册方式至少需启用一种",
|
"mobileOrUsernameNoEmpty": "普通注册方式至少需启用一种",
|
||||||
"loginPageSet": "界面设置",
|
"loginPageSet": "界面设置",
|
||||||
"bgUrl": "背景图",
|
"bgUrl": "背景图",
|
||||||
"bgUrlPlaceholder": "建议图片尺寸:750*669像素;图片格式:jpg、png、jpeg",
|
"bgUrlPlaceholder": "前台快捷登录/注册页的背景图,建议图片尺寸:750*669像素;图片格式:jpg、png、jpeg",
|
||||||
"desc": "描述",
|
"desc": "描述",
|
||||||
"descPlaceholder": "请输入描述"
|
"descPlaceholder": "请输入描述"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,12 +30,8 @@
|
|||||||
"customerServiceCode": "客服二维码",
|
"customerServiceCode": "客服二维码",
|
||||||
"contactsTel": "联系电话",
|
"contactsTel": "联系电话",
|
||||||
"contactsTelPlaceholder": "请输入联系电话",
|
"contactsTelPlaceholder": "请输入联系电话",
|
||||||
"logoPlaceholder": "建议图片尺寸:210*30像素;图片格式:jpg、png、jpeg。",
|
"logoPlaceholder": "管理系统左上角的长方形Logo,建议图片尺寸:210*30像素;图片格式:jpg、png、jpeg。",
|
||||||
"iconPlaceholder": "建议图片尺寸:100*100像素;图片格式:jpg、png、jpeg。",
|
"iconPlaceholder": "管理系统左上角的正方形Logo,建议图片尺寸:100*100像素;图片格式:jpg、png、jpeg。",
|
||||||
"siteLoginLogo": "站点登录Logo",
|
|
||||||
"siteLoginLogoTips": "站点端登录Logo,建议图片尺寸:132*40像素;图片格式:jpg、png、jpeg。",
|
|
||||||
"siteLoginBgImg": "站点登录背景图",
|
|
||||||
"siteLoginBgImgTips": "站点端登录背景图,建议图片尺寸:1920*1280像素;图片格式:jpg、png、jpeg。",
|
|
||||||
"metaTitle": "Meta 标题",
|
"metaTitle": "Meta 标题",
|
||||||
"MetaPlaceholder": "请输入Meta 标题",
|
"MetaPlaceholder": "请输入Meta 标题",
|
||||||
"metaDescription": "Meta 描述",
|
"metaDescription": "Meta 描述",
|
||||||
|
|||||||
@ -24,5 +24,6 @@
|
|||||||
"startBackUp": "开始备份",
|
"startBackUp": "开始备份",
|
||||||
"backUpEnd": "备份完成",
|
"backUpEnd": "备份完成",
|
||||||
"remark": "备注",
|
"remark": "备注",
|
||||||
"remarkEmpty": "无"
|
"remarkEmpty": "无",
|
||||||
|
"status": "状态"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<template v-if="Object.keys(marketingList).length">
|
<template v-if="Object.keys(marketingList).length">
|
||||||
|
|
||||||
<template v-for="(item, index) in marketingList" :key="index + 'b'">
|
<template v-for="(item, index) in marketingList" :key="index + 'b'">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center" v-if="item.list.length > 0">
|
||||||
<span class="text-page-title">{{ item.title }}</span>
|
<span class="text-page-title">{{ item.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ const loading = ref(true)
|
|||||||
const getMarketingList = async () => {
|
const getMarketingList = async () => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
getMarketingList()
|
// getMarketingList()
|
||||||
|
|
||||||
const toLink = (item: any) => {
|
const toLink = (item: any) => {
|
||||||
if (item.url) {
|
if (item.url) {
|
||||||
|
|||||||
@ -24,10 +24,10 @@
|
|||||||
|
|
||||||
<el-form-item :label="t('parentMenu')" prop="parent_key">
|
<el-form-item :label="t('parentMenu')" prop="parent_key">
|
||||||
<el-tree-select class="input-width" v-if="formData.addon != ''" v-model="formData.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" />
|
:render-after-expand="false" />
|
||||||
<el-tree-select class="input-width" v-else v-model="formData.parent_key"
|
<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" />
|
:render-after-expand="false" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
@ -183,6 +183,38 @@ const getAddonMenuFn = async (key: any) => {
|
|||||||
addonMenuList.value = data
|
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) => {
|
const addonChange = async (val: any) => {
|
||||||
formData.parent_key = ''
|
formData.parent_key = ''
|
||||||
|
|||||||
@ -54,8 +54,34 @@ let popTitle: string = ''
|
|||||||
// 获取权限数据
|
// 获取权限数据
|
||||||
const menus = ref<Record<string, any>[]>([])
|
const menus = ref<Record<string, any>[]>([])
|
||||||
getAuthMenus({ is_button: 0 }).then((res) => {
|
getAuthMenus({ is_button: 0 }).then((res) => {
|
||||||
menus.value = res.data
|
menus.value = mergeMenuKeyAndAuth(res.data)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const mergeMenuKeyAndAuth = (arr: any) => {
|
||||||
|
// 递归终止条件:非数组直接返回原值
|
||||||
|
if (!Array.isArray(arr)) {
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历数组每个元素,返回新数组
|
||||||
|
return arr.map(item => {
|
||||||
|
// 深拷贝当前对象,避免修改原数据
|
||||||
|
const newItem = { ...item };
|
||||||
|
|
||||||
|
// 1. 如果当前节点有 menu_key 和 auth,执行合并
|
||||||
|
if (newItem.menu_key && Array.isArray(newItem.auth)) {
|
||||||
|
// 注意:menu_key 是字符串,需转为数组后合并(concat 支持非数组参数,会自动包装)
|
||||||
|
newItem.menu_key = newItem.auth.concat(newItem.menu_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 递归处理下一层 children(如果有)
|
||||||
|
if (Array.isArray(newItem.children)) {
|
||||||
|
newItem.children = mergeMenuKeyAndAuth(newItem.children);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newItem;
|
||||||
|
});
|
||||||
|
}
|
||||||
// 全选
|
// 全选
|
||||||
const selectAll = ref(false)
|
const selectAll = ref(false)
|
||||||
const checkStrictly = ref(false)
|
const checkStrictly = ref(false)
|
||||||
@ -71,7 +97,7 @@ watch(selectAll, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const handleCheckChange = debounce((e) => {
|
const handleCheckChange = debounce((e) => {
|
||||||
formData.rules = treeRef.value.getCheckedKeys()
|
formData.rules = treeRef.value.getCheckedKeys().flat(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
const menuAction = () => {
|
const menuAction = () => {
|
||||||
@ -145,7 +171,7 @@ const confirm = async (formEl: FormInstance | undefined) => {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
const data = Object.assign({}, formData)
|
const data = Object.assign({}, formData)
|
||||||
data.rules = data.rules.concat(treeRef.value.getHalfCheckedKeys())
|
data.rules = data.rules.concat(treeRef.value.getHalfCheckedKeys().flat(1))
|
||||||
|
|
||||||
save(data).then(res => {
|
save(data).then(res => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
@ -190,7 +216,7 @@ const setFormData = async (row: any = null) => {
|
|||||||
function checked (menuKey:string, data:any, newArr:any) {
|
function checked (menuKey:string, data:any, newArr:any) {
|
||||||
Object.keys(data).forEach((key:string) => {
|
Object.keys(data).forEach((key:string) => {
|
||||||
const item = data[key]
|
const item = data[key]
|
||||||
if (item.menu_key == menuKey) {
|
if (!Array.isArray(item.menu_key) && item.menu_key == menuKey || Array.isArray(item.menu_key) && item.menu_key.indexOf(menuKey) != -1) {
|
||||||
if (!item.children || item.children.length == 0) {
|
if (!item.children || item.children.length == 0) {
|
||||||
newArr.push(item.menu_key)
|
newArr.push(item.menu_key)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
||||||
@ -129,6 +129,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')),
|
||||||
@ -140,9 +141,12 @@ 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(() => {})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -196,10 +196,6 @@ getWeappConfig().then(res => {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
})
|
})
|
||||||
|
|
||||||
getWeappConfig().then(res => {
|
|
||||||
Object.assign(res.data)
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 复制
|
* 复制
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
<div class="w-[700px]">
|
<div class="w-[700px]">
|
||||||
<div class="flex flex-wrap">
|
<div class="flex flex-wrap">
|
||||||
<!-- 多应用切换启动页 -->
|
<!-- 多应用切换启动页 v-if="siteApps.length > 1" -->
|
||||||
<el-button type="primary" @click="showDialog = true" v-if="siteApps.length > 1">{{ t('changePage') }}</el-button>
|
<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>
|
<el-button type="primary" @click="toDecorate()" v-show="page.use_template.action == 'decorate'" class="ml-[12px]">{{ t('decorate') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -59,7 +59,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-dialog v-model="showDialog" :title="t('pageSelectTips')" width="400px" :close-on-press-escape="false" :destroy-on-close="true" :close-on-click-modal="false">
|
<el-dialog v-model="showDialog" :title="t('pageSelectTips')" width="400px" :close-on-press-escape="true" :destroy-on-close="true" :close-on-click-modal="false">
|
||||||
<div class="flex items-start">
|
<div class="flex items-start">
|
||||||
<el-scrollbar class="pl-4 h-[300px] flex-1">
|
<el-scrollbar class="pl-4 h-[300px] flex-1">
|
||||||
<div class="flex flex-wrap">
|
<div class="flex flex-wrap">
|
||||||
|
|||||||
@ -115,7 +115,7 @@
|
|||||||
<div class="mt-[16px] flex justify-end">
|
<div class="mt-[16px] flex justify-end">
|
||||||
<el-pagination v-model:current-page="formMemberList.page" v-model:page-size="formMemberList.limit"
|
<el-pagination v-model:current-page="formMemberList.page" v-model:page-size="formMemberList.limit"
|
||||||
layout="total, sizes, prev, pager, next, jumper" :total="formMemberList.total"
|
layout="total, sizes, prev, pager, next, jumper" :total="formMemberList.total"
|
||||||
@size-change="getFormRecordsMemberFn()" @current-change="getFormRecordsMemberFn()" />
|
@size-change="getFormRecordsMemberFn()" @current-change="getFormRecordsMemberFn" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|||||||
@ -194,7 +194,7 @@ const searchFormRef = ref<FormInstance>()
|
|||||||
|
|
||||||
// 去空操作
|
// 去空操作
|
||||||
watch(() => siteAccountLogTable.searchParam.trade_no, (nval) => {
|
watch(() => siteAccountLogTable.searchParam.trade_no, (nval) => {
|
||||||
siteAccountLogTable.searchParam.trade_no = nval.trim();
|
siteAccountLogTable.searchParam.trade_no = nval.trim()
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,9 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="t('adjustBalance')" prop="adjust">
|
<el-form-item :label="t('adjustBalance')" prop="adjust">
|
||||||
|
<div>
|
||||||
<el-input-number v-model="formData.adjust" clearable :min="0" :max="999999" :placeholder="t('adjustBalancePlaceholder')" @focus="formData.adjust = ''" class="!w-[200px]"/>
|
<el-input-number v-model="formData.adjust" clearable :min="0" :max="999999" :placeholder="t('adjustBalancePlaceholder')" @focus="formData.adjust = ''" class="!w-[200px]"/>
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="t('memo')" prop="memo">
|
<el-form-item :label="t('memo')" prop="memo">
|
||||||
@ -70,7 +72,7 @@ const formRules = computed(() => {
|
|||||||
callback(new Error(t('adjustBalancePlaceholder')))
|
callback(new Error(t('adjustBalancePlaceholder')))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formData.adjust_type == -1 && (parseFloat(formData.balance) - adjust < 0)) {
|
if (formData.adjust_type == -1 && (parseFloat(formData.balance) - adjust) < 0) {
|
||||||
callback(new Error(t('adjustBalanceMaxAccountMessage')))
|
callback(new Error(t('adjustBalanceMaxAccountMessage')))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,9 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="t('adjustPoint')" prop="adjust">
|
<el-form-item :label="t('adjustPoint')" prop="adjust">
|
||||||
|
<div>
|
||||||
<el-input-number v-model="formData.adjust" clearable :min="0" :max="999999" :placeholder="t('adjustPlaceholder')" @focus="formData.adjust = ''" class="!w-[200px]"/>
|
<el-input-number v-model="formData.adjust" clearable :min="0" :max="999999" :placeholder="t('adjustPlaceholder')" @focus="formData.adjust = ''" class="!w-[200px]"/>
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="t('memo')" prop="memo">
|
<el-form-item :label="t('memo')" prop="memo">
|
||||||
@ -72,7 +74,7 @@ const formRules = computed(() => {
|
|||||||
callback(new Error(t('adjustPointPlaceholder')))
|
callback(new Error(t('adjustPointPlaceholder')))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formData.adjust_type == -1 && (parseFloat(formData.point) - adjust < 0)) {
|
if (formData.adjust_type == -1 && (parseFloat(formData.point) - adjust) < 0) {
|
||||||
callback(new Error(t('adjustPointMaxAccountMessage')))
|
callback(new Error(t('adjustPointMaxAccountMessage')))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -279,6 +279,8 @@ const previewPoster = (data: any) => {
|
|||||||
previewDialogVisible.value = true
|
previewDialogVisible.value = true
|
||||||
}
|
}
|
||||||
isRepeat.value = false
|
isRepeat.value = false
|
||||||
|
}).catch(() => {
|
||||||
|
isRepeat.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,24 +11,36 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mb-[10px] flex items-center">
|
<div class="mb-[10px] flex items-center">
|
||||||
<el-checkbox v-model="toggleCheckbox" size="large" class="px-[14px]" @change="toggleChange" :indeterminate="isIndeterminate" />
|
<el-checkbox v-model="toggleCheckbox" size="large" class="px-[14px]" @change="toggleChange" :indeterminate="isIndeterminate" />
|
||||||
<el-button @click="batchDeleteEvent" size="small">{{t("批量删除")}}</el-button>
|
<el-button @click="batchDeleteEvent" size="small">{{ t('批量删除') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="tableData.data" size="large" v-loading="tableData.loading" ref="smsSignListTableRef" @selection-change="handleSelectionChange">
|
<el-table
|
||||||
|
:data="tableData.data"
|
||||||
|
size="large"
|
||||||
|
v-loading="tableData.loading"
|
||||||
|
ref="smsSignListTableRef"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
>
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<span>{{ !tableData.loading ? t("emptyData") : "" }}</span>
|
<span>{{ !tableData.loading ? t('emptyData') : '' }}</span>
|
||||||
</template>
|
</template>
|
||||||
<el-table-column type="selection" :selectable="checkSelectable" width="55" />
|
<el-table-column type="selection" :selectable="checkSelectable" width="55" />
|
||||||
<el-table-column prop="sign" :label="t('签名名称')" min-width="200" />
|
<el-table-column prop="sign" :label="t('签名名称')" min-width="200" />
|
||||||
<el-table-column prop="is_default" :label="t('使用状态')" min-width="120">
|
<el-table-column prop="is_default" :label="t('使用状态')" min-width="120">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div>{{ row.is_default? t('使用中') : t('未使用') }}</div>
|
<div>
|
||||||
|
{{ row.is_default ? t('使用中') : t('未使用') }}
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="auditResultName" :label="t('审核状态')" min-width="200">
|
<el-table-column prop="auditResultName" :label="t('审核状态')" min-width="200">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div>
|
<div>
|
||||||
<div :class="[row.auditResult == 2 ? 'text-green-600' : '']">{{ row.auditResultName }}</div>
|
<div :class="[row.auditResult == 2 ? 'text-green-600' : '']">
|
||||||
<div class="text-red-600" v-if="row.auditResult != 2">{{ row.auditMsg }}</div>
|
{{ row.auditResultName }}
|
||||||
|
</div>
|
||||||
|
<div class="text-red-600" v-if="row.auditResult != 2">
|
||||||
|
{{ row.auditMsg }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -49,9 +61,9 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div class="flex gap-[5px]">
|
<div class="flex gap-[5px]">
|
||||||
<el-tag :type="row.realNameLt == 0 ? 'info' : row.realNameLt == 1 ? 'success' : 'danger'">{{ t("联通") }}</el-tag>
|
<el-tag :type="row.realNameLt == 0 ? 'info' : row.realNameLt == 1 ? 'success' : 'danger'">{{ t('联通') }}</el-tag>
|
||||||
<el-tag :type="row.realNameYd == 0 ? 'info' : row.realNameYd == 1 ? 'success' : 'danger'">{{ t("移动") }}</el-tag>
|
<el-tag :type="row.realNameYd == 0 ? 'info' : row.realNameYd == 1 ? 'success' : 'danger'">{{ t('移动') }}</el-tag>
|
||||||
<el-tag :type="row.realNameDx == 0 ? 'info' : row.realNameDx == 1 ? 'success' : 'danger'">{{ t("电信") }}</el-tag>
|
<el-tag :type="row.realNameDx == 0 ? 'info' : row.realNameDx == 1 ? 'success' : 'danger'">{{ t('电信') }}</el-tag>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -63,51 +75,116 @@
|
|||||||
<el-table-column :label="t('操作')" fixed="right" align="right" min-width="120">
|
<el-table-column :label="t('操作')" fixed="right" align="right" min-width="120">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button type="primary" link @click="selectTemplate(row)" v-if="!row.is_default && row.auditResult == 2">
|
<el-button type="primary" link @click="selectTemplate(row)" v-if="!row.is_default && row.auditResult == 2">
|
||||||
{{ t("使用") }}
|
{{ t('使用') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" link @click="deleteTemplate(row)" v-if="!row.is_default">
|
<el-button type="primary" link @click="deleteTemplate(row)" v-if="!row.is_default">
|
||||||
{{ t("删除") }}
|
{{ t('删除') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<div class="mt-[16px] flex justify-end">
|
<div class="mt-[16px] flex justify-end">
|
||||||
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.limit"
|
<el-pagination
|
||||||
layout="total, sizes, prev, pager, next, jumper" :total="tableData.total" @size-change="loadSignList()" @current-change="loadSignList" />
|
v-model:current-page="tableData.page"
|
||||||
|
v-model:page-size="tableData.limit"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="tableData.total"
|
||||||
|
@size-change="loadSignList()"
|
||||||
|
@current-change="loadSignList"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="visible = false">{{ t("cancel") }}</el-button>
|
<el-button @click="visible = false">{{ t('cancel') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<el-dialog v-model="visibleAdd" :title="t('添加签名')" width="800px" destroy-on-close :close-on-click-modal="false">
|
<el-dialog v-model="visibleAdd" :title="t('添加签名')" width="800px" destroy-on-close :close-on-click-modal="false">
|
||||||
|
<div class="max-h-[600px] overflow-auto">
|
||||||
<el-form label-width="150px" :model="formData" ref="formRef" :rules="formRules" class="page-form ml-[20px]">
|
<el-form label-width="150px" :model="formData" ref="formRef" :rules="formRules" class="page-form ml-[20px]">
|
||||||
<el-form-item :label="t('短信签名')" prop="signature">
|
<el-form-item :label="t('短信签名')" prop="signature">
|
||||||
<el-input v-model="formData.signature" placeholder="请输入短信签名" class="input-width" maxlength="20" show-word-limit clearable />
|
<el-input
|
||||||
|
v-model="formData.signature"
|
||||||
|
placeholder="请输入短信签名"
|
||||||
|
class="input-width"
|
||||||
|
maxlength="20"
|
||||||
|
show-word-limit
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="ml-[150px] text-[12px] text-[#999] leading-[20px]">必须由【】包裹,例如:【test】</div>
|
<div class="ml-[150px] text-[12px] text-[#999] leading-[20px]">必须由【】包裹,例如:【test】</div>
|
||||||
<div class="my-[5px] ml-[150px] text-[12px] text-[#999] leading-[20px]">字数要求在2-20个字符,不能使用空格和特殊符号“ - + = * & % # @ ~等;</div>
|
<div class="my-[5px] ml-[150px] text-[12px] text-[#999] leading-[20px]">
|
||||||
|
字数要求在2-20个字符,不能使用空格和特殊符号“ - + = * & % # @ ~等;
|
||||||
|
</div>
|
||||||
<el-form-item :label="t('短信示例内容')" prop="contentExample">
|
<el-form-item :label="t('短信示例内容')" prop="contentExample">
|
||||||
<el-input v-model="formData.contentExample" placeholder="请输入短信示例内容" clearable maxlength="50" show-word-limit class="input-width" />
|
<el-input
|
||||||
|
v-model="formData.contentExample"
|
||||||
|
placeholder="请输入短信示例内容"
|
||||||
|
clearable
|
||||||
|
maxlength="50"
|
||||||
|
show-word-limit
|
||||||
|
class="input-width"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('企业名称')" prop="companyName">
|
<el-form-item :label="t('企业名称')" prop="companyName">
|
||||||
<el-input v-model="formData.companyName" placeholder="请输入企业名称" clearable maxlength="20" show-word-limit class="input-width" />
|
<el-input
|
||||||
|
v-model="formData.companyName"
|
||||||
|
placeholder="请输入企业名称"
|
||||||
|
clearable
|
||||||
|
maxlength="20"
|
||||||
|
show-word-limit
|
||||||
|
class="input-width"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('社会统一信用代码')" prop="creditCode">
|
<el-form-item :label="t('社会统一信用代码')" prop="creditCode">
|
||||||
<el-input v-model="formData.creditCode" placeholder="请输入社会统一信用代码" clearable maxlength="20" show-word-limit class="input-width" />
|
<el-input
|
||||||
|
v-model="formData.creditCode"
|
||||||
|
placeholder="请输入社会统一信用代码"
|
||||||
|
clearable
|
||||||
|
maxlength="20"
|
||||||
|
show-word-limit
|
||||||
|
class="input-width"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('法人姓名')" prop="legalPerson">
|
<el-form-item :label="t('法人姓名')" prop="legalPerson">
|
||||||
<el-input v-model="formData.legalPerson" placeholder="请输入法人姓名" clearable maxlength="20" show-word-limit class="input-width" />
|
<el-input
|
||||||
|
v-model="formData.legalPerson"
|
||||||
|
placeholder="请输入法人姓名"
|
||||||
|
clearable
|
||||||
|
maxlength="20"
|
||||||
|
show-word-limit
|
||||||
|
class="input-width"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('经办人姓名')" prop="principalName">
|
<el-form-item :label="t('责任人姓名')" prop="principalName">
|
||||||
<el-input v-model="formData.principalName" placeholder="请输入经办人姓名" clearable maxlength="20" show-word-limit class="input-width" />
|
<el-input
|
||||||
|
v-model="formData.principalName"
|
||||||
|
placeholder="请输入责任人姓名"
|
||||||
|
clearable
|
||||||
|
maxlength="20"
|
||||||
|
show-word-limit
|
||||||
|
class="input-width"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('经办人手机号')" prop="principalMobile">
|
<el-form-item :label="t('责任人手机号')" prop="principalMobile">
|
||||||
<el-input v-model="formData.principalMobile" placeholder="请输入经办人手机号" clearable maxlength="20" show-word-limit class="input-width" />
|
<el-input
|
||||||
|
v-model="formData.principalMobile"
|
||||||
|
placeholder="请输入责任人手机号"
|
||||||
|
clearable
|
||||||
|
maxlength="20"
|
||||||
|
show-word-limit
|
||||||
|
class="input-width"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('经办人身份证')" prop="principalIdCard">
|
<el-form-item :label="t('责任人身份证')" prop="principalIdCard">
|
||||||
<el-input v-model="formData.principalIdCard" placeholder="请输入经办人身份证" clearable maxlength="18" show-word-limit class="input-width" />
|
<el-input
|
||||||
|
v-model="formData.principalIdCard"
|
||||||
|
placeholder="请输入责任人身份证"
|
||||||
|
clearable
|
||||||
|
maxlength="18"
|
||||||
|
show-word-limit
|
||||||
|
class="input-width"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('签名来源')">
|
<el-form-item :label="t('签名来源')">
|
||||||
<el-radio-group v-model="formData.signSource">
|
<el-radio-group v-model="formData.signSource">
|
||||||
@ -119,11 +196,38 @@
|
|||||||
<el-radio v-for="item in signConfig.signTypeList" :key="item.type" :label="item.type">{{ item.name }}</el-radio>
|
<el-radio v-for="item in signConfig.signTypeList" :key="item.type" :label="item.type">{{ item.name }}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('上传图片')" prop="imgUrl">
|
<!-- <el-form-item :label="t('上传图片')" prop="imgUrl">
|
||||||
<upload-image v-model="formData.imgUrl" :limit="1" />
|
<upload-image v-model="formData.imgUrl" :limit="1" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="ml-[150px] text-[12px] text-[#999] leading-[20px]">当签名来源为商标、APP、小程序、事业单位简称或企业名称简称时,需必填此字段</div>
|
<div class="ml-[150px] text-[12px] text-[#999] leading-[20px]">
|
||||||
<div class="my-[5px] ml-[150px] text-[12px] text-[#999] leading-[20px]">当签名来源为事业单位全称或企业名称全称时,选填此字段。</div>
|
当签名来源为商标、APP、小程序、事业单位简称或企业名称简称时,需必填此字段
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="my-[5px] ml-[150px] text-[12px] text-[#999] leading-[20px]"
|
||||||
|
>
|
||||||
|
当签名来源为事业单位全称或企业名称全称时,选填此字段。
|
||||||
|
</div> -->
|
||||||
|
<el-form-item :label="t('营业执照')" prop="bizLicenseUrl">
|
||||||
|
<upload-image v-model="formData.bizLicenseUrl" :limit="1" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('企查查唯一性截图')" prop="qccUrl">
|
||||||
|
<upload-image v-model="formData.qccUrl" :limit="1" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('中国商标网截图')" prop="tmnetUrl">
|
||||||
|
<upload-image v-model="formData.tmnetUrl" :limit="1" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('移动ICP截图')" prop="mobileIcpUrl">
|
||||||
|
<upload-image v-model="formData.mobileIcpUrl" :limit="1" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('应用商店 /小程序页面开发者截图')" prop="telecomAppstoreUrl">
|
||||||
|
<upload-image v-model="formData.telecomAppstoreUrl" :limit="1" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('身份证正面(人像面)')" prop="idcardFrontUrl">
|
||||||
|
<upload-image v-model="formData.idcardFrontUrl" :limit="1" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('身份证反面URL')" prop="idcardBackUrl">
|
||||||
|
<upload-image v-model="formData.idcardBackUrl" :limit="1" />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item :label="t('是否默认')">
|
<el-form-item :label="t('是否默认')">
|
||||||
<el-radio-group v-model="formData.defaultSign">
|
<el-radio-group v-model="formData.defaultSign">
|
||||||
<el-radio :label="1">是</el-radio>
|
<el-radio :label="1">是</el-radio>
|
||||||
@ -131,9 +235,10 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="visibleAdd = false">{{ t("cancel") }}</el-button>
|
<el-button @click="visibleAdd = false">{{ t('cancel') }}</el-button>
|
||||||
<el-button type="primary" @click="onSave()">{{ t("confirm") }}</el-button>
|
<el-button type="primary" @click="onSave()">{{ t('confirm') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
@ -150,12 +255,19 @@ const emit = defineEmits(['select'])
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
username: {
|
username: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: '',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
const initialFormData = {
|
const initialFormData = {
|
||||||
defaultSign: 0,
|
defaultSign: 0,
|
||||||
imgUrl: '',
|
imgUrl: '',
|
||||||
|
bizLicenseUrl: '',
|
||||||
|
qccUrl: '',
|
||||||
|
tmnetUrl: '',
|
||||||
|
mobileIcpUrl: '',
|
||||||
|
telecomAppstoreUrl: '',
|
||||||
|
idcardFrontUrl: '',
|
||||||
|
idcardBackUrl: '',
|
||||||
contentExample: '',
|
contentExample: '',
|
||||||
signType: '',
|
signType: '',
|
||||||
signSource: '',
|
signSource: '',
|
||||||
@ -165,16 +277,16 @@ const initialFormData = {
|
|||||||
legalPerson: '',
|
legalPerson: '',
|
||||||
creditCode: '',
|
creditCode: '',
|
||||||
companyName: '',
|
companyName: '',
|
||||||
signature: ''
|
signature: '',
|
||||||
}
|
}
|
||||||
const formData = reactive({ ...initialFormData })
|
const formData = reactive({ ...initialFormData })
|
||||||
|
|
||||||
const signConfig = reactive({
|
const signConfig = reactive({
|
||||||
signTypeList: [],
|
signTypeList: [],
|
||||||
signSourceList: []
|
signSourceList: [],
|
||||||
})
|
})
|
||||||
const getSmsSignConfigFn = () => {
|
const getSmsSignConfigFn = () => {
|
||||||
getSmsSignConfig().then(res => {
|
getSmsSignConfig().then((res) => {
|
||||||
signConfig.signTypeList = res.data.sign_type_list
|
signConfig.signTypeList = res.data.sign_type_list
|
||||||
signConfig.signSourceList = res.data.sign_source_list
|
signConfig.signSourceList = res.data.sign_source_list
|
||||||
formData.signSource = res.data.sign_source_list[0].type
|
formData.signSource = res.data.sign_source_list[0].type
|
||||||
@ -210,31 +322,27 @@ const formRules = computed(() => {
|
|||||||
|
|
||||||
callback()
|
callback()
|
||||||
},
|
},
|
||||||
trigger: 'blur'
|
trigger: 'blur',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
principalMobile: [
|
principalMobile: [
|
||||||
{ required: true, message: '请输入经办人手机号', trigger: 'blur' },
|
{ required: true, message: '请输入责任人手机号', trigger: 'blur' },
|
||||||
{ validator: phoneVerify, trigger: 'blur' }
|
{ validator: phoneVerify, trigger: 'blur' },
|
||||||
],
|
|
||||||
companyName: [
|
|
||||||
{ required: true, message: '请输入企业名称', trigger: 'blur' }
|
|
||||||
],
|
|
||||||
contentExample: [
|
|
||||||
{ required: true, message: '请输入短信示例内容', trigger: 'blur' }
|
|
||||||
],
|
],
|
||||||
|
companyName: [{ required: true, message: '请输入企业名称', trigger: 'blur' }],
|
||||||
|
contentExample: [{ required: true, message: '请输入短信示例内容', trigger: 'blur' }],
|
||||||
creditCode: [
|
creditCode: [
|
||||||
{ required: true, message: '请输入社会统一信用代码', trigger: 'blur' }
|
{
|
||||||
],
|
required: true,
|
||||||
legalPerson: [
|
message: '请输入社会统一信用代码',
|
||||||
{ required: true, message: '请输入法人姓名', trigger: 'blur' }
|
trigger: 'blur',
|
||||||
],
|
},
|
||||||
principalName: [
|
|
||||||
{ required: true, message: '请输入经办人姓名', trigger: 'blur' }
|
|
||||||
],
|
],
|
||||||
|
legalPerson: [{ required: true, message: '请输入法人姓名', trigger: 'blur' }],
|
||||||
|
principalName: [{ required: true, message: '请输入责任人姓名', trigger: 'blur' }],
|
||||||
principalIdCard: [
|
principalIdCard: [
|
||||||
{ required: true, message: '请输入经办人身份证', trigger: 'blur' },
|
{ required: true, message: '请输入责任人身份证', trigger: 'blur' },
|
||||||
{ validator: idCardVerify, trigger: 'blur' }
|
{ validator: idCardVerify, trigger: 'blur' },
|
||||||
],
|
],
|
||||||
imgUrl: [
|
imgUrl: [
|
||||||
{
|
{
|
||||||
@ -250,10 +358,86 @@ const formRules = computed(() => {
|
|||||||
callback() // 不需要校验
|
callback() // 不需要校验
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
trigger: 'blur'
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
bizLicenseUrl: [{ required: true, message: '请输入营业执照', trigger: 'blur' }],
|
||||||
|
qccUrl: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
const needImage = [1, 2].includes(formData.signSource) || formData.signType === 1
|
||||||
|
if (needImage) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
callback(new Error('请上传企查查唯一性截图'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
}
|
}
|
||||||
]
|
} else {
|
||||||
|
callback() // 不需要校验
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tmnetUrl: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
const needImage = [3].includes(formData.signSource)
|
||||||
|
if (needImage) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
callback(new Error('请上传中国商标网截图'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback() // 不需要校验
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
mobileIcpUrl: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
const needImage = [4, 5].includes(formData.signSource)
|
||||||
|
if (needImage) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
callback(new Error('请上传移动ICP截图'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback() // 不需要校验
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
telecomAppstoreUrl: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
const needImage = [4, 5].includes(formData.signSource)
|
||||||
|
if (needImage) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
callback(new Error('请上传应用商店/小程序页面开发者截图'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback() // 不需要校验
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
idcardFrontUrl: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入身份证正面(人像面)',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
idcardBackUrl: [{ required: true, message: '请输入身份证反面', trigger: 'blur' }],
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -293,7 +477,7 @@ const tableData = reactive({
|
|||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
data: [],
|
data: [],
|
||||||
searchParam: {}
|
searchParam: {},
|
||||||
})
|
})
|
||||||
|
|
||||||
const open = () => {
|
const open = () => {
|
||||||
@ -306,13 +490,15 @@ const loadSignList = () => {
|
|||||||
const params = {
|
const params = {
|
||||||
page: tableData.page,
|
page: tableData.page,
|
||||||
limit: tableData.limit,
|
limit: tableData.limit,
|
||||||
...tableData.searchParam
|
...tableData.searchParam,
|
||||||
}
|
}
|
||||||
getSignList(props.username, params).then((res) => {
|
getSignList(props.username, params)
|
||||||
|
.then((res) => {
|
||||||
tableData.loading = false
|
tableData.loading = false
|
||||||
tableData.data = res.data.data
|
tableData.data = res.data.data
|
||||||
tableData.total = res.data.total
|
tableData.total = res.data.total
|
||||||
}).catch(() => {
|
})
|
||||||
|
.catch(() => {
|
||||||
tableData.loading = false
|
tableData.loading = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -328,7 +514,7 @@ const deleteTemplate = (row:any) => {
|
|||||||
ElMessageBox.confirm(t('确定删除该签名吗?'), t('提示'), {
|
ElMessageBox.confirm(t('确定删除该签名吗?'), t('提示'), {
|
||||||
confirmButtonText: t('确定'),
|
confirmButtonText: t('确定'),
|
||||||
cancelButtonText: t('取消'),
|
cancelButtonText: t('取消'),
|
||||||
type: 'warning'
|
type: 'warning',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
deleteSign(props.username, { signatures: [row.sign] }).then((res) => {
|
deleteSign(props.username, { signatures: [row.sign] }).then((res) => {
|
||||||
// loadSignList()
|
// loadSignList()
|
||||||
@ -381,7 +567,7 @@ const batchDeleteEvent = () => {
|
|||||||
if (multipleSelection.value.length == 0) {
|
if (multipleSelection.value.length == 0) {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: `${t('请选择要删除的签名')}`
|
message: `${t('请选择要删除的签名')}`,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -389,7 +575,7 @@ const batchDeleteEvent = () => {
|
|||||||
ElMessageBox.confirm(t('确定删除选中的签名吗?'), t('warning'), {
|
ElMessageBox.confirm(t('确定删除选中的签名吗?'), t('warning'), {
|
||||||
confirmButtonText: t('confirm'),
|
confirmButtonText: t('confirm'),
|
||||||
cancelButtonText: t('cancel'),
|
cancelButtonText: t('cancel'),
|
||||||
type: 'warning'
|
type: 'warning',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
const signatures: any = []
|
const signatures: any = []
|
||||||
multipleSelection.value.forEach((item: any) => {
|
multipleSelection.value.forEach((item: any) => {
|
||||||
@ -397,14 +583,15 @@ const batchDeleteEvent = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
deleteSign(props.username, {
|
deleteSign(props.username, {
|
||||||
signatures
|
signatures,
|
||||||
}).then(() => {
|
})
|
||||||
|
.then(() => {
|
||||||
tableData.loading = true
|
tableData.loading = true
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loadSignList()
|
loadSignList()
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}).catch(() => {
|
|
||||||
})
|
})
|
||||||
|
.catch(() => {})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,16 @@
|
|||||||
<el-form-item :label="t('icon')">
|
<el-form-item :label="t('icon')">
|
||||||
<upload-image v-model="formData.front_end_icon" />
|
<upload-image v-model="formData.front_end_icon" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="t('metaTitle')">
|
||||||
|
<el-input v-model.trim="formData.meta_title" :placeholder="t('MetaPlaceholder')" class="input-width" clearable maxlength="40" show-word-limit />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('metaDescription')">
|
||||||
|
<el-input v-model.trim="formData.meta_desc" :placeholder="t('metaDescriptionPlaceholder')" class="input-width" clearable maxlength="200" show-word-limit />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('metaKeywords')">
|
||||||
|
<el-input v-model.trim="formData.meta_keyword" :placeholder="t('metaKeywordsPlaceholder')" class="input-width" clearable maxlength="200" show-word-limit />
|
||||||
|
</el-form-item>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
<el-card class="box-card mt-[15px] !border-none" shadow="never">
|
||||||
@ -75,13 +85,10 @@ import { setWebsite, getWebsite, getService } from '@/app/api/sys'
|
|||||||
import { FormInstance, FormRules } from 'element-plus'
|
import { FormInstance, FormRules } from 'element-plus'
|
||||||
import { getAppType } from '@/utils/common'
|
import { getAppType } from '@/utils/common'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import useUserStore from '@/stores/modules/user'
|
|
||||||
import useSystemStore from '@/stores/modules/system';
|
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const pageName = route.meta.title
|
const pageName = route.meta.title
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const appType = ref(getAppType())
|
|
||||||
const formData = reactive<Record<string, string>>({
|
const formData = reactive<Record<string, string>>({
|
||||||
site_name: '',
|
site_name: '',
|
||||||
logo: '',
|
logo: '',
|
||||||
@ -102,7 +109,10 @@ const formData = reactive<Record<string, string>>({
|
|||||||
icon: '',
|
icon: '',
|
||||||
wechat_code: '',
|
wechat_code: '',
|
||||||
enterprise_wechat: '',
|
enterprise_wechat: '',
|
||||||
tel: ''
|
tel: '',
|
||||||
|
meta_title: '',
|
||||||
|
meta_desc: '',
|
||||||
|
meta_keyword: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
const setFormData = async () => {
|
const setFormData = async () => {
|
||||||
|
|||||||
@ -83,7 +83,7 @@
|
|||||||
温馨提示
|
温馨提示
|
||||||
</span>
|
</span>
|
||||||
<span class="text-[12px] text-[#9699B6] ml-[10px]">运行环境要求:需预先配置 Nodejs 环境</span>
|
<span class="text-[12px] text-[#9699B6] ml-[10px]">运行环境要求:需预先配置 Nodejs 环境</span>
|
||||||
<span class="text-[14px] text-primary cursor-pointer ml-[10px] border-b-[1px] border-solid border-primary" @click="linkEvent('https://doc.niucloud.com/saas.html?keywords=/di-san-fang-yun-bian-yi-pei-zhi')">搭建教程</span>
|
<span class="text-[14px] text-primary cursor-pointer ml-[10px] border-b-[1px] border-solid border-primary" @click="linkEvent('https://doc.press.niucloud.com/php/saas-framework/use/other/third-party-cloud-compilation.html')">搭建教程</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-[40px] text-[14px] text-[#4F516D] mb-[18px]">
|
<div class="ml-[40px] text-[14px] text-[#4F516D] mb-[18px]">
|
||||||
<span>1、下载第三方云编译服务器搭建程序包</span><span class="text-primary cursor-pointer " @click="linkEvent('https://gitee.com/niucloud-team/niucloud-compile-server')"> niucloud-compile-server</span>
|
<span>1、下载第三方云编译服务器搭建程序包</span><span class="text-primary cursor-pointer " @click="linkEvent('https://gitee.com/niucloud-team/niucloud-compile-server')"> niucloud-compile-server</span>
|
||||||
@ -139,7 +139,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="ml-[40px] text-[#374151] text-[14px] italic">
|
<div class="ml-[40px] text-[#374151] text-[14px] italic">
|
||||||
<span class="text-[16px] italic">#安装依赖:</span>
|
<span class="text-[16px] italic font-500">#安装依赖:</span>
|
||||||
<span class="italic">进入admin端与uniapp端以及web端目录都可执行</span>
|
<span class="italic">进入admin端与uniapp端以及web端目录都可执行</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-[40px] w-[1085px] h-[40px] bg-[#F9F9FB] rounded-[4px] mt-[10px] flex items-center justify-between border-[#F1F1F8] border-solid border-[1px] px-[10px]">
|
<div class="ml-[40px] w-[1085px] h-[40px] bg-[#F9F9FB] rounded-[4px] mt-[10px] flex items-center justify-between border-[#F1F1F8] border-solid border-[1px] px-[10px]">
|
||||||
@ -149,9 +149,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-[21px]">
|
<div class="mt-[21px]">
|
||||||
<div class="ml-[40px] text-[14px] text-[#374151] italic">
|
<div class="ml-[40px] text-[14px] text-[#374151] italic">
|
||||||
<span class="text-[16px] italic">#后台admin端口打包:</span>
|
<span class="text-[16px] italic font-500">#后台admin端口打包:</span>
|
||||||
<span>进入admin目录下执行,执行后编译代码默认移动到系统的niucloud下的</span>
|
<span>进入admin目录下执行,执行后编译代码默认移动到系统的niucloud下的</span>
|
||||||
<span class="text-[#F09000] mx-[3px]">public/admin</span>
|
<span class="text-[#F09000] mx-[3px] font-bold">public/admin</span>
|
||||||
<span>目录下</span>
|
<span>目录下</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-[40px] w-[1085px] h-[40px] bg-[#F9F9FB] rounded-[4px] mt-[10px] flex items-center justify-between border-[#F1F1F8] border-solid border-[1px] px-[10px]">
|
<div class="ml-[40px] w-[1085px] h-[40px] bg-[#F9F9FB] rounded-[4px] mt-[10px] flex items-center justify-between border-[#F1F1F8] border-solid border-[1px] px-[10px]">
|
||||||
@ -161,9 +161,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-[21px]">
|
<div class="mt-[21px]">
|
||||||
<div class="ml-[40px] text-[14px] text-[#374151] italic">
|
<div class="ml-[40px] text-[14px] text-[#374151] italic">
|
||||||
<span class="text-[16px] italic">#使用uniapp打包H5:</span>
|
<span class="text-[16px] italic font-500">#使用uniapp打包H5:</span>
|
||||||
<span>进入uniapp目录下执行,执行后编译代码默认移动到系统niucloud下的</span>
|
<span>进入uniapp目录下执行,执行后编译代码默认移动到系统niucloud下的</span>
|
||||||
<span class="text-[#F09000] mx-[3px]">public/wap</span>
|
<span class="text-[#F09000] mx-[3px] font-bold">public/wap</span>
|
||||||
<span>目录下</span>
|
<span>目录下</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-[40px] w-[1085px] h-[40px] bg-[#F9F9FB] rounded-[4px] mt-[10px] flex items-center justify-between border-[#F1F1F8] border-solid border-[1px] px-[10px]">
|
<div class="ml-[40px] w-[1085px] h-[40px] bg-[#F9F9FB] rounded-[4px] mt-[10px] flex items-center justify-between border-[#F1F1F8] border-solid border-[1px] px-[10px]">
|
||||||
@ -173,9 +173,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-[21px]">
|
<div class="mt-[21px]">
|
||||||
<div class="ml-[40px] text-[14px] text-[#374151] italic">
|
<div class="ml-[40px] text-[14px] text-[#374151] italic">
|
||||||
<span class="text-[16px] italic">#使用uniapp打包微信小程序:</span>
|
<span class="text-[16px] italic font-500">#使用uniapp打包微信小程序:</span>
|
||||||
<span>进入uniapp目录下执行,执行后编译代码默认移动到系统niucloud下的</span>
|
<span>进入uniapp目录下执行,执行后编译代码默认移动到系统niucloud下的</span>
|
||||||
<span class="text-[#F09000] mx-[3px]">uni-app/dist/build/mp-weixin</span>
|
<span class="text-[#F09000] mx-[3px] font-bold">uni-app/dist/build/mp-weixin</span>
|
||||||
<span>目录</span>
|
<span>目录</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-[40px] w-[1085px] h-[40px] bg-[#F9F9FB] rounded-[4px] mt-[10px] flex items-center justify-between border-[#F1F1F8] border-solid border-[1px] px-[10px]">
|
<div class="ml-[40px] w-[1085px] h-[40px] bg-[#F9F9FB] rounded-[4px] mt-[10px] flex items-center justify-between border-[#F1F1F8] border-solid border-[1px] px-[10px]">
|
||||||
@ -185,9 +185,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-[21px]">
|
<div class="mt-[21px]">
|
||||||
<div class="ml-[40px] text-[14px] text-[#374151] italic">
|
<div class="ml-[40px] text-[14px] text-[#374151] italic">
|
||||||
<span class="text-[16px] italic">#前台web(pc)端打包::</span>
|
<span class="text-[16px] italic font-500">#前台web(pc)端打包::</span>
|
||||||
<span>进入web目录下执行,执行后编译代码默认移动到系统niucloud下的</span>
|
<span>进入web目录下执行,执行后编译代码默认移动到系统niucloud下的</span>
|
||||||
<span class="text-[#F09000] mx-[3px]">public/web</span>
|
<span class="text-[#F09000] mx-[3px] font-bold">public/web</span>
|
||||||
<span>目录下</span>
|
<span>目录下</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-[40px] w-[1085px] h-[40px] bg-[#F9F9FB] rounded-[4px] mt-[10px] flex items-center justify-between border-[#F1F1F8] border-solid border-[1px] px-[10px]">
|
<div class="ml-[40px] w-[1085px] h-[40px] bg-[#F9F9FB] rounded-[4px] mt-[10px] flex items-center justify-between border-[#F1F1F8] border-solid border-[1px] px-[10px]">
|
||||||
|
|||||||
@ -264,7 +264,7 @@ const deleteEvent = (id: number) => {
|
|||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
deleteGenerateTable(id).then(() => {
|
deleteGenerateTable(id).then(() => {
|
||||||
loadGenerateTableList()
|
loadGenerateTableList(getTablePageStorage(codeTableData.searchParam).page)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -314,7 +314,7 @@ const generateCreateFn = (id: any, generate_type: any) => {
|
|||||||
codeTableData.loading = false
|
codeTableData.loading = false
|
||||||
window.open(img(res.data.file), '_blank')
|
window.open(img(res.data.file), '_blank')
|
||||||
} else {
|
} else {
|
||||||
loadGenerateTableList()
|
loadGenerateTableList(getTablePageStorage(codeTableData.searchParam).page)
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
codeTableData.loading = false
|
codeTableData.loading = false
|
||||||
@ -368,7 +368,7 @@ const listToTree = (arr:any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
obj = { name: name, path: name.indexOf('.') < 0 ? '' : arr[i], key: 'k' + i + j + k }
|
obj = { name, path: name.indexOf('.') < 0 ? '' : arr[i], key: 'k' + i + j + k }
|
||||||
if (name.indexOf('.') < 0) obj.children = []
|
if (name.indexOf('.') < 0) obj.children = []
|
||||||
if (obj.path === arr[0]) treeKey.value = obj.key
|
if (obj.path === arr[0]) treeKey.value = obj.key
|
||||||
_ret.push(obj)
|
_ret.push(obj)
|
||||||
|
|||||||
@ -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-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-col>
|
||||||
</el-row>
|
</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>
|
<el-scrollbar>
|
||||||
<!-- 选择弹出框 -->
|
<!-- 选择弹出框 -->
|
||||||
<div class="flex flex-wrap" v-if="attachment.data.length && (operate === true || scene != 'attachment')">
|
<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)">
|
<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'"/>
|
<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>
|
<span class="absolute bottom-[2px] right-[2px] text-white z-[2] leading-none">{{ getFileIndex(item.att_id) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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">
|
<div class="flex items-center">
|
||||||
<el-tooltip placement="top">
|
<el-tooltip placement="top">
|
||||||
<template #content>{{ item.real_name }}</template>
|
<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="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]">
|
<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"/>
|
<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>
|
<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>
|
<div class="truncate my-[10px] cursor-pointer text-base flex-1 text-center">{{ item.real_name }}</div>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
<div class="flex absolute top-0 left-0 right-0 bottom-0 items-center justify-center" v-else>
|
<div class="flex absolute top-0 left-0 right-0 bottom-0 items-center justify-center" v-else>
|
||||||
@ -668,6 +670,9 @@ defineExpose({
|
|||||||
.attachment-action {
|
.attachment-action {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
.del-icon {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment-list-wrap {
|
.attachment-list-wrap {
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
<icon name="element Delete" color="#fff" size="18px" @click.stop="removeImage" />
|
<icon name="element Delete" color="#fff" size="18px" @click.stop="removeImage" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<upload-attachment :limit="limit" @confirm="confirmSelect" v-else>
|
<upload-attachment :limit="uploadImgNum" @confirm="confirmSelect" v-else>
|
||||||
<div class="w-full h-full flex items-center justify-center flex-col content-wrap">
|
<div class="w-full h-full flex items-center justify-center flex-col content-wrap">
|
||||||
<icon name="element Plus" size="20px" color="var(--el-text-color-secondary)" />
|
<icon name="element Plus" size="20px" color="var(--el-text-color-secondary)" />
|
||||||
<div class="leading-none text-xs mt-[10px] text-secondary">{{ imageText || t('upload.root') }}</div>
|
<div class="leading-none text-xs mt-[10px] text-secondary">{{ imageText || t('upload.root') }}</div>
|
||||||
@ -34,7 +34,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded cursor-pointer overflow-hidden relative border border-dashed border-color" :style="style" v-if="images.data.length < limit">
|
<div class="rounded cursor-pointer overflow-hidden relative border border-dashed border-color" :style="style" v-if="images.data.length < limit">
|
||||||
<upload-attachment :limit="limit" @confirm="confirmSelect">
|
<upload-attachment :limit="uploadImgNum" @confirm="confirmSelect">
|
||||||
<div class="w-full h-full flex items-center justify-center flex-col content-wrap">
|
<div class="w-full h-full flex items-center justify-center flex-col content-wrap">
|
||||||
<icon name="element Plus" size="20px" color="var(--el-text-color-secondary)" />
|
<icon name="element Plus" size="20px" color="var(--el-text-color-secondary)" />
|
||||||
<div class="leading-none text-xs mt-[10px] text-secondary">{{ imageText || t('upload.root') }}</div>
|
<div class="leading-none text-xs mt-[10px] text-secondary">{{ imageText || t('upload.root') }}</div>
|
||||||
@ -105,6 +105,11 @@ const setValue = () => {
|
|||||||
previewImageList = toRaw(images.data).map((url: string) => { return url.indexOf('data:image') != -1 ? url : img(url) })
|
previewImageList = toRaw(images.data).map((url: string) => { return url.indexOf('data:image') != -1 ? url : img(url) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uploadImgNum = computed(() => {
|
||||||
|
const num = prop.limit - images.data.length
|
||||||
|
return num
|
||||||
|
})
|
||||||
|
|
||||||
watch(() => value.value, () => {
|
watch(() => value.value, () => {
|
||||||
if (value.value.indexOf('data:image') != -1) {
|
if (value.value.indexOf('data:image') != -1) {
|
||||||
images.data = [value.value]
|
images.data = [value.value]
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -105,38 +105,38 @@
|
|||||||
setup (props, context) {
|
setup (props, context) {
|
||||||
const { mode, captchaType, vSpace, imgSize, barSize, type, blockSize, explain } = toRefs(props)
|
const { mode, captchaType, vSpace, imgSize, barSize, type, blockSize, explain } = toRefs(props)
|
||||||
const { proxy } = getCurrentInstance()
|
const { proxy } = getCurrentInstance()
|
||||||
const secretKey = ref(''), // 后端返回的ase加密秘钥
|
const secretKey = ref('') // 后端返回的ase加密秘钥
|
||||||
passFlag = ref(''), // 是否通过的标识
|
const passFlag = ref('') // 是否通过的标识
|
||||||
backImgBase = ref(''), // 验证码背景图片
|
const backImgBase = ref('') // 验证码背景图片
|
||||||
blockBackImgBase = ref(''), // 验证滑块的背景图片
|
const blockBackImgBase = ref('') // 验证滑块的背景图片
|
||||||
backToken = ref(''), // 后端返回的唯一token值
|
const backToken = ref('') // 后端返回的唯一token值
|
||||||
startMoveTime = ref(''), // 移动开始的时间
|
const startMoveTime = ref('') // 移动开始的时间
|
||||||
endMoveTime = ref(''), // 移动结束的时间
|
const endMoveTime = ref('') // 移动结束的时间
|
||||||
tipsBackColor = ref(''), // 提示词的背景颜色
|
const tipsBackColor = ref('') // 提示词的背景颜色
|
||||||
tipWords = ref(''),
|
const tipWords = ref('')
|
||||||
text = ref(''),
|
const text = ref('')
|
||||||
finishText = ref(''),
|
const finishText = ref('')
|
||||||
setSize = reactive({
|
const setSize = reactive({
|
||||||
imgHeight: 0,
|
imgHeight: 0,
|
||||||
imgWidth: 0,
|
imgWidth: 0,
|
||||||
barHeight: 0,
|
barHeight: 0,
|
||||||
barWidth: 0
|
barWidth: 0
|
||||||
}),
|
})
|
||||||
top = ref(0),
|
const top = ref(0)
|
||||||
left = ref(0),
|
const left = ref(0)
|
||||||
moveBlockLeft = ref(undefined),
|
const moveBlockLeft = ref(undefined)
|
||||||
leftBarWidth = ref(undefined),
|
const leftBarWidth = ref(undefined)
|
||||||
// 移动中样式
|
// 移动中样式
|
||||||
moveBlockBackgroundColor = ref(undefined),
|
const moveBlockBackgroundColor = ref(undefined)
|
||||||
leftBarBorderColor = ref('#ddd'),
|
const leftBarBorderColor = ref('#ddd')
|
||||||
iconColor = ref(undefined),
|
const iconColor = ref(undefined)
|
||||||
iconClass = ref('icon-right'),
|
const iconClass = ref('icon-right')
|
||||||
status = ref(false), // 鼠标状态
|
const status = ref(false) // 鼠标状态
|
||||||
isEnd = ref(false), // 是够验证完成
|
const isEnd = ref(false) // 是够验证完成
|
||||||
showRefresh = ref(true),
|
const showRefresh = ref(true)
|
||||||
transitionLeft = ref(''),
|
const transitionLeft = ref('')
|
||||||
transitionWidth = ref(''),
|
const transitionWidth = ref('')
|
||||||
startLeft = ref(0)
|
const startLeft = ref(0)
|
||||||
|
|
||||||
const barArea = computed(() => {
|
const barArea = computed(() => {
|
||||||
return proxy.$el.querySelector('.verify-bar-area')
|
return proxy.$el.querySelector('.verify-bar-area')
|
||||||
@ -146,7 +146,7 @@
|
|||||||
text.value = explain.value
|
text.value = explain.value
|
||||||
getPictrue()
|
getPictrue()
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
let { imgHeight, imgWidth, barHeight, barWidth } = resetSize(proxy)
|
const { imgHeight, imgWidth, barHeight, barWidth } = resetSize(proxy)
|
||||||
setSize.imgHeight = imgHeight
|
setSize.imgHeight = imgHeight
|
||||||
setSize.imgWidth = imgWidth
|
setSize.imgWidth = imgWidth
|
||||||
setSize.barHeight = barHeight
|
setSize.barHeight = barHeight
|
||||||
@ -225,8 +225,8 @@
|
|||||||
} else { // 兼容移动端
|
} else { // 兼容移动端
|
||||||
var x = e.touches[0].pageX
|
var x = e.touches[0].pageX
|
||||||
}
|
}
|
||||||
var bar_area_left = barArea.value.getBoundingClientRect().left
|
const bar_area_left = barArea.value.getBoundingClientRect().left
|
||||||
var move_block_left = x - bar_area_left // 小方块相对于父元素的left值
|
let move_block_left = x - bar_area_left // 小方块相对于父元素的left值
|
||||||
if (move_block_left >= barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2) {
|
if (move_block_left >= barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2) {
|
||||||
move_block_left = barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2
|
move_block_left = barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2
|
||||||
}
|
}
|
||||||
@ -244,15 +244,17 @@
|
|||||||
endMoveTime.value = +new Date()
|
endMoveTime.value = +new Date()
|
||||||
// 判断是否重合
|
// 判断是否重合
|
||||||
if (status.value && isEnd.value == false) {
|
if (status.value && isEnd.value == false) {
|
||||||
var moveLeftDistance = parseInt(( moveBlockLeft.value || '' ).replace('px', ''))
|
let moveLeftDistance = parseInt((moveBlockLeft.value || '').replace('px', ''))
|
||||||
moveLeftDistance = moveLeftDistance * 310 / parseInt(setSize.imgWidth)
|
moveLeftDistance = moveLeftDistance * 310 / parseInt(setSize.imgWidth)
|
||||||
const data = {
|
const data = {
|
||||||
captchaType: captchaType.value,
|
captchaType: captchaType.value,
|
||||||
'captcha_code': secretKey.value ? aesEncrypt(JSON.stringify({
|
captcha_code: secretKey.value
|
||||||
|
? aesEncrypt(JSON.stringify({
|
||||||
x: moveLeftDistance,
|
x: moveLeftDistance,
|
||||||
y: 5.0
|
y: 5.0
|
||||||
}), secretKey.value) : JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
|
}), secretKey.value)
|
||||||
'captcha_key': backToken.value
|
: JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
|
||||||
|
captcha_key: backToken.value
|
||||||
}
|
}
|
||||||
reqCheck(data).then(res => {
|
reqCheck(data).then(res => {
|
||||||
if (res.code == 1) {
|
if (res.code == 1) {
|
||||||
@ -270,10 +272,12 @@
|
|||||||
}
|
}
|
||||||
passFlag.value = true
|
passFlag.value = true
|
||||||
tipWords.value = `${((endMoveTime.value - startMoveTime.value) / 1000).toFixed(2)}s验证成功`
|
tipWords.value = `${((endMoveTime.value - startMoveTime.value) / 1000).toFixed(2)}s验证成功`
|
||||||
var captchaVerification = secretKey.value ? aesEncrypt(backToken.value + '---' + JSON.stringify({
|
const captchaVerification = secretKey.value
|
||||||
|
? aesEncrypt(backToken.value + '---' + JSON.stringify({
|
||||||
x: moveLeftDistance,
|
x: moveLeftDistance,
|
||||||
y: 5.0
|
y: 5.0
|
||||||
}), secretKey.value) : backToken.value + '---' + JSON.stringify({
|
}), secretKey.value)
|
||||||
|
: backToken.value + '---' + JSON.stringify({
|
||||||
x: moveLeftDistance,
|
x: moveLeftDistance,
|
||||||
y: 5.0
|
y: 5.0
|
||||||
})
|
})
|
||||||
|
|||||||
@ -181,9 +181,6 @@ const handleJump = (routeName: string) => {
|
|||||||
storage.remove('activeAppKey')
|
storage.remove('activeAppKey')
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
const processedSpecialMenus = handleSpecialMenus();
|
|
||||||
specialMenuNamesLevel1.value = collectSpecialMenuNamesLevel1(processedSpecialMenus)
|
|
||||||
|
|
||||||
// 点击特殊菜单的一级,跳转应用列表
|
// 点击特殊菜单的一级,跳转应用列表
|
||||||
if (specialMenuNamesLevel1.value.includes(routeName)) {
|
if (specialMenuNamesLevel1.value.includes(routeName)) {
|
||||||
routeName = 'addon_list'
|
routeName = 'addon_list'
|
||||||
|
|||||||
@ -60,7 +60,6 @@ const addonRouters: Record<string, any> = {}
|
|||||||
// storage.set({ key: 'specialAppList', data: specialList.value })
|
// storage.set({ key: 'specialAppList', data: specialList.value })
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getWebConfig().then(({ data }) => {
|
getWebConfig().then(({ data }) => {
|
||||||
webSite.value = data
|
webSite.value = data
|
||||||
@ -95,17 +94,17 @@ routers.forEach(item => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 排序, 功能正确,改了排序后需要把菜单排序的默认值重新调整一下【多应用一级菜单,单应用二级菜单】
|
// 排序, 功能正确,改了排序后需要把菜单排序的默认值重新调整一下【多应用一级菜单,单应用二级菜单】
|
||||||
// menuData.value.sort((a, b) => {
|
menuData.value.sort((a, b) => {
|
||||||
// if (a.meta.sort && b.meta.sort) {
|
if (a.meta.sort && b.meta.sort) {
|
||||||
// return b.meta.sort - a.meta.sort
|
return b.meta.sort - a.meta.sort
|
||||||
// } else if (a.meta.sort) {
|
} else if (a.meta.sort) {
|
||||||
// return -1
|
return -1
|
||||||
// } else if (b.meta.sort) {
|
} else if (b.meta.sort) {
|
||||||
// return 1
|
return 1
|
||||||
// } else {
|
} else {
|
||||||
// return 0
|
return 0
|
||||||
// }
|
}
|
||||||
// })
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// 多应用时将应用插入菜单
|
// 多应用时将应用插入菜单
|
||||||
@ -120,17 +119,17 @@ if (systemStore?.apps.length > 1) {
|
|||||||
menuData.value.unshift(...routers)
|
menuData.value.unshift(...routers)
|
||||||
|
|
||||||
// 排序, 功能正确,改了排序后需要把菜单排序的默认值重新调整一下【多应用一级菜单,单应用二级菜单】
|
// 排序, 功能正确,改了排序后需要把菜单排序的默认值重新调整一下【多应用一级菜单,单应用二级菜单】
|
||||||
// menuData.value.sort((a, b) => {
|
menuData.value.sort((a, b) => {
|
||||||
// if (a.meta.sort && b.meta.sort) {
|
if (a.meta.sort && b.meta.sort) {
|
||||||
// return b.meta.sort - a.meta.sort
|
return b.meta.sort - a.meta.sort
|
||||||
// } else if (a.meta.sort) {
|
} else if (a.meta.sort) {
|
||||||
// return -1
|
return -1
|
||||||
// } else if (b.meta.sort) {
|
} else if (b.meta.sort) {
|
||||||
// return 1
|
return 1
|
||||||
// } else {
|
} else {
|
||||||
// return 0
|
return 0
|
||||||
// }
|
}
|
||||||
// })
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -258,4 +258,8 @@ const toPreview = () => {
|
|||||||
font-weight: inherit !important;
|
font-weight: inherit !important;
|
||||||
color: var(--el-text-color-regular) !important;
|
color: var(--el-text-color-regular) !important;
|
||||||
}
|
}
|
||||||
|
:deep(.inter .el-breadcrumb__inner){
|
||||||
|
font-weight: inherit !important;
|
||||||
|
color: var(--el-text-color-regular) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tab-wrap w-full px-[16px]">
|
<div class="tab-wrap w-full px-[16px]" v-show="systemStore.tab">
|
||||||
<el-tabs :closable="tabbarStore.tabLength > 1" :model-value="route.path" @tab-click="tabClick" @tab-remove="removeTab">
|
<el-tabs :closable="tabbarStore.tabLength > 1" :model-value="route.name" @tab-click="tabClick" @tab-remove="removeTab">
|
||||||
<el-tab-pane v-for="(tab, key, index) in tabbarStore.tabs" :name="tab.path" :key="index">
|
<el-tab-pane v-for="(tab, key, index) in tabbarStore.tabs" :name="tab.name" :key="index">
|
||||||
<template #label>
|
<template #label>
|
||||||
<el-dropdown trigger="contextmenu" placement="bottom-start">
|
<el-dropdown trigger="contextmenu" placement="bottom-start">
|
||||||
<span :class="{ 'text-primary': route.path == tab.path }" class="tab-name">{{ tab.title }}</span>
|
<span :class="{ 'text-primary': route.name == tab.name }" class="tab-name">{{ tab.title }}</span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item icon="Back" :disabled="index == 0" @click="closeLeft(tab.path)">{{t('tabs.closeLeft') }}</el-dropdown-item>
|
<el-dropdown-item icon="Back" :disabled="index == 0" @click="closeLeft(tab.name)">{{t('tabs.closeLeft') }}</el-dropdown-item>
|
||||||
<el-dropdown-item icon="Right" :disabled="index == (tabbarStore.tabLength - 1)" @click="closeRight(tab.path)">{{t('tabs.closeRight') }}</el-dropdown-item>
|
<el-dropdown-item icon="Right" :disabled="index == (tabbarStore.tabLength - 1)" @click="closeRight(tab.name)">{{t('tabs.closeRight') }}</el-dropdown-item>
|
||||||
<el-dropdown-item icon="Close" :disabled="tabbarStore.tabLength == 1" @click="closeOther(tab.path)">{{t('tabs.closeOther') }}</el-dropdown-item>
|
<el-dropdown-item icon="Close" :disabled="tabbarStore.tabLength == 1" @click="closeOther(tab.name)">{{t('tabs.closeOther') }}</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
@ -22,10 +22,12 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { watch, onMounted } from 'vue'
|
import { watch, onMounted } from 'vue'
|
||||||
import useTabbarStore from '@/stores/modules/tabbar'
|
import useTabbarStore from '@/stores/modules/tabbar'
|
||||||
|
import useSystemStore from '@/stores/modules/system'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { t } from '@/lang'
|
import { t } from '@/lang'
|
||||||
|
|
||||||
const tabbarStore = useTabbarStore()
|
const tabbarStore = useTabbarStore()
|
||||||
|
const systemStore = useSystemStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@ -43,7 +45,7 @@ watch(route, (nval: any) => {
|
|||||||
*/
|
*/
|
||||||
const tabClick = (content: any) => {
|
const tabClick = (content: any) => {
|
||||||
const tabRoute = tabbarStore.tabs[content.props.name]
|
const tabRoute = tabbarStore.tabs[content.props.name]
|
||||||
router.push({ path: tabRoute.path, query: tabRoute.query })
|
router.push({ name: tabRoute.name, query: tabRoute.query })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,45 +53,49 @@ const tabClick = (content: any) => {
|
|||||||
* @param content
|
* @param content
|
||||||
*/
|
*/
|
||||||
const removeTab = (content: any) => {
|
const removeTab = (content: any) => {
|
||||||
if (route.path == content) {
|
if (route.name == content) {
|
||||||
const tabs = Object.keys(tabbarStore.tabs)
|
const tabs = Object.keys(tabbarStore.tabs)
|
||||||
router.push({ path: tabs[tabs.indexOf(content) - 1] })
|
if (tabs.indexOf(content) == 0) {
|
||||||
|
router.push({ name: tabs[1] })
|
||||||
|
} else {
|
||||||
|
router.push({ name: tabs[tabs.indexOf(content) - 1] })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tabbarStore.removeTab(content)
|
tabbarStore.removeTab(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭左侧
|
* 关闭左侧
|
||||||
* @param path
|
* @param name
|
||||||
*/
|
*/
|
||||||
const closeLeft = (path: string) => {
|
const closeLeft = (name: string) => {
|
||||||
const tabs = Object.keys(tabbarStore.tabs)
|
const tabs = Object.keys(tabbarStore.tabs)
|
||||||
for (let i = tabs.indexOf(path) - 1; i >= 0; i--) {
|
for (let i = tabs.indexOf(name) - 1; i >= 0; i--) {
|
||||||
delete tabbarStore.tabs[tabs[i]]
|
delete tabbarStore.tabs[tabs[i]]
|
||||||
}
|
}
|
||||||
router.push({ path })
|
router.push({ name })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭右侧
|
* 关闭右侧
|
||||||
* @param path
|
* @param name
|
||||||
*/
|
*/
|
||||||
const closeRight = (path: string) => {
|
const closeRight = (name: string) => {
|
||||||
const tabs = Object.keys(tabbarStore.tabs)
|
const tabs = Object.keys(tabbarStore.tabs)
|
||||||
for (let i = tabs.indexOf(path) + 1; i < tabs.length; i++) {
|
for (let i = tabs.indexOf(name) + 1; i < tabs.length; i++) {
|
||||||
delete tabbarStore.tabs[tabs[i]]
|
delete tabbarStore.tabs[tabs[i]]
|
||||||
}
|
}
|
||||||
router.push({ path })
|
router.push({ name })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭其他
|
* 关闭其他
|
||||||
* @param path
|
* @param name
|
||||||
*/
|
*/
|
||||||
const closeOther = (path: string) => {
|
const closeOther = (name: string) => {
|
||||||
const tabs = Object.keys(tabbarStore.tabs)
|
const tabs = Object.keys(tabbarStore.tabs)
|
||||||
tabs.forEach((key: string) => { key != path && delete tabbarStore.tabs[key] })
|
tabs.forEach((key: string) => { key != name && delete tabbarStore.tabs[key] })
|
||||||
router.push({ path })
|
router.push({ name })
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -11,12 +11,14 @@
|
|||||||
</el-header>
|
</el-header>
|
||||||
<!-- 顶部 end -->
|
<!-- 顶部 end -->
|
||||||
|
|
||||||
|
<layout-tab />
|
||||||
|
|
||||||
<!-- 主体 -->
|
<!-- 主体 -->
|
||||||
<el-main class="h-full p-0 bg-page">
|
<el-main class="h-full p-0 bg-page">
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<div class="p-[15px]">
|
<div class="p-[15px]">
|
||||||
<router-view v-slot="{ Component, route }" v-if="appStore.routeRefreshTag">
|
<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" />
|
<component :is="Component" :key="route.fullPath" />
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</router-view>
|
</router-view>
|
||||||
@ -32,6 +34,7 @@
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import layoutHeader from './components/header/index.vue'
|
import layoutHeader from './components/header/index.vue'
|
||||||
import layoutAside from './components/aside/index.vue'
|
import layoutAside from './components/aside/index.vue'
|
||||||
|
import layoutTab from './components/tabs.vue'
|
||||||
import useAppStore from '@/stores/modules/app'
|
import useAppStore from '@/stores/modules/app'
|
||||||
import useTabbarStore from '@/stores/modules/tabbar'
|
import useTabbarStore from '@/stores/modules/tabbar'
|
||||||
import useSystemStore from '@/stores/modules/system'
|
import useSystemStore from '@/stores/modules/system'
|
||||||
|
|||||||
@ -79,8 +79,12 @@ router.beforeEach(async (to: any, from, next) => {
|
|||||||
|
|
||||||
// 设置首页路由
|
// 设置首页路由
|
||||||
let firstRoute: symbol | string | undefined = findFirstValidRoute(userStore.routers)
|
let firstRoute: symbol | string | undefined = findFirstValidRoute(userStore.routers)
|
||||||
if (systemStore.apps[0]) {
|
for (let i = 0; i < systemStore.apps.length; i++) {
|
||||||
firstRoute = userStore.addonIndexRoute[ systemStore.apps[0].key ]
|
const item = systemStore.apps[i]
|
||||||
|
if (userStore.addonIndexRoute[item.key]) {
|
||||||
|
firstRoute = userStore.addonIndexRoute[item.key]
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ROOT_ROUTER.redirect = { name: firstRoute }
|
ROOT_ROUTER.redirect = { name: firstRoute }
|
||||||
|
|||||||
@ -1,17 +1,20 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import storage from '@/utils/storage'
|
import storage from '@/utils/storage'
|
||||||
import { useCssVar } from '@vueuse/core'
|
import { useCssVar } from '@vueuse/core'
|
||||||
import { useCssVar } from '@vueuse/core'
|
|
||||||
import { getInstalledAddonList } from '@/app/api/addon'
|
import { getInstalledAddonList } from '@/app/api/addon'
|
||||||
|
|
||||||
|
|
||||||
interface System {
|
interface System {
|
||||||
menuIsCollapse: boolean,
|
menuIsCollapse: boolean,
|
||||||
|
menuDrawer: boolean,
|
||||||
dark: boolean,
|
dark: boolean,
|
||||||
theme: string,
|
theme: string,
|
||||||
lang: string,
|
lang: string,
|
||||||
apps: Record<string, any>[],
|
apps: Record<string, any>[],
|
||||||
addons: Record<string, any>[]
|
addons: Record<string, any>[]
|
||||||
|
sidebar: string,
|
||||||
|
sidebarStyle: string,
|
||||||
|
currHeadMenuName: any,
|
||||||
|
tab: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const theme = storage.get('theme') ?? {}
|
const theme = storage.get('theme') ?? {}
|
||||||
@ -20,14 +23,22 @@ const useSystemStore = defineStore('system', {
|
|||||||
state: (): System => {
|
state: (): System => {
|
||||||
return {
|
return {
|
||||||
menuIsCollapse: false,
|
menuIsCollapse: false,
|
||||||
|
menuDrawer: false,
|
||||||
dark: theme.dark ?? false,
|
dark: theme.dark ?? false,
|
||||||
theme: theme.theme ?? '#273de3',
|
theme: theme.theme ?? '#273de3',
|
||||||
|
sidebar: theme.sidebar ?? 'oneType',
|
||||||
lang: storage.get('lang') ?? 'zh-cn',
|
lang: storage.get('lang') ?? 'zh-cn',
|
||||||
apps: [],
|
apps: [],
|
||||||
addons: []
|
addons: [],
|
||||||
|
sidebarStyle: theme.sidebarStyle ?? 'threeType',
|
||||||
|
currHeadMenuName: '',
|
||||||
|
tab: storage.get('tab') ?? false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
setHeadMenu(value: any) {
|
||||||
|
this.currHeadMenuName = value
|
||||||
|
},
|
||||||
setTheme(state: string, value: any) {
|
setTheme(state: string, value: any) {
|
||||||
this[state] = value
|
this[state] = value
|
||||||
theme[state] = value
|
theme[state] = value
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
import type { RouteLocationNormalizedLoaded, RouteRecordName } from 'vue-router'
|
||||||
|
import useSystemStore from '@/stores/modules/system'
|
||||||
|
|
||||||
interface Tabbar {
|
interface Tabbar {
|
||||||
curr: string,
|
curr: string,
|
||||||
tabs: {
|
tabs: {
|
||||||
[key: string]: any
|
[key: RouteRecordName]: any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,17 +17,18 @@ const useTabbarStore = defineStore('tabbar', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
addTab(roter: RouteLocationNormalizedLoaded) {
|
addTab(router: RouteLocationNormalizedLoaded) {
|
||||||
if (roter.meta && roter.meta.type != 1) return
|
if (router.meta && router.meta.type != 1) return
|
||||||
if (this.tabs[roter.path]) {
|
if (this.tabs[router.name]) {
|
||||||
this.tabs[roter.path].query = roter.query || {}
|
this.tabs[router.name].query = router.query || {}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.tabs[roter.path] = {
|
this.tabs[router.name] = {
|
||||||
path: roter.path,
|
path: router.path,
|
||||||
title: roter.meta ? roter.meta.title : '',
|
title: router.meta ? router.meta.title : '',
|
||||||
name: roter.name,
|
name: router.name,
|
||||||
query: roter.query || {}
|
query: router.query || {},
|
||||||
|
componentName: router.matched.at(-1)?.components.default.__name
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
removeTab(path: string) {
|
removeTab(path: string) {
|
||||||
@ -40,8 +42,9 @@ const useTabbarStore = defineStore('tabbar', {
|
|||||||
tabLength: (state) => Object.keys(state.tabs).length,
|
tabLength: (state) => Object.keys(state.tabs).length,
|
||||||
tabNames: (state) => {
|
tabNames: (state) => {
|
||||||
const name: any[] = []
|
const name: any[] = []
|
||||||
|
if (!useSystemStore().tab) return name
|
||||||
Object.keys(state.tabs).forEach(key => {
|
Object.keys(state.tabs).forEach(key => {
|
||||||
name.push(state.tabs[key].name)
|
name.push(state.tabs[key].componentName)
|
||||||
})
|
})
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,7 +53,9 @@ const useUserStore = defineStore('user', {
|
|||||||
logout()
|
logout()
|
||||||
// 清除tabbar
|
// 清除tabbar
|
||||||
useTabbarStore().clearTab()
|
useTabbarStore().clearTab()
|
||||||
router.push('/login')
|
const login = '/login'
|
||||||
|
// router.push(login)
|
||||||
|
location.href = `${location.origin}${login}`
|
||||||
},
|
},
|
||||||
getAuthMenusFn() {
|
getAuthMenusFn() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|||||||
Binary file not shown.
@ -1 +1,2 @@
|
|||||||
/* addon-iconfont.css */
|
@import "addon/o2o/iconfont.css";
|
||||||
|
@import "addon/tourism/iconfont.css";
|
||||||
|
|||||||
38
admin/src/styles/icon/addon/o2o/iconfont.css
Normal file
38
admin/src/styles/icon/addon/o2o/iconfont.css
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "o2o"; /* Project id 4412516 */
|
||||||
|
src: url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.woff2?t=1705720131974') format('woff2'),
|
||||||
|
url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.woff?t=1705720131974') format('woff'),
|
||||||
|
url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.ttf?t=1705720131974') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o {
|
||||||
|
font-family: "o2o" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-danhanghuadong:before {
|
||||||
|
content: "\e66f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-yuanjiao:before {
|
||||||
|
content: "\e6c0";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-gl-square:before {
|
||||||
|
content: "\ea92";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-sousuo12:before {
|
||||||
|
content: "\e699";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-sousuo11:before {
|
||||||
|
content: "\e6d4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-jishi:before {
|
||||||
|
content: "\e600";
|
||||||
|
}
|
||||||
51
admin/src/styles/icon/addon/o2o/iconfont.json
Normal file
51
admin/src/styles/icon/addon/o2o/iconfont.json
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"id": "4412516",
|
||||||
|
"name": "上门服务",
|
||||||
|
"font_family": "o2o",
|
||||||
|
"css_prefix_text": "o2o-icon-",
|
||||||
|
"description": "",
|
||||||
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "30621139",
|
||||||
|
"name": "单行滑动",
|
||||||
|
"font_class": "danhanghuadong",
|
||||||
|
"unicode": "e66f",
|
||||||
|
"unicode_decimal": 58991
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7149037",
|
||||||
|
"name": "圆角",
|
||||||
|
"font_class": "yuanjiao",
|
||||||
|
"unicode": "e6c0",
|
||||||
|
"unicode_decimal": 59072
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7594344",
|
||||||
|
"name": "20gl-square",
|
||||||
|
"font_class": "gl-square",
|
||||||
|
"unicode": "ea92",
|
||||||
|
"unicode_decimal": 60050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "10133070",
|
||||||
|
"name": "搜索",
|
||||||
|
"font_class": "sousuo12",
|
||||||
|
"unicode": "e699",
|
||||||
|
"unicode_decimal": 59033
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "14652583",
|
||||||
|
"name": "搜索",
|
||||||
|
"font_class": "sousuo11",
|
||||||
|
"unicode": "e6d4",
|
||||||
|
"unicode_decimal": 59092
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "6818781",
|
||||||
|
"name": "技师",
|
||||||
|
"font_class": "jishi",
|
||||||
|
"unicode": "e600",
|
||||||
|
"unicode_decimal": 58880
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
58
admin/src/styles/icon/addon/tourism/iconfont.css
Normal file
58
admin/src/styles/icon/addon/tourism/iconfont.css
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "tourism"; /* Project id 4137250 */
|
||||||
|
src: url('//at.alicdn.com/t/c/font_4137250_st1ha9l0k1e.woff2?t=1687685028672') format('woff2'),
|
||||||
|
url('//at.alicdn.com/t/c/font_4137250_st1ha9l0k1e.woff?t=1687685028672') format('woff'),
|
||||||
|
url('//at.alicdn.com/t/c/font_4137250_st1ha9l0k1e.ttf?t=1687685028672') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism {
|
||||||
|
font-family: "tourism" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-feiji:before {
|
||||||
|
content: "\e600";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou:before {
|
||||||
|
content: "\e6a9";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyouchanpin:before {
|
||||||
|
content: "\e63b";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou1:before {
|
||||||
|
content: "\e623";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou2:before {
|
||||||
|
content: "\e601";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou3:before {
|
||||||
|
content: "\e60c";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyoubaochedingdan:before {
|
||||||
|
content: "\e612";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou4:before {
|
||||||
|
content: "\e653";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou5:before {
|
||||||
|
content: "\e610";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyouguanguang:before {
|
||||||
|
content: "\e87e";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou6:before {
|
||||||
|
content: "\e642";
|
||||||
|
}
|
||||||
86
admin/src/styles/icon/addon/tourism/iconfont.json
Normal file
86
admin/src/styles/icon/addon/tourism/iconfont.json
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
"id": "4137250",
|
||||||
|
"name": "旅游业",
|
||||||
|
"font_family": "tourism",
|
||||||
|
"css_prefix_text": "tourism-icon-",
|
||||||
|
"description": "",
|
||||||
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "1443",
|
||||||
|
"name": "飞机",
|
||||||
|
"font_class": "feiji",
|
||||||
|
"unicode": "e600",
|
||||||
|
"unicode_decimal": 58880
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "446824",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou",
|
||||||
|
"unicode": "e6a9",
|
||||||
|
"unicode_decimal": 59049
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "1167173",
|
||||||
|
"name": "旅游产品",
|
||||||
|
"font_class": "lvyouchanpin",
|
||||||
|
"unicode": "e63b",
|
||||||
|
"unicode_decimal": 58939
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "1354920",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou1",
|
||||||
|
"unicode": "e623",
|
||||||
|
"unicode_decimal": 58915
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "1505555",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou2",
|
||||||
|
"unicode": "e601",
|
||||||
|
"unicode_decimal": 58881
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "2121726",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou3",
|
||||||
|
"unicode": "e60c",
|
||||||
|
"unicode_decimal": 58892
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "2357494",
|
||||||
|
"name": "旅游包车订单",
|
||||||
|
"font_class": "lvyoubaochedingdan",
|
||||||
|
"unicode": "e612",
|
||||||
|
"unicode_decimal": 58898
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "3944019",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou4",
|
||||||
|
"unicode": "e653",
|
||||||
|
"unicode_decimal": 58963
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "4838220",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou5",
|
||||||
|
"unicode": "e610",
|
||||||
|
"unicode_decimal": 58896
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7444178",
|
||||||
|
"name": "旅游观光",
|
||||||
|
"font_class": "lvyouguanguang",
|
||||||
|
"unicode": "e87e",
|
||||||
|
"unicode_decimal": 59518
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "9748082",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou6",
|
||||||
|
"unicode": "e642",
|
||||||
|
"unicode_decimal": 58946
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,9 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont";
|
font-family: "iconfont"; /* Project id 3883393 */
|
||||||
/* Project id 3883393 */
|
src: url('//at.alicdn.com/t/c/font_3883393_jquqyagjvf.woff2?t=1773643077865') format('woff2'),
|
||||||
src: url('//at.alicdn.com/t/c/font_3883393_0604cbkh5j03.woff2?t=1762651161569') format('woff2'),
|
url('//at.alicdn.com/t/c/font_3883393_jquqyagjvf.woff?t=1773643077865') format('woff'),
|
||||||
url('//at.alicdn.com/t/c/font_3883393_0604cbkh5j03.woff?t=1762651161569') format('woff'),
|
url('//at.alicdn.com/t/c/font_3883393_jquqyagjvf.ttf?t=1773643077865') format('truetype');
|
||||||
url('//at.alicdn.com/t/c/font_3883393_0604cbkh5j03.ttf?t=1762651161569') format('truetype');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@ -14,6 +13,18 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.iconjiang-right:before {
|
||||||
|
content: "\e921";
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconpeisongshezhi:before {
|
||||||
|
content: "\e920";
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconai:before {
|
||||||
|
content: "\e91f";
|
||||||
|
}
|
||||||
|
|
||||||
.icona-zhulixiangqingpc30:before {
|
.icona-zhulixiangqingpc30:before {
|
||||||
content: "\e914";
|
content: "\e914";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "nc-iconfont"; /* Project id 4567203 */
|
font-family: "nc-iconfont"; /* Project id 4567203 */
|
||||||
src: url('//at.alicdn.com/t/c/font_4567203_9qmfc2elgrt.woff2?t=1741345195504') format('woff2'),
|
src: url('//at.alicdn.com/t/c/font_4567203_mq3zv60st5a.woff2?t=1767940264104') format('woff2'),
|
||||||
url('//at.alicdn.com/t/c/font_4567203_9qmfc2elgrt.woff?t=1741345195504') format('woff'),
|
url('//at.alicdn.com/t/c/font_4567203_mq3zv60st5a.woff?t=1767940264104') format('woff'),
|
||||||
url('//at.alicdn.com/t/c/font_4567203_9qmfc2elgrt.ttf?t=1741345195504') format('truetype');
|
url('//at.alicdn.com/t/c/font_4567203_mq3zv60st5a.ttf?t=1767940264104') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.nc-iconfont {
|
.nc-iconfont {
|
||||||
@ -13,6 +13,578 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-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 {
|
.nc-icon-qingliV6xx:before {
|
||||||
content: "\e865";
|
content: "\e865";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -127,14 +127,15 @@ export function isUrl(str: string): boolean {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function img(path: string): string {
|
export function img(path: string): string {
|
||||||
|
if (!path) return ''
|
||||||
|
|
||||||
let imgDomain = import.meta.env.VITE_IMG_DOMAIN || location.origin
|
let imgDomain = import.meta.env.VITE_IMG_DOMAIN || location.origin
|
||||||
|
|
||||||
if (typeof path == 'string' && path.startsWith('/')) path = path.replace(/^\//, '')
|
if (path.startsWith('/')) path = path.replace(/^\//, '')
|
||||||
if (typeof imgDomain == 'string' && imgDomain.endsWith('/')) imgDomain = imgDomain.slice(0, -1)
|
if (imgDomain.endsWith('/')) imgDomain = imgDomain.slice(0, -1)
|
||||||
if(path){
|
|
||||||
return isUrl(path) ? path : `${imgDomain}/${path}`
|
return isUrl(path) ? path : `${imgDomain}/${path}`
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输出asset img
|
* 输出asset img
|
||||||
@ -401,3 +402,37 @@ export function getTablePageStorage(where: any = {}) {
|
|||||||
}
|
}
|
||||||
return data;
|
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'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取图片尺寸的函数
|
||||||
|
export function getImageDimensions (url: string) {
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const imgObj = new Image()
|
||||||
|
imgObj.onload = () => {
|
||||||
|
// 成功加载
|
||||||
|
const size = {
|
||||||
|
width: imgObj.naturalWidth,
|
||||||
|
height: imgObj.naturalHeight
|
||||||
|
}
|
||||||
|
resolve(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
imgObj.onerror = (err) => {
|
||||||
|
// 加载失败
|
||||||
|
resolve(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置图片源,开始加载
|
||||||
|
// 注意:如果图片跨域且服务器未设置CORS,可能会触发onerror
|
||||||
|
imgObj.src = img(url)
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -134,6 +134,9 @@ export const createPolygon = (map: any, geometriesData: any) => {
|
|||||||
* @param key
|
* @param key
|
||||||
*/
|
*/
|
||||||
export const deleteGeometry = (key: string) => {
|
export const deleteGeometry = (key: string) => {
|
||||||
|
if (!geometry[key]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
geometry[key].graphical.remove(key)
|
geometry[key].graphical.remove(key)
|
||||||
geometry[key].editor.delete()
|
geometry[key].editor.delete()
|
||||||
}
|
}
|
||||||
@ -143,6 +146,9 @@ export const deleteGeometry = (key: string) => {
|
|||||||
* @param key
|
* @param key
|
||||||
*/
|
*/
|
||||||
export const selectGeometry = (key: string) => {
|
export const selectGeometry = (key: string) => {
|
||||||
|
if (!geometry[key] || !geometry[key].editor) {
|
||||||
|
return
|
||||||
|
}
|
||||||
geometry[key].editor.select([key])
|
geometry[key].editor.select([key])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -82,8 +82,9 @@ class Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送get请求
|
* 发送post请求
|
||||||
* @param url
|
* @param url
|
||||||
|
* @param data
|
||||||
* @param config
|
* @param config
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
@ -92,8 +93,9 @@ class Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送get请求
|
* 发送put请求
|
||||||
* @param url
|
* @param url
|
||||||
|
* @param data
|
||||||
* @param config
|
* @param config
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
@ -102,7 +104,7 @@ class Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送get请求
|
* 发送delete请求
|
||||||
* @param url
|
* @param url
|
||||||
* @param config
|
* @param config
|
||||||
* @returns
|
* @returns
|
||||||
@ -180,15 +182,27 @@ class Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private messageCache = new Map();
|
private messageCache = new Map();
|
||||||
|
private readonly CACHE_EXPIRY = 5000; // 5秒内重复内容不再弹出,可自定义过期时间
|
||||||
|
private readonly MAX_CACHE_SIZE = 100;
|
||||||
|
|
||||||
private showElMessage(options: MessageParams) {
|
private showElMessage(options: MessageParams) {
|
||||||
const cacheKey = options.message
|
const cacheKey = options.message
|
||||||
|
const now = Date.now()
|
||||||
const cachedMessage = this.messageCache.get(cacheKey);
|
const cachedMessage = this.messageCache.get(cacheKey);
|
||||||
|
|
||||||
if (!cachedMessage || Date.now() - cachedMessage.timestamp > 5000) { // 5秒内重复内容不再弹出,可自定义过期时间
|
if (!cachedMessage || now - cachedMessage.timestamp > this.CACHE_EXPIRY) {
|
||||||
this.messageCache.set(cacheKey, { timestamp: Date.now() });
|
this.messageCache.set(cacheKey, { timestamp: now });
|
||||||
ElMessage(options)
|
ElMessage(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 定期清理过期缓存,防止内存泄漏
|
||||||
|
if (this.messageCache.size > this.MAX_CACHE_SIZE) {
|
||||||
|
for (const [key, value] of this.messageCache.entries()) {
|
||||||
|
if (now - value.timestamp > this.CACHE_EXPIRY) {
|
||||||
|
this.messageCache.delete(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,10 +34,12 @@ class Storage {
|
|||||||
*/
|
*/
|
||||||
public get(key: string) {
|
public get(key: string) {
|
||||||
try {
|
try {
|
||||||
const json: any = window.localStorage.getItem(`${this.prefix}.${key}`)
|
const value = window.localStorage.getItem(`${this.prefix}.${key}`)
|
||||||
return JSON.parse(json)
|
if (value === null) return null
|
||||||
|
return JSON.parse(value)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return window.localStorage.getItem(`${this.prefix}.${key}`)
|
const value = window.localStorage.getItem(`${this.prefix}.${key}`)
|
||||||
|
return value !== null ? value : null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user