This commit is contained in:
全栈小学生 2024-08-17 09:35:06 +08:00
parent 25791938f6
commit bf224633d5
102 changed files with 794 additions and 546 deletions

View File

@ -8,4 +8,4 @@ VITE_IMG_DOMAIN=''
VITE_REQUEST_HEADER_TOKEN_KEY='token'
# 请求时header中站点的参数名
VITE_REQUEST_HEADER_SITEID_KEY='site-id'
VITE_REQUEST_HEADER_SITEID_KEY='site-id'

View File

@ -8,4 +8,4 @@ VITE_IMG_DOMAIN=''
VITE_REQUEST_HEADER_TOKEN_KEY='token'
# 请求时header中站点的参数名
VITE_REQUEST_HEADER_SITEID_KEY='site-id'
VITE_REQUEST_HEADER_SITEID_KEY='site-id'

View File

@ -16,14 +16,9 @@ declare module '@vue/runtime-core' {
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
ElButton: typeof import('element-plus/es')['ElButton']
ElCalendar: typeof import('element-plus/es')['ElCalendar']
ElCard: typeof import('element-plus/es')['ElCard']
ElCarousel: typeof import('element-plus/es')['ElCarousel']
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCascader: typeof import('element-plus/es')['ElCascader']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
ElCheckTag: typeof import('element-plus/es')['ElCheckTag']
ElCol: typeof import('element-plus/es')['ElCol']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
@ -59,7 +54,6 @@ declare module '@vue/runtime-core' {
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRate: typeof import('element-plus/es')['ElRate']
ElResult: typeof import('element-plus/es')['ElResult']
ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
@ -77,7 +71,6 @@ declare module '@vue/runtime-core' {
ElTag: typeof import('element-plus/es')['ElTag']
ElTimeline: typeof import('element-plus/es')['ElTimeline']
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
ElTimeSelect: typeof import('element-plus/es')['ElTimeSelect']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTree: typeof import('element-plus/es')['ElTree']
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']

View File

@ -108,8 +108,8 @@
"touppercase", // 字母大写
"tolowercase", // 字母小写
"|",
// "link", // 超链接
// "unlink", // 取消链接
"link", // 超链接
"unlink", // 取消链接
// "anchor", // 锚点
"|",
"imagenone", // 图片默认

View File

@ -35,6 +35,11 @@ onMounted(() => {
//
toggleDark(systemStore.dark)
setThemeColor(systemStore.theme, systemStore.dark ? 'dark' : 'light')
// importIconFontCss();
// getIcon()
})
</script>

View File

View File

@ -5,7 +5,7 @@ import request from '@/utils/request'
* @returns
*/
export function getAddonLocal(params: Record<string, any>) {
return request.get('addon/local', params, { showSuccessMessage: true })
return request.get('addon/local', params)
}
/**
@ -13,7 +13,7 @@ export function getAddonLocal(params: Record<string, any>) {
* @returns
*/
export function getAddonDetial(id: number) {
return request.get(`addon/${id}`)
return request.get(`addon/${ id }`)
}
/**
@ -22,7 +22,7 @@ export function getAddonDetial(id: number) {
* @returns
*/
export function installAddon(params: Record<string, any>) {
return request.post(`addon/install/${params.addon}`, params)
return request.post(`addon/install/${ params.addon }`, params)
}
/**
@ -31,7 +31,7 @@ export function installAddon(params: Record<string, any>) {
* @returns
*/
export function cloudInstallAddon(params: Record<string, any>) {
return request.post(`addon/cloudinstall/${params.addon}`, params)
return request.post(`addon/cloudinstall/${ params.addon }`, params)
}
/**
@ -40,7 +40,7 @@ export function cloudInstallAddon(params: Record<string, any>) {
* @returns
*/
export function uninstallAddon(params: Record<string, any>) {
return request.post(`addon/uninstall/${params.addon}`, params, { showSuccessMessage: true })
return request.post(`addon/uninstall/${ params.addon }`, params, { showSuccessMessage: true })
}
/**
@ -49,7 +49,7 @@ export function uninstallAddon(params: Record<string, any>) {
* @returns
*/
export function preInstallCheck(addon: string) {
return request.get(`addon/install/check/${addon}`)
return request.get(`addon/install/check/${ addon }`)
}
/**
@ -66,7 +66,7 @@ export function getAddonInstalltask() {
* @returns
*/
export function getAddonCloudInstallLog(addon: string) {
return request.get(`addon/cloudinstall/${addon}`)
return request.get(`addon/cloudinstall/${ addon }`)
}
/**
@ -75,7 +75,7 @@ export function getAddonCloudInstallLog(addon: string) {
* @returns
*/
export function preUninstallCheck(addon: string) {
return request.get(`addon/uninstall/check/${addon}`)
return request.get(`addon/uninstall/check/${ addon }`)
}
/**
@ -84,7 +84,7 @@ export function preUninstallCheck(addon: string) {
* @returns
*/
export function cancelInstall(addon: string) {
return request.put(`addon/install/cancel/${addon}`, {}, { showErrorMessage: false })
return request.put(`addon/install/cancel/${ addon }`, {}, { showErrorMessage: false })
}
export function getInstalledAddonList() {

View File

@ -10,15 +10,6 @@ export function getNoticeList(params: any) {
return request.get('notice/notice', {params})
}
/**
*
* @param key
* @returns
*/
export function getNoticeInfo(key: string) {
return request.get(`notice/notice/${key}`)
}
/**
*
* @param params
@ -28,6 +19,15 @@ export function getNoticeLog(params: any) {
return request.get(`notice/log`, {params})
}
/**
*
* @param key
* @returns
*/
export function getNoticeInfo(key: string) {
return request.get(`notice/notice/${key}`)
}
/**
*
* @param params

View File

@ -1,70 +0,0 @@
import request from '@/utils/request'
/***************************************************** 充值订单 ****************************************************/
/**
*
* @param params
* @returns
*/
export function getRechargeOrderList(params: Record<string, any>) {
return request.get(`order/recharge`, {params})
}
/**
*
* @param params
* @returns
*/
export function getRechargeStat(params: Record<string, any>) {
return request.get(`order/recharge/stat`, {params})
}
/**
*
* @param order_id
* @returns
*/
export function getRechargeOrderInfo(order_id: number) {
return request.get(`order/recharge/${order_id}`);
}
/**
*
* @returns
*/
export function getRechargeOrderStatusList() {
return request.get(`order/recharge/status`)
}
/**
* 退
* @returns
*/
export function getRechargeRefund(params: Record<string, any>) {
return request.get(`order/recharge/refund`, {params})
}
/**
* 退
* @returns
*/
export function getRechargeRefundStatus() {
return request.get(`order/recharge/refund/status`)
}
/**
* 退
* @returns
*/
export function rechargeRefund(id: number) {
return request.put(`order/recharge/refund/${id}`, {}, {showSuccessMessage: true});
}
/**
* 退
* @returns
*/
export function getRechargeRefundStat() {
return request.get(`order/recharge/refund/stat`);
}

View File

@ -33,7 +33,7 @@ export function getRoleList(params: Record<string, any>) {
* @param roleId
*/
export function getRoleInfo(roleId: number) {
return request.get(`sys/role/${roleId}`)
return request.get(`sys/role/${ roleId }`)
}
/**
@ -50,7 +50,7 @@ export function addRole(params: Record<string, any>) {
* @param params
*/
export function editRole(params: Record<string, any>) {
return request.put(`sys/role/${params.role_id}`, params, { showSuccessMessage: true })
return request.put(`sys/role/${ params.role_id }`, params, { showSuccessMessage: true })
}
/**
@ -58,7 +58,7 @@ export function editRole(params: Record<string, any>) {
* @param roleId
*/
export function deleteRole(roleId: number) {
return request.delete(`sys/role/${roleId}`, { showSuccessMessage: true })
return request.delete(`sys/role/${ roleId }`, { showSuccessMessage: true })
}
/**
@ -76,7 +76,7 @@ export function allRole() {
* @returns
*/
export function getMenus(type: string) {
return request.get(`sys/menu/${type}`)
return request.get(`sys/menu/${ type }`)
}
/**
@ -85,7 +85,7 @@ export function getMenus(type: string) {
* @param menu_key
*/
export function getMenuInfo(app_type: string, menu_key: string) {
return request.get(`sys/menu/${app_type}/info/${menu_key}`);
return request.get(`sys/menu/${ app_type }/info/${ menu_key }`);
}
/**
@ -102,7 +102,7 @@ export function addMenu(params: Record<string, any>) {
* @param params
*/
export function editMenu(params: Record<string, any>) {
return request.put(`sys/menu/${params.app_type}/${params.menu_key}`, params, { showSuccessMessage: true })
return request.put(`sys/menu/${ params.app_type }/${ params.menu_key }`, params, { showSuccessMessage: true })
}
/**
@ -111,7 +111,7 @@ export function editMenu(params: Record<string, any>) {
* @param menu_key
*/
export function deleteMenu(app_type: string, menu_key: string) {
return request.delete(`sys/menu/${app_type}/${menu_key}`, { showSuccessMessage: true })
return request.delete(`sys/menu/${ app_type }/${ menu_key }`, { showSuccessMessage: true })
}
/**
@ -127,7 +127,7 @@ export function getSystemMenu() {
*
*/
export function getAddonMenu(key: any) {
return request.get(`sys/menu/addon_menu/${key}`)
return request.get(`sys/menu/addon_menu/${ key }`)
}
/**
@ -135,7 +135,7 @@ export function getAddonMenu(key: any) {
* @param key
*/
export function getMenuByTypeDir(key: any = 'system') {
return request.get(`sys/menu/dir/${key}`)
return request.get(`sys/menu/dir/${ key }`)
}
/***************************************************** 站点菜单 ****************************************************/
@ -231,7 +231,7 @@ export function addAttachmentCategory(params: Record<string, any>) {
* @returns
*/
export function editAttachmentCategory(params: Record<string, any>) {
return request.put(`sys/attachment/category/${params.id}`, params, { showSuccessMessage: true })
return request.put(`sys/attachment/category/${ params.id }`, params, { showSuccessMessage: true })
}
/**
@ -240,7 +240,7 @@ export function editAttachmentCategory(params: Record<string, any>) {
* @returns
*/
export function deleteAttachmentCategory(id: number) {
return request.delete(`sys/attachment/category/${id}`, { showSuccessMessage: true })
return request.delete(`sys/attachment/category/${ id }`, { showSuccessMessage: true })
}
/**
@ -302,6 +302,7 @@ export function getIconList(params: Record<string, any>) {
export function getEnv() {
return request.get(`sys/env`)
}
/***************************************************** 地址管理 ****************************************************/
/**
@ -309,7 +310,7 @@ export function getEnv() {
* @param pid
*/
export function getAreaListByPid(pid: number = 0) {
return request.get(`sys/area/list_by_pid/${pid}`)
return request.get(`sys/area/list_by_pid/${ pid }`)
}
/**
@ -317,7 +318,7 @@ export function getAreaListByPid(pid: number = 0) {
* @param level
*/
export function getAreatree(level: number = 1) {
return request.get(`sys/area/tree/${level}`)
return request.get(`sys/area/tree/${ level }`)
}
/**
@ -339,8 +340,9 @@ export function getContraryAddress(params: any) {
* @param code
*/
export function getAreaByCode(code: number | string) {
return request.get(`sys/area/code/${code}`)
return request.get(`sys/area/code/${ code }`)
}
/***************************************************** 存储设置 ****************************************************/
/**
@ -355,7 +357,7 @@ export function getStorageList() {
* @param type
*/
export function getStorageInfo(type: string) {
return request.get(`sys/storage/${type}`)
return request.get(`sys/storage/${ type }`)
}
/**
@ -364,7 +366,7 @@ export function getStorageInfo(type: string) {
* @returns
*/
export function editStorage(params: Record<string, any>) {
return request.put(`sys/storage/${params.storage_type}`, params, { showSuccessMessage: true })
return request.put(`sys/storage/${ params.storage_type }`, params, { showSuccessMessage: true })
}
/***************************************************** 支付设置 ****************************************************/
@ -374,7 +376,7 @@ export function editStorage(params: Record<string, any>) {
* @returns
*/
export function getPayConfig(type: string) {
return request.get(`pay/config/${type}`)
return request.get(`pay/config/${ type }`)
}
/**
@ -382,7 +384,7 @@ export function getPayConfig(type: string) {
* @returns
*/
export function setPayConfig(params: Record<string, any>) {
return request.put(`pay/config/${params.type}`, params, { showSuccessMessage: true });
return request.put(`pay/config/${ params.type }`, params, { showSuccessMessage: true });
}
/**
@ -399,7 +401,7 @@ export function getPayList() {
* @param channel
*/
export function getTransferInfo(channel: string) {
return request.get(`pay/channel/lists/${channel}`)
return request.get(`pay/channel/lists/${ channel }`)
}
/**
@ -426,7 +428,7 @@ export function getCronList(params: any) {
* @returns
*/
export function getCronInfo(id: string) {
return request.get(`sys/cron/${id}`);
return request.get(`sys/cron/${ id }`);
}
/**
@ -466,7 +468,7 @@ export function addCron(params: Record<string, any>) {
* @returns
*/
export function editCron(params: Record<string, any>) {
return request.put(`sys/schedule/${params.id}`, params, { showSuccessMessage: true })
return request.put(`sys/schedule/${ params.id }`, params, { showSuccessMessage: true })
}
/**
@ -474,7 +476,7 @@ export function editCron(params: Record<string, any>) {
* @returns
*/
export function deleteCron(id: string) {
return request.delete(`sys/schedule/${id}`, { showSuccessMessage: true })
return request.delete(`sys/schedule/${ id }`, { showSuccessMessage: true })
}
/***************************************************** 协议管理 ****************************************************/
@ -492,7 +494,7 @@ export function getAgreementList() {
* @returns
*/
export function getAgreementInfo(key: string) {
return request.get(`sys/agreement/${key}`);
return request.get(`sys/agreement/${ key }`);
}
/**
@ -500,7 +502,7 @@ export function getAgreementInfo(key: string) {
* @returns
*/
export function editAgreement(params: Record<string, any>) {
return request.put(`sys/agreement/${params.key}`, params, { showSuccessMessage: true })
return request.put(`sys/agreement/${ params.key }`, params, { showSuccessMessage: true })
}
/**
@ -602,7 +604,7 @@ export function getPayAuditList(params: Record<string, any>) {
* @returns
*/
export function payAuditPass(outTradeNo: string) {
return request.put(`pay/pass/${outTradeNo}`, {}, { showSuccessMessage: true })
return request.put(`pay/pass/${ outTradeNo }`, {}, { showSuccessMessage: true })
}
/**
@ -610,14 +612,14 @@ export function payAuditPass(outTradeNo: string) {
* @returns
*/
export function payAuditRefuse(params: Record<string, any>) {
return request.put(`pay/refuse/${params.out_trade_no}`, params, { showSuccessMessage: true })
return request.put(`pay/refuse/${ params.out_trade_no }`, params, { showSuccessMessage: true })
}
/**
*
*/
export function getPayDetail(id: number) {
return request.get(`pay/detail/${id}`)
return request.get(`pay/detail/${ id }`)
}
/**
@ -717,7 +719,7 @@ export function getExportKeyList() {
* @returns
*/
export function exportData(type: string, params: Record<string, any>) {
return request.get(`sys/export/${type}`, { params })
return request.get(`sys/export/${ type }`, { params })
}
/**
@ -725,7 +727,7 @@ export function exportData(type: string, params: Record<string, any>) {
* @returns
*/
export function exportDataCheck(type: string, params: Record<string, any>) {
return request.get(`sys/export/check/${type}`, { params })
return request.get(`sys/export/check/${ type }`, { params })
}
/**
@ -733,7 +735,7 @@ export function exportDataCheck(type: string, params: Record<string, any>) {
* @param id
*/
export function deleteExport(id: number) {
return request.delete(`sys/export/${id}`, { showSuccessMessage: true })
return request.delete(`sys/export/${ id }`, { showSuccessMessage: true })
}
/**

View File

@ -19,7 +19,7 @@ export function getUserList(params: Record<string, any>) {
* @returns
*/
export function getUserInfo(uid: number) {
return request.get(`user/user/${uid}`);
return request.get(`user/user/${ uid }`);
}
/**
@ -31,6 +31,14 @@ export function addUser(params: Record<string, any>) {
return request.post('user/user', params, { showSuccessMessage: true })
}
/**
*
* @param uid
*/
export function deleteUser(uid: number) {
return request.delete(`user/user/${uid}`, { showSuccessMessage: true })
}
/**
*
* @param params
@ -63,7 +71,7 @@ export function checkUsernameIsExist(username: string) {
* @param uid
*/
export function getUserCreateSiteLimit(uid: number) {
return request.get(`user/user/create_site_limit/${uid}`)
return request.get(`user/user/create_site_limit/${ uid }`)
}
/**
@ -71,7 +79,7 @@ export function getUserCreateSiteLimit(uid: number) {
* @param id
*/
export function getUserCreateSiteLimitInfo(id: number) {
return request.get(`user/user/create_site_limit/info/${id}`)
return request.get(`user/user/create_site_limit/info/${ id }`)
}
/**
@ -87,7 +95,7 @@ export function addUserCreateSiteLimit(params: Record<string, any>) {
* @param params
*/
export function editUserCreateSiteLimit(params: Record<string, any>) {
return request.put(`user/user/create_site_limit/${params.id}`, params, { showSuccessMessage: true })
return request.put(`user/user/create_site_limit/${ params.id }`, params, { showSuccessMessage: true })
}
/**
@ -95,5 +103,5 @@ export function editUserCreateSiteLimit(params: Record<string, any>) {
* @param id
*/
export function delUserCreateSiteLimit(id: number) {
return request.delete(`user/user/create_site_limit/${id}`, { showSuccessMessage: true })
return request.delete(`user/user/create_site_limit/${ id }`, { showSuccessMessage: true })
}

View File

@ -109,6 +109,7 @@ const getCloudBuildLogFn = () => {
if (showDialog.value && cloudBuildLog.length) {
active.value = 'complete'
terminalRef.value.execute('clear')
clearCloudBuildTask()
}
notificationEl && notificationEl.close()
cloudBuildTask.value = null

View File

@ -8,7 +8,7 @@
本次升级将从<span class="font-bold">{{ upgradeContent.version }}</span>升级到<span class="font-bold">{{ upgradeContent.upgrade_version }}</span>版本
</div>
<div class="mt-[10px]" v-if="upgradeContent.upgrade_version != upgradeContent.last_version">
<el-alert type="info" show-icon >
<el-alert type="info" show-icon>
<template #title>
当前最新版本为{{ upgradeContent.last_version }}您的服务已于{{ upgradeContent.expire_time }}到期如需升级到最新版可在<a class="text-primary" href="https://www.niucloud.com" target="_blank">niucloud-admin官网</a>购买相关服务后再进行升级
</template>
@ -22,7 +22,7 @@
</div>
</el-scrollbar>
</div>
<div class="flex justify-end">
<div class="flex justify-end" v-if="upgradeContent.version_list.length">
<el-button type="primary" @click="handleUpgrade" :loading="uploading">{{ t('upgrade.upgradeButton') }}</el-button>
</div>
</div>
@ -109,20 +109,17 @@
</div>
</template>
</el-dialog>
<cloud-build ref="cloudBuildRef" />
</template>
<script lang="ts" setup>
import { ref, h, watch } from 'vue'
import { t } from '@/lang'
import { getVersions } from '@/app/api/auth'
import { getFrameworkVersionList } from '@/app/api/module'
import { getFrameworkNewVersion } from '@/app/api/module'
import { getUpgradeContent, getUpgradeTask, upgradeAddon, executeUpgrade, preUpgradeCheck, clearUpgradeTask } from '@/app/api/upgrade'
import { Terminal, TerminalFlash } from 'vue-web-terminal'
import 'vue-web-terminal/lib/theme/dark.css'
import { AnyObject } from '@/types/global'
import CloudBuild from '@/app/components/cloud-build/index.vue'
import { ElNotification, ElMessage, ElMessageBox } from 'element-plus'
import Storage from '@/utils/storage'
@ -132,12 +129,11 @@ const upgradeTask = ref<null | AnyObject>(null)
const active = ref('content')
const upgradeCheck = ref<null | AnyObject>(null)
const uploading = ref(false)
const terminalRef = ref(null)
const emits = defineEmits(['complete'])
const cloudBuildRef = ref(null)
const terminalRef: any = ref(null)
const emits = defineEmits(['complete', 'cloudbuild'])
const upgradeTipsShowDialog = ref<boolean>(false)
let upgradeLog = []
let upgradeLog: any = []
/**
* 查询升级任务
*/
@ -172,6 +168,7 @@ const getUpgradeTaskFn = () => {
active.value = 'complete'
notificationEl && notificationEl.close()
emits('complete')
clearUpgradeTask()
return
}
upgradeTask.value = data
@ -210,13 +207,14 @@ const elNotificationClick = () => {
notificationEl && notificationEl.close()
}
const versions = ref('')
const getVersionsInfo = () => {
getVersions().then(res => {
versions.value = res.data.version.version
})
}
getVersionsInfo()
const frameworkVersion = ref('')
getVersions().then(res => {
frameworkVersion.value = res.data.version.version
})
const newFrameworkVersion = ref("")
getFrameworkNewVersion().then(({ data }) => {
newFrameworkVersion.value = data.last_version
})
/**
* 执行升级
@ -247,33 +245,25 @@ const open = (addonKey: string = '') => {
ElMessage({ message: '已有正在执行中的升级任务', type: 'error' })
showDialog.value = true
} else {
getFrameworkVersionList().then(({ data }) => {
const newVersion = data.length ? data[0] : null
if (addonKey && newVersion && newVersion.version_no !== versions.value) {
ElMessage({ message: '存在新版本框架,请先升级框架', type: 'error' })
return
if (addonKey && frameworkVersion.value != newFrameworkVersion.value) {
ElMessage({ message: '存在新版本框架,请先升级框架', type: 'error' })
return
}
getUpgradeContent(addonKey).then(({ data }) => {
upgradeContent.value = data
if (Storage.get('upgradeTipsLock')) {
showDialog.value = true
} else {
getUpgradeContent(addonKey).then(({ data }) => {
upgradeContent.value = data
if (!data.version_list.length) {
ElMessage({ message: '已经是最新版本了', type: 'error' })
return
}
if (Storage.get('upgradeTipsLock')) {
showDialog.value = true
} else {
upgradeTipsShowDialog.value = true
}
}).catch()
upgradeTipsShowDialog.value = true
}
})
}).catch()
}
}
/**
* 升级进度动画
*/
let flashInterval = null
let flashInterval: any = null
const terminalFlash = new TerminalFlash()
const onExecCmd = (key, command, success, failed, name) => {
if (command == '开始升级') {
@ -335,7 +325,7 @@ const clearUpgradeTaskFn = () => {
*/
const handleCloudBuild = () => {
showDialog.value = false
cloudBuildRef.value?.open()
emits('cloudbuild')
}
const upgradeTipsConfirm = (isLock: boolean = false) => {

View File

@ -31,8 +31,7 @@ import useUserStore from '@/stores/modules/user'
const userStore = useUserStore()
const router = useRouter()
//
const saveInfo = reactive({})
const saveInfo: any = reactive({})
const formRef = ref<FormInstance>()
const loading = ref(true)
const dialogVisible = ref(false)
@ -61,7 +60,7 @@ const submitForm = (formEl: FormInstance | undefined) => {
setUserInfo(saveInfo).then((res: any) => {
loading.value = false
dialogVisible.value = false
let data = deepClone(userStore.userInfo)
let data: any = deepClone(userStore.userInfo)
data.head_img = saveInfo.head_img
userStore.setUserInfo(data)
}).catch(() => {

View File

@ -3,7 +3,7 @@
"preview": "预览图",
"copy": "复制",
"clickVisit": "点击访问",
"PCDomainName": "pc域名",
"pCDomainName": "pc域名",
"newInfo": "最新消息",
"isOpen": "是否开启"
}

View File

@ -20,5 +20,6 @@
"customMenu": "自定义菜单",
"wechatTemplate": "模板消息",
"menusEmptyTips": "空菜单,不能保存与发布。",
"reply": "自动回复"
"reply": "自动回复",
"menuUrlErrorTips": "请输入完整的网页链接如https://www.baidu.com"
}

View File

@ -2,5 +2,7 @@
"title": "协议标题",
"type": "协议类型",
"titlePlaceholder": "请输入协议标题",
"contentPlaceholder": "请填写协议内容",
"contentMaxTips": "协议内容字符数应在550000之间",
"content": "内容"
}

View File

@ -1,16 +1,21 @@
{
"logonMode": "普通注册方式",
"isUsername": "账号密码登录",
"isMobile": "手机验证码登录",
"isAuthRegister": "第三方自动注册",
"isBindMobile": "强制绑定手机",
"isUsernameTip": "开启之后可以使用账号+密码进行注册和登录",
"isMobileTip": "开启之后可以使用手机+验证码进行注册和登录",
"isAuthRegisterTip": "开启之后,微信公众号、小程序等第三方平台可以自动注册会员。方便会员自动登录",
"isBindMobileTip": "开启之后,会员通过普通注册方式会强制绑定手机号,同时在相关页面也会引导会员强制绑定手机账号,否则影响功能正常使用,也方便商家进行管理,同时方便会员在不同端口统一账号",
"agreement": "政策协议",
"agreementTips": "注册时服务协议和隐私协议是否进行展示",
"mobileOrUsernameNoEmpty":"普通注册方式至少需启用一种",
"commonSetting": "通用设置",
"tripartiteSetting": "第三方设置"
"commonSetting": "通用设置",
"logonMode": "普通注册方式",
"isUsername": "账号密码登录",
"isUsernameTip": "开启之后可以使用账号+密码进行注册和登录",
"isMobile": "手机验证码登录",
"isMobileTip": "开启之后可以使用手机+验证码进行注册和登录或者快捷登录/注册",
"isBindMobile": "强制绑定手机",
"isBindMobileTip": "开启之后,会员注册时会强制绑定手机号,并且在相关页面也会引导会员强制绑定手机账号,否则将影响功能正常使用,方便会员在不同端口统一账号,也方便商家进行管理",
"agreement": "政策协议",
"agreementTips": "注册时服务协议和隐私协议是否进行展示",
"tripartiteSetting": "第三方设置",
"isAuthRegister": "快捷登录/注册",
"isAuthRegisterTip": "开启之后,微信公众号、小程序等第三方平台可以自动注册会员或者快捷登录/注册会员,方便会员自动登录",
"mobileOrUsernameNoEmpty": "普通注册方式至少需启用一种",
"loginPageSet": "界面设置",
"bgUrl": "背景图",
"bgUrlPlaceholder": "建议图片尺寸750*669像素图片格式jpg、png、jpeg",
"desc": "描述",
"descPlaceholder": "请输入描述"
}

View File

@ -29,5 +29,8 @@
"visitTimePlaceholder":"请输入访问时间",
"createTimePlaceholder":"请输入消息时间",
"buyerNotice": "会员消息",
"messageKey":"消息模版",
"messageInfo":"发送记录详情",
"smsType":"短信类型",
"sellerNotice":"平台消息"
}

View File

@ -5,7 +5,6 @@
"lastLoginIP": "最后登录IP",
"userNamePlaceholder": "请输入账号/用户名",
"detail": "详情",
"siteNum": "站点数量",
"endDate": "结束时间",
"startDate": "开始时间",
"loginTime": "最后登录时间",
@ -19,10 +18,12 @@
"userCreateSiteLimit": "套餐权限",
"siteGroup": "站点套餐",
"siteMonth": "站点效期限",
"siteNum": "站数量",
"siteNum": "数量",
"month": "月",
"siteMonthPlaceholder": "请输入站点效期限",
"siteNumPlaceholder": "请输入建站数量",
"siteMonthCannotLtOne": "站点效期限不能小于1",
"siteNumCannotLtOne": "建站数量不能小于1"
"siteNumCannotLtOne": "建站数量不能小于1",
"userDeleteTips": "确定要删除该用户吗?",
"createSiteNum": "可创建站点数量"
}

View File

@ -61,6 +61,8 @@
"formCheckbox":"复选框",
"formDateTime":"日期",
"formImageSelect":"图片上传",
"formFileSelect":"文件上传",
"formVideoSelect":"视频上传",
"formEditor":"富文本",
"formNumber":"数字框",
"pk":"主键",
@ -140,4 +142,4 @@
"selectType":"下拉类型"
}
}

View File

@ -45,17 +45,14 @@
<el-button class="w-[154px] !h-[48px] mt-[8px]" type="primary" @click="authCodeApproveFn">授权码认证</el-button>
<el-popover ref="getAuthCodeDialog" placement="bottom-start" :width="478" trigger="click" class="mt-[8px]">
<div class="px-[18px] py-[8px]">
<p class="leading-[32px] text-[14px]">您在官方应用市场购买任意一款应用即可获得授权码输入正确授权码认证通过后即可支持在线升级和其它相关服务
</p>
<p class="leading-[32px] text-[14px]">您在官方应用市场购买任意一款应用即可获得授权码输入正确授权码认证通过后即可支持在线升级和其它相关服务</p>
<div class="flex justify-end mt-[36px]">
<el-button class="w-[182px] !h-[48px]" plain @click="market">去应用市场逛逛</el-button>
<el-button class="w-[100px] !h-[48px]" plain @click="getAuthCodeDialog.hide()">关闭</el-button>
</div>
</div>
<template #reference>
<el-button
class="w-[154px] !h-[48px] mt-[8px] !text-[var(--el-color-primary)] hover:!text-[var(--el-color-primary)] !bg-transparent"
plain type="primary">如何获取授权码?</el-button>
<el-button class="w-[154px] !h-[48px] mt-[8px] !text-[var(--el-color-primary)] hover:!text-[var(--el-color-primary)] !bg-transparent" plain type="primary">如何获取授权码?</el-button>
</template>
</el-popover>
</div>
@ -99,7 +96,7 @@
</el-timeline>
</el-card>
<upgrade ref="upgradeRef" />
<upgrade ref="upgradeRef" @cloudbuild="handleCloudBuild"/>
<cloud-build ref="cloudBuildRef" />
</div>
</template>
@ -109,9 +106,10 @@ import { reactive, ref, computed } from 'vue'
import { t } from '@/lang'
import { getVersions } from '@/app/api/auth'
import { getAuthInfo, setAuthInfo, getFrameworkVersionList } from '@/app/api/module'
import { ElMessageBox, FormInstance, FormRules,ElMessage } from 'element-plus'
import { ElMessageBox, FormInstance, FormRules,ElMessage } from 'element-plus'
import Upgrade from '@/app/components/upgrade/index.vue'
import CloudBuild from '@/app/components/cloud-build/index.vue'
import { cloneDeep } from 'lodash-es'
const upgradeRef = ref<any>(null)
const cloudBuildRef = ref<any>(null)
@ -144,7 +142,7 @@ const newVersion:any = computed(() => {
})
const hideAuthCode = (res:any) => {
const authCode = JSON.parse(JSON.stringify(res))
const authCode = cloneDeep(res)
const data = authCode.slice(0, authCode.length / 2) + authCode.slice(authCode.length / 2, authCode.length - 1).replace(/./g, '*')
return data
}

View File

@ -145,7 +145,7 @@ const refreshMenu = () => {
location.reload()
}).catch(() => {})
}).catch(()=>{})
}
/**
* 添加菜单

View File

@ -16,7 +16,7 @@
<el-switch v-model="formData.is_open"/>
</el-form-item>
<el-form-item :label="t('PCDomainName')">
<el-form-item :label="t('pCDomainName')">
<el-input :model-value="formData.request_url" class="input-width" :readonly="true">
<template #append>
<div class="cursor-pointer" @click="copyEvent(formData.request_url)">{{ t('copy') }}</div>

View File

@ -35,8 +35,7 @@
<el-table-column :label="t('response')" min-width="180">
<template #default="{ row }">
<div v-for="(item, index) in row.weapp.content" :key="'a' + index" class="text-left">
{{ item.join(":") }}</div>
<div v-for="(item, index) in row.weapp.content" :key="'a' + index" class="text-left">{{ item.join(":") }}</div>
</template>
</el-table-column>

View File

@ -39,7 +39,7 @@
<script lang="ts" setup>
import { computed, ref } from 'vue'
import { t } from '@/lang'
import { strByteLength } from '@/utils/common'
import { strByteLength, isUrl } from '@/utils/common'
const prop = defineProps({
data: {
@ -84,7 +84,20 @@ const formRules = computed(() => {
}
],
url: [
{ required: !buttonData.value.sub_button || !buttonData.value.sub_button.length, message: t('webpageUrlPlaceholder'), trigger: 'blur' }
{ required: !buttonData.value.sub_button || !buttonData.value.sub_button.length, message: t('webpageUrlPlaceholder'), trigger: 'blur' },
{
validator: (rule: any, value: string, callback: any) => {
if (!buttonData.value.sub_button || !buttonData.value.sub_button.length) {
if (!isUrl(value)) {
callback(new Error(t('menuUrlErrorTips')))
} else {
callback()
}
} else {
callback()
}
}
}
],
appid: [
{ required: ((!buttonData.value.sub_button || !buttonData.value.sub_button.length) && buttonData.value.type == 'miniprogram'), message: t('weappAppidPlaceholder'), trigger: 'blur' }

View File

@ -94,7 +94,7 @@ const router = useRouter()
const pageName = route.meta.title
const showDialog = ref(false)
const formData = reactive<Record<string, string>>({
const formData: any = reactive({
id: 0,
name: '',
keyword: '',

View File

@ -248,7 +248,7 @@ import useDiyStore from '@/stores/modules/diy'
import { ref, reactive, watch, onMounted, nextTick } from 'vue'
import { ElTable } from 'element-plus'
import Sortable from 'sortablejs'
import { range } from 'lodash-es'
import { range,cloneDeep } from 'lodash-es'
import { getDiyPageListByCarouselSearch } from '@/app/api/diy'
@ -427,6 +427,8 @@ const loadDiyPageList = (page: number = 1) => {
newData.push(data[i]);
}
}
} else {
newData = cloneDeep(data); //
}
if (isExistCount) {
res.data.total = res.data.total - isExistCount;

View File

@ -74,7 +74,7 @@
</div>
</div>
<el-button v-show="diyStore.editComponent.list.length < 10" class="w-full" @click="addGraphicNav">{{ t('addGraphicNav') }}</el-button>
<el-button v-show="diyStore.editComponent.list.length < 50" class="w-full" @click="addGraphicNav">{{ t('addGraphicNav') }}</el-button>
</el-form>
</div>

View File

@ -54,12 +54,12 @@
<el-button class="page-btn absolute right-[20px]" @click="diyStore.changeCurrentIndex(-99)">{{ t('pageSet') }}</el-button>
<div class="diy-view-wrap w-[375px] shadow-lg mx-auto">
<div class="preview-head bg-no-repeat bg-center bg-cover cursor-pointer h-[64px]" :class="[diyStore.global.topStatusBar.style]" :style="{backgroundColor :diyStore.global.topStatusBar.bgColor}" @click="diyStore.changeCurrentIndex(-99)">
<div v-if="diyStore.global.topStatusBar.style == 'style-1'" class="content-wrap">
<div v-if="diyStore.global.topStatusBar.style == 'style-1' && diyStore.global.topStatusBar.isShow" class="content-wrap">
<div class="title-wrap" :style="{ fontSize: '14px', color: diyStore.global.topStatusBar.textColor, textAlign: diyStore.global.topStatusBar.textAlign }">
{{ diyStore.global.title }}
</div>
</div>
<div v-if="diyStore.global.topStatusBar.style == 'style-2'" class="content-wrap">
<div v-if="diyStore.global.topStatusBar.style == 'style-2' && diyStore.global.topStatusBar.isShow" class="content-wrap">
<div class="title-wrap" :style="{ color: diyStore.global.topStatusBar.textColor }">
<div class="h-[28px] max-w-[150px] mr-[8px]" v-if="diyStore.global.topStatusBar.imgUrl">
<img class="max-w-[100%] max-h-[100%]" :src="img(diyStore.global.topStatusBar.imgUrl)" mode="heightFix" />
@ -67,16 +67,16 @@
<div :style="{ color: diyStore.global.topStatusBar.textColor }">{{ diyStore.global.title }}</div>
</div>
</div>
<div v-if="diyStore.global.topStatusBar.style == 'style-3'" class="content-wrap">
<div v-if="diyStore.global.topStatusBar.style == 'style-3' && diyStore.global.topStatusBar.isShow" class="content-wrap">
<div class="title-wrap" v-if="diyStore.global.topStatusBar.imgUrl">
<img class="max-w-[100%] max-h-[100%]" :src="img(diyStore.global.topStatusBar.imgUrl)" />
</div>
<div class="search">
<span class="iconfont iconsousuo absolute left-[10px]"></span>
<span class="text-[14px]">{{diyStore.global.topStatusBar.inputPlaceholder}}</span>
<span class="nc-iconfont nc-icon-sousuo-duanV6xx1 !text-[12px] absolute left-[10px]"></span>
<span class="text-[12px]">{{diyStore.global.topStatusBar.inputPlaceholder}}</span>
</div>
</div>
<div v-if="diyStore.global.topStatusBar.style == 'style-4'" class="content-wrap">
<div v-if="diyStore.global.topStatusBar.style == 'style-4' && diyStore.global.topStatusBar.isShow" class="content-wrap">
<span class="iconfont iconxiazai19 !text-[14px]" :style="{ color: diyStore.global.topStatusBar.textColor }"></span>
<div class="title-wrap" :style="{ color: diyStore.global.topStatusBar.textColor }">我的位置</div>
<span class="iconfont iconxiangyoujiantou !text-[12px]" :style="{ color: diyStore.global.topStatusBar.textColor }"></span>
@ -337,15 +337,14 @@ const changeTemplatePage = (value:any)=> {
type: 'warning'
}).then(() => {
diyStore.changeCurrentIndex(-99)
diyStore.init(); //
if (value) {
let data = templatePages[value].data;
let data = cloneDeep(templatePages[value].data);
diyStore.global = data.global;
if (data.value.length) {
diyStore.value = data.value
}
} else {
//
diyStore.init();
if (route.query.title) diyStore.global.title = diyStore.typeName
}
}).catch(() => {
@ -353,15 +352,14 @@ const changeTemplatePage = (value:any)=> {
template.value = oldTemplate.value;
});
} else {
diyStore.init(); //
if (value) {
let data = templatePages[value].data;
let data = cloneDeep(templatePages[value].data);
diyStore.global = data.global;
if (data.value.length) {
diyStore.value = data.value
}
} else {
//
diyStore.init();
if (route.query.title) diyStore.global.title = diyStore.typeName
}
}
@ -793,6 +791,7 @@ const settingTips = () => {
align-items: center;
margin-right: 105px;
overflow: hidden;
box-sizing: border-box;
span {
overflow: hidden; //

View File

@ -80,7 +80,7 @@ const page: any = reactive({})
const router = useRouter()
const wapDomain = ref('')
const wapImage = ref('')
const link = ref({
const link: any = ref({
name: ''
})

View File

@ -105,7 +105,7 @@ const page: any = reactive({})
const router = useRouter()
const wapDomain = ref('')
const wapImage = ref('')
const link = ref({
const link: any = ref({
name: ''
})

View File

@ -42,6 +42,7 @@
import { t } from '@/lang'
import { getDiyBottomList } from '@/app/api/diy'
import { useRoute, useRouter } from 'vue-router'
import { cloneDeep } from 'lodash-es'
const route = useRoute()
const router = useRouter()
@ -64,7 +65,7 @@
bottomNavTableData.loading = false
const len = Math.ceil(res.data.length / bottomNavTableData.limit)
const data = JSON.parse(JSON.stringify(res.data))
const data = cloneDeep(res.data)
const dataGather = []
for (let i = 0; i < len; i++) {
dataGather[i] = data.splice(0, bottomNavTableData.limit)

View File

@ -114,7 +114,6 @@ const formRules = computed(() => {
return {
label_name: [
{ required: true, message: t('labelNamePlaceholder'), trigger: 'blur' }
]
}
})

View File

@ -1,5 +1,5 @@
<template>
<div class="main-container w-full pt-[64px] " v-loading="loading">
<div class="main-container w-full pt-[64px]" v-loading="loading">
<div class="flex justify-between items-center h-[32px] mb-4">
<span class="text-page-title">{{ t('editPersonal') }}</span>
</div>

View File

@ -35,8 +35,7 @@
<div class="min-h-[580px]">
<div class="flex flex-wrap mt-[30px]" v-loading="loading">
<div v-for="(item, index) in tableData" :key="index" @click="selectSite(item)"
:class="['home-item w-[285px] box-border mb-[20px] cursor-pointer',{'mr-[20px]': index ==0 || (index+1)%4 != 0}]">
<div v-for="(item, index) in tableData" :key="index" @click="selectSite(item)" :class="['home-item w-[285px] box-border mb-[20px] cursor-pointer',{'mr-[20px]': index ==0 || (index+1)%4 != 0}]">
<div class="flex items-center px-[24px] pt-[22px] pb-[16px] bg-[#F0F2F4] home-item-head relative">
<div class="absolute h-[5px] w-full z-1 left-0 top-0" :style="{'background-color': item.theme_color}" v-if="item.theme_color"></div>
<img v-if="item.icon" class="w-[48px] h-[48px] mr-[15px] rounded-[50%] overflow-hidden" :src="img(item.icon)" />

View File

@ -164,7 +164,7 @@ const statInfo = ref<StatInfo>({
app: {}
})
const getStatInfoFn = async (id: number = 0) => {
const getStatInfoFn = async () => {
statInfo.value = await (await getStatInfo()).data
loading.value = false
setTimeout(() => {

View File

@ -135,7 +135,7 @@
</p>
</template>
</el-empty>
<div v-if="!localList.all.length && !loading && !authinfo && activeName == 'all'&&!authLoading" class="mx-auto overview-empty flex flex-col items-center pt-14 pb-6">
<div v-if="!localList.all.length && !loading && !authinfo && activeName == 'all' && !authLoading" class="mx-auto overview-empty flex flex-col items-center pt-14 pb-6">
<div class="mb-[20px] text-sm text-[#888]">检测到当前账号尚未绑定授权请先绑定授权</div>
<div class="flex flex-1 flex-wrap justify-center relative">
<el-button class="w-[154px] !h-[48px] mt-[8px]" type="primary" @click="authCodeApproveFn">授权码认证</el-button>
@ -154,7 +154,7 @@
</el-popover>
</div>
</div>
<el-empty class="mx-auto overview-empty" v-if="!localList.all.length && !loading && authinfo && activeName == 'all'&&!authLoading">
<el-empty class="mx-auto overview-empty" v-if="!localList.all.length && !loading && authinfo && activeName == 'all' && !authLoading">
<template #image>
<div class="w-[230px] mx-auto">
<img src="@/app/assets/images/index/apply_empty.png" class="max-w-full" alt="">
@ -366,7 +366,7 @@
</el-card>
</div>
<upgrade ref="upgradeRef" @complete="localListFn"/>
<upgrade ref="upgradeRef" @complete="localListFn" @cloudbuild="handleCloudBuild"/>
<cloud-build ref="cloudBuildRef" />
</template>
@ -687,25 +687,23 @@ const authElMessageBox = () => {
let installLog: string[] = []
const getCloudInstallLog = () => {
getAddonCloudInstallLog(currAddon.value)
.then(res => {
const data = res.data.data ?? []
if (data[0] && data[0].length && installShowDialog.value == true) {
data[0].forEach(item => {
if (!installLog.includes(item.action)) {
terminalRef.value.pushMessage({ content: `正在执行:${item.action}` })
installLog.push(item.action)
getAddonCloudInstallLog(currAddon.value).then(res => {
const data = res.data.data ?? []
if (data[0] && data[0].length && installShowDialog.value == true) {
data[0].forEach(item => {
if (!installLog.includes(item.action)) {
terminalRef.value.pushMessage({ content: `正在执行:${ item.action }` })
installLog.push(item.action)
if (item.code == 0) {
terminalRef.value.pushMessage({ content: item.msg, class: 'error' })
}
if (item.code == 0) {
terminalRef.value.pushMessage({ content: item.msg, class: 'error' })
}
})
}
})
.catch(() => {
notificationEl?.close()
})
}
})
}
}).catch(() => {
notificationEl?.close()
})
}
watch(currAddon, (nval) => {
@ -805,11 +803,14 @@ const installShowDialogClose = (done: () => {}) => {
).then(() => {
cancelInstall(currAddon.value)
done()
}).catch(() => { })
}).catch(() => {
})
} else if (installStep.value == 3) {
activeNameTabFn('installed')
location.reload()
} else done()
} else {
done()
}
flashInterval && clearInterval(flashInterval)
}
@ -866,20 +867,18 @@ const formRules = reactive<FormRules>({
const save = async (formEl: FormInstance | undefined) => {
if (saveLoading.value || !formEl) return
await formEl.validate(async (valid) => {
await formEl.validate(async(valid) => {
if (valid) {
saveLoading.value = true
setAuthInfo(formData)
.then(() => {
saveLoading.value = false
setTimeout(() => {
location.reload()
}, 1000)
})
.catch(() => {
saveLoading.value = false
})
setAuthInfo(formData).then(() => {
saveLoading.value = false
setTimeout(() => {
location.reload()
}, 1000)
}).catch(() => {
saveLoading.value = false
})
}
})
}

View File

@ -14,9 +14,7 @@
<h3 class="text-center text-2xl font-bold mb-[26px]">{{ t('platform') }}</h3>
<el-form :model="form" ref="formRef" :rules="formRules">
<el-form-item prop="username">
<el-input v-model="form.username" :placeholder="t('userPlaceholder')"
autocomplete="off"
@keyup.enter="handleLogin(formRef)" class="h-[40px] input-with-select">
<el-input v-model="form.username" :placeholder="t('userPlaceholder')" autocomplete="off" @keyup.enter="handleLogin(formRef)" class="h-[40px] input-with-select">
<template #prepend>
<icon name="element User" />
</template>
@ -162,7 +160,7 @@ const form = reactive({
//
const loginConfig = ref(null)
const getLoginConfigFn = async (id: number = 0) => {
const getLoginConfigFn = async () => {
imgLoading.value = true
const data = await (await getLoginConfig()).data
loginConfig.value = data

View File

@ -116,6 +116,7 @@ import signDay from '@/app/views/marketing/components/sign-day.vue'
import signContinue from '@/app/views/marketing/components/sign-continue.vue'
import { FormInstance, FormRules } from 'element-plus'
import { useRoute } from 'vue-router'
import { cloneDeep } from 'lodash-es'
const route = useRoute()
const pageName = route.meta.title
@ -188,11 +189,11 @@ const setFormData = async () => {
if (formData.continue_award) {
formData.continue_award.forEach((item: any, index: number) => {
continueSignAwardTableData.data.push(JSON.parse(JSON.stringify(item)))
continueSignAwardTableData.data.push(cloneDeep(item))
contentData.gifts = [];
const val = JSON.parse(JSON.stringify(item))
const val = cloneDeep(item)
delete val['continue_sign'];
delete val['continue_tag'];
@ -242,12 +243,12 @@ const setMemberBenefitsContents = async (content: any, item: any, index: number
if (!isEdit) {
if (tag == 0) {
continueSignAwardTableData.data.splice(index, 1, JSON.parse(JSON.stringify(newArr)))
continueSignAwardTableData.data.splice(index, 1, cloneDeep(newArr))
} else {
continueSignAwardTableData.data.push(JSON.parse(JSON.stringify(newArr)))
continueSignAwardTableData.data.push(cloneDeep(newArr))
}
} else {
continueSignAwardTableData.data.splice(editIndex, 1, JSON.parse(JSON.stringify(newArr)))
continueSignAwardTableData.data.splice(editIndex, 1, cloneDeep(newArr))
}
isEdit = false
@ -262,7 +263,7 @@ const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate((valid) => {
if (valid) {
const save = JSON.parse(JSON.stringify(formData))
const save = cloneDeep(formData)
setSignConfig(save).then(() => {
loading.value = false
}).catch(() => {
@ -334,7 +335,7 @@ const setContinueSignAward = async () => {
}
if (Object.keys(continue_award.value).length > 0) {
const val = JSON.parse(JSON.stringify(continue_award.value))
const val = cloneDeep(continue_award.value)
delete val['continue_sign'];
delete val['continue_tag'];
@ -351,9 +352,9 @@ const setContinueSignAward = async () => {
setMemberBenefitsContents(contentData, continue_award.value, 0, 1)
if (!isEdit) {
formData.continue_award.push(JSON.parse(JSON.stringify(continue_award.value)))
formData.continue_award.push(cloneDeep(continue_award.value))
} else {
formData.continue_award.splice(editIndex, 1, JSON.parse(JSON.stringify(continue_award.value)))
formData.continue_award.splice(editIndex, 1, cloneDeep(continue_award.value))
}
}
}

View File

@ -57,11 +57,8 @@
<el-dialog v-model="showDialog" :title="t('addVerifier')" width="500px" :destroy-on-close="true">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form" v-loading="addLoading">
<el-form-item :label="t('member')" prop="member_id">
<el-select v-model="formData.member_id" filterable remote reserve-keyword clearable
:placeholder="t('searchPlaceholder')" :remote-method="searchMember" :loading="searchLoading"
class="input-width">
<el-option v-for="item in memberList" :key="item.member_id" :label="item.nickname"
:value="item.member_id" />
<el-select v-model="formData.member_id" filterable remote reserve-keyword clearable :placeholder="t('searchPlaceholder')" :remote-method="searchMember" :loading="searchLoading" class="input-width">
<el-option v-for="item in memberList" :key="item.member_id" :label="item.nickname" :value="item.member_id" />
</el-select>
</el-form-item>
<el-form-item :label="t('verifyType')" prop="verify_type">

View File

@ -59,7 +59,7 @@
<el-form-item :label="t('fromType')" prop="from_type">
<el-select v-model="memberAccountLogTableData.searchParam.from_type" clearable :placeholder="t('fromTypePlaceholder')" class="input-width">
<el-option :label="t('selectPlaceholder')" value="" />
<el-option :label="item.name" :value="key" v-for="(item, key) in fromTypeList" :key="key"/>
<el-option :label="item.name" :value="key" v-for="(item, key) in fromTypeList" :key="key"/>
</el-select>
</el-form-item>
<el-form-item :label="t('createTime')" prop="create_time">

View File

@ -162,7 +162,7 @@ const memberAccountLogTableData = reactive({
from_type: '',
create_time: '',
mobile: '',
member_id: member_id
member_id
}
})

View File

@ -106,7 +106,7 @@ const memberAccountLogTableData = reactive({
from_type: '',
create_time: '',
mobile: '',
member_id: memberId
member_id
}
})

View File

@ -130,7 +130,7 @@
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { img } from '@/utils/common'
import { addMember, getRegisterChannelType, getMemberList, getMemberLabelAll, editMemberStatus, deleteMember, getMemberLevelAll } from '@/app/api/member'
import { getRegisterChannelType, getMemberList, getMemberLabelAll, editMemberStatus, deleteMember, getMemberLevelAll } from '@/app/api/member'
import { ElMessageBox, FormInstance } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
import AddMember from '@/app/views/member/components/add-member.vue'

View File

@ -194,7 +194,6 @@
</el-form-item>
</template>
<!-- <el-form-item :label="t('旋转角度')">-->
<!-- <el-slider v-model="posterStore.editComponent.angle" show-input size="small" class="ml-[10px]" :min="0" :max="360" />-->
<!-- </el-form-item>-->
@ -249,7 +248,6 @@ if(route && route.query){
route.query.back = route.query.back || '/site/poster/list'
}
const backPath:any = route.query.back
const template = ref('');
const oldTemplate = ref('');
@ -262,8 +260,8 @@ const activeNames = ref(componentType)
const handleChange = (val: string[]) => {
}
const previewIframeStyle = (data)=>{
let style = {
const previewIframeStyle = (data: any)=>{
let style: any = {
transform: '',
zIndex: '',
top: '',
@ -323,6 +321,7 @@ const xAlignList = ref([
className: 'right'
}
])
//
const yAlignList = ref([
{
@ -341,9 +340,8 @@ const yAlignList = ref([
className: 'bottom'
},
])
const alignChangeFn = (type,data)=>{
const alignChangeFn = (type: any,data: any)=>{
posterStore.editComponent[type] = data.className;
}
//

View File

@ -151,7 +151,7 @@ const addEvent = async (formEl: FormInstance | undefined) => {
}
//
const loadPosterType = (addon = '')=> {
const loadPosterType = ()=> {
getPosterType({}).then((res:any)=>{
for (let key in posterType) {
delete posterType[key];

View File

@ -6,7 +6,7 @@
<h3 class="panel-title !text-sm">{{ t('admin') }}</h3>
<el-form-item :label="t('isCaptcha')" prop="formData.is_auth_register">
<el-switch v-model="formData.is_captcha"/>
<el-switch v-model="formData.is_captcha" :active-value="1" :inactive-value="0" />
</el-form-item>
<el-form-item :label="t('bgImg')">
<upload-image v-model="formData.bg" />
@ -18,7 +18,7 @@
<h3 class="panel-title !text-sm">{{ t('site') }}</h3>
<el-form-item :label="t('isCaptcha')" prop="formData.is_auth_register">
<el-switch v-model="formData.is_site_captcha"/>
<el-switch v-model="formData.is_site_captcha" :active-value="1" :inactive-value="0" />
</el-form-item>
<el-form-item :label="t('bgImg')">
<upload-image v-model="formData.site_bg" />
@ -41,6 +41,7 @@ import { t } from '@/lang'
import { getConfigLogin, setConfigLogin } from '@/app/api/sys'
import { FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
import { cloneDeep } from 'lodash-es'
const route = useRoute()
const pageName = route.meta.title
@ -54,11 +55,10 @@ const formData = reactive<Record<string, number | string>>({
site_bg: ''
})
const getFormData = async (id: number = 0) => {
const getFormData = async () => {
const data = await (await getConfigLogin()).data
Object.keys(formData).forEach((key: string) => {
if (['is_captcha', 'is_site_captcha'].includes(key)) formData[key] = Boolean(Number(data[key]))
else formData[key] = data[key]
formData[key] = data[key]
})
loading.value = false
}
@ -68,10 +68,7 @@ const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate((valid) => {
if (valid) {
const save = JSON.parse(JSON.stringify(formData))
Object.keys(save).forEach((key) => {
if (['is_captcha', 'is_site_captcha'].includes(key)) save[key] = Number(save[key])
})
const save = cloneDeep(formData)
setConfigLogin(save).then(() => {
loading.value = false

View File

@ -13,7 +13,7 @@
<el-form-item :label="t('title')" prop="title">
<el-input v-model.trim="formData.title" clearable :placeholder="t('titlePlaceholder')" class="input-width" maxlength="20" />
</el-form-item>
<el-form-item :label="t('content')">
<el-form-item :label="t('content')" prop="content">
<editor v-model="formData.content" />
</el-form-item>
</el-form>
@ -73,7 +73,23 @@ const formRules = computed(() => {
return {
title: [
{ required: true, message: t('titlePlaceholder'), trigger: 'blur' }
]
],
content: [
{
required: true,
trigger: ['blur', 'change'],
validator: (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error(t('contentPlaceholder')))
} else if (value.length < 5 || value.length > 50000) {
callback(new Error(t('contentMaxTips')))
return false
} else {
callback()
}
}
}
]
}
})

View File

@ -11,7 +11,7 @@
<el-card class="box-card !border-none" shadow="never">
<el-form-item :label="t('isOpen')">
<el-switch v-model="formData.is_open" />
<el-switch v-model="formData.is_open" active-value="1" inactive-value="0" />
</el-form-item>
<el-form-item :label="t('cashWithdrawalAmount')" v-if="formData.is_open" prop="min">
@ -67,7 +67,7 @@ const pageName = route.meta.title
const loading = ref(true)
const ruleFormRef = ref<FormInstance>()
const formData = reactive<Record<string, string | boolean | Array<string> >>({
const formData = reactive({
is_auto_transfer: '0',
is_auto_verify: '0',
is_open: '0',
@ -84,12 +84,11 @@ const getTransfertypeFn = async () => {
getTransfertypeFn()
//
const setFormData = async (id: number = 0) => {
const setFormData = async () => {
const data = await (await getCashOutConfig()).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
formData.is_open = Boolean(Number(formData.is_open))
loading.value = false
}
setFormData()
@ -124,7 +123,6 @@ const onSave = async (formEl: FormInstance | undefined) => {
await formEl.validate((valid) => {
if (valid) {
const save = { ...formData }
save.is_open = Number(save.is_open).toString()
setCashOutConfig(save).then(() => {
loading.value = false

View File

@ -7,19 +7,23 @@
</el-form-item>
<el-form-item :label="t('smsType')">
<div class="input-width"> {{ formData.sms_type_name }} </div>
<div class="input-width">
<div v-if="formData.notice_type == 'sms'">{{ t('sms') }}</div>
<div v-if="formData.notice_type == 'wechat'">{{ t('wechat') }}</div>
<div v-if="formData.notice_type == 'weapp'">{{ t('weapp') }}</div>
</div>
</el-form-item>
<!-- <el-form-item :label="t('messageData')">
<div class="input-width"> {{ formData.message_data }} </div>
</el-form-item> -->
<!-- <el-form-item :label="t('nickname')">
<el-form-item :label="t('nickname')">
<div class="input-width"> {{ formData.nickname }} </div>
</el-form-item> -->
</el-form-item>
<el-form-item :label="t('receiver')">
<div class="input-width"> {{ formData.mobile }} </div>
<div class="input-width"> {{ formData.receiver }} </div>
</el-form-item>
<el-form-item :label="t('createTime')">
@ -54,8 +58,8 @@ const initialFormData = {
message_type: '',
name: '',
nickname: '',
mobile: '',
sms_type_name: ''
receiver: '',
notice_type: ''
}
const formData: Record<string, any> = reactive({ ...initialFormData })

View File

@ -0,0 +1,90 @@
<template>
<el-dialog v-model="showDialog" :title="t('messageInfo')" width="550px" :destroy-on-close="true">
<el-form :model="formData" label-width="110px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('messageKey')">
<div class="input-width"> {{ formData.name }} </div>
</el-form-item>
<el-form-item :label="t('smsType')">
<div class="input-width"> {{ formData.sms_type_name }} </div>
</el-form-item>
<!-- <el-form-item :label="t('messageData')">
<div class="input-width"> {{ formData.message_data }} </div>
</el-form-item> -->
<!-- <el-form-item :label="t('nickname')">
<div class="input-width"> {{ formData.nickname }} </div>
</el-form-item> -->
<el-form-item :label="t('receiver')">
<div class="input-width"> {{ formData.mobile }} </div>
</el-form-item>
<el-form-item :label="t('createTime')">
<div class="input-width"> {{ formData.create_time }} </div>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="showDialog = false">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
const showDialog = ref(false)
const loading = ref(true)
/**
* 表单数据
*/
const initialFormData = {
create_time: 0,
message_data: '',
message_key: '',
message_type: '',
name: '',
nickname: '',
mobile: '',
sms_type_name: ''
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
}
})
const setFormData = async (row: any = null) => {
loading.value = true
Object.assign(formData, initialFormData)
if (row) {
Object.keys(formData).forEach((key: string) => {
if (row[key] != undefined) formData[key] = row[key]
})
}
loading.value = false
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>

View File

@ -68,7 +68,7 @@ const formData = reactive<Record<string, string>>({
copyright_desc: ''
})
const setFormData = async (id: number = 0) => {
const setFormData = async () => {
const data = await (await getCopyright()).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]

View File

@ -32,7 +32,7 @@ const formData = ref({
getDeveloperToken().then(({ data }) => {
loading.value = false
data.token && (formData.value = data)
}).catch()
})
const formRef = ref<FormInstance>()

View File

@ -106,7 +106,7 @@ getInstalledAddonList().then(({ data }) => {
item.type == 'app' && addonList.value.push(item)
})
loading.value = false
}).catch()
})
const getLayoutConfig = () => {
getLayout().then(({ data }) => {

View File

@ -6,19 +6,19 @@
<h3 class="panel-title !text-sm">{{ t('commonSetting') }}</h3>
<el-form-item :label="t('logonMode')" prop="type">
<el-checkbox v-model="formData.is_username" :label="t('isUsername')" @change="switchChange($event, 'is_username')" />
<div class="form-tip">{{ t('isUsernameTip') }}</div>
<el-checkbox v-model="formData.is_mobile" :label="t('isMobile')" @change="switchChange($event, 'is_mobile')" />
<el-checkbox v-model="formData.is_username" :true-value="1" :false-value="0" :label="t('isUsername')" />
<div class="form-tip mb-[10px]">{{ t('isUsernameTip') }}</div>
<el-checkbox v-model="formData.is_mobile" :true-value="1" :false-value="0" :label="t('isMobile')" />
<div class="form-tip">{{ t('isMobileTip') }}</div>
</el-form-item>
<el-form-item :label="t('isBindMobile')" prop="formData.is_bind_mobile">
<el-switch v-model="formData.is_bind_mobile" @change="switchChange($event, 'is_bind_mobile')" />
<el-switch v-model="formData.is_bind_mobile" :active-value="1" :inactive-value="0" />
<div class="form-tip">{{ t('isBindMobileTip') }}</div>
</el-form-item>
<el-form-item :label="t('agreement')" prop="formData.agreement_show">
<el-switch v-model="formData.agreement_show" @change="switchChange($event, 'agreement_show')" />
<el-switch v-model="formData.agreement_show" :active-value="1" :inactive-value="0" />
<div class="form-tip">{{ t('agreementTips') }}</div>
</el-form-item>
</el-card>
@ -27,10 +27,24 @@
<h3 class="panel-title !text-sm">{{ t('tripartiteSetting') }}</h3>
<el-form-item :label="t('isAuthRegister')" prop="formData.is_auth_register">
<el-switch v-model="formData.is_auth_register" @change="switchChange($event, 'is_auth_register')" />
<el-switch v-model="formData.is_auth_register" :active-value="1" :inactive-value="0" />
<div class="form-tip">{{ t('isAuthRegisterTip') }}</div>
</el-form-item>
</el-card>
<el-card class="box-card mt-[15px] !border-none" shadow="never">
<h3 class="panel-title !text-sm">{{ t('loginPageSet') }}</h3>
<el-form-item :label="t('bgUrl')">
<div>
<upload-image v-model="formData.bg_url" />
<p class="text-[12px] text-[#a9a9a9]">{{ t('bgUrlPlaceholder') }}</p>
</div>
</el-form-item>
<el-form-item :label="t('desc')">
<el-input v-model="formData.desc" :placeholder="t('descPlaceholder')" class="input-width" clearable maxlength="20" show-word-limit />
</el-form-item>
</el-card>
</el-form>
<div class="fixed-footer-wrap">
@ -47,18 +61,22 @@ import { t } from '@/lang'
import { getLoginConfig, setLoginConfig } from '@/app/api/member'
import { FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
import { cloneDeep } from 'lodash-es'
const route = useRoute()
const pageName = route.meta.title
const loading = ref(true)
const ruleFormRef = ref<FormInstance>()
const formData = reactive<Record<string, number | boolean>>({
const formData:any = reactive({
is_username: 0,
is_mobile: 0,
is_auth_register: 0,
is_bind_mobile: 0,
agreement_show: 0
agreement_show: 0,
bg_url: '',
logo: '',
desc: ''
})
const formRules = computed(() => {
@ -79,27 +97,20 @@ const formRules = computed(() => {
}
})
const setFormData = async (id: number = 0) => {
const setFormData = async () => {
const data = await (await getLoginConfig()).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = Boolean(Number(data[key]))
if (data[key] != undefined) formData[key] = data[key]
})
loading.value = false
}
setFormData()
const switchChange = (val, key) => {
formData[key] = val
}
const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate((valid) => {
if (valid) {
const save = JSON.parse(JSON.stringify(formData))
Object.keys(save).forEach((key) => {
save[key] = Number(save[key])
})
const save = cloneDeep(formData)
setLoginConfig(save).then(() => {
loading.value = false

View File

@ -40,7 +40,7 @@ import { FormInstance } from 'element-plus'
const loading = ref(false)
const formRef = ref<FormInstance>()
const formData = reactive<Record<string, string>>({
const formData = reactive({
key: '',
is_open: 1,
valid_time: 0

View File

@ -46,25 +46,19 @@
<el-table-column :label="t('operation')" align="right" fixed="right" min-width="300">
<template #default="{ row }">
<div class="flex">
<div class="text-sm mr-1 flex items-center cursor-pointer"
v-if="row.support_type.indexOf('sms') != -1"
@click="setNotice(row, 'sms')">
<div class="text-sm mr-1 flex items-center cursor-pointer" v-if="row.support_type.indexOf('sms') != -1" @click="setNotice(row, 'sms')">
<el-icon class="text-[15px] mr-[3px]" :class="row.is_sms ? 'open' : ''">
<SuccessFilled />
</el-icon>
<span class="ml-0.5">{{ t('sms') }}</span>
</div>
<div class="text-sm flex items-center cursor-pointer ml-[20px]"
v-if="row.support_type.indexOf('wechat') != -1"
@click="setNotice(row, 'wechat')">
<div class="text-sm flex items-center cursor-pointer ml-[20px]" v-if="row.support_type.indexOf('wechat') != -1" @click="setNotice(row, 'wechat')">
<el-icon class="text-[15px] mr-[3px]" :class="row.is_wechat ? 'open' : ''">
<SuccessFilled />
</el-icon>
<span class="ml-0.5">{{ t('wechat') }}</span>
</div>
<div class="text-sm flex items-center cursor-pointer ml-[20px]"
v-if="row.support_type.indexOf('weapp') != -1"
@click="setNotice(row, 'weapp')">
<div class="text-sm flex items-center cursor-pointer ml-[20px]" v-if="row.support_type.indexOf('weapp') != -1" @click="setNotice(row, 'weapp')">
<el-icon class="text-[15px] mr-[3px]" :class="row.is_weapp ? 'open' : ''">
<SuccessFilled />
</el-icon>
@ -135,7 +129,6 @@ const loadNoticeList = () => {
})
noticeTableData.loading = false
}).catch((e) => {
console.log(e)
noticeTableData.loading = false
})
}

View File

@ -15,7 +15,6 @@
<el-form-item :label="t('noticeKey')" prop="key">
<el-select v-model="recordsTableData.searchParam.key" clearable :placeholder="t('noticeKeyPlaceholder')" class="input-width" popper-class="notice">
<el-option :label="t('selectPlaceholder')" value="" />
<el-option-group v-for="(group, gindex) in templateList" :key="gindex" :label="group.label">
<el-option :label="item.name" :value="item.value" :disabled="item.disabled ?? false" v-for="(item, index) in group.list" :key="index" />
</el-option-group>
@ -28,7 +27,7 @@
<el-form-item>
<el-button type="primary" @click="loadNoticeLogList()">{{ t('search') }}</el-button>
<el-button @click="searchFormRef?.resetFields()">{{ t('reset') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
@ -76,7 +75,7 @@
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getNoticeList } from '@/app/api/notice'
import { getNoticeLog, getNoticeList } from '@/app/api/notice'
import RecordsInfo from '@/app/views/setting/components/notice-records-info.vue'
import { FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
@ -145,7 +144,7 @@ const loadNoticeLogList = (page: number = 1) => {
recordsTableData.loading = true
recordsTableData.page = page
getNoticeList({
getNoticeLog({
page: recordsTableData.page,
limit: recordsTableData.limit,
...recordsTableData.searchParam
@ -159,6 +158,12 @@ const loadNoticeLogList = (page: number = 1) => {
}
loadNoticeLogList()
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadNoticeLogList()
}
const recordsDialog: Record<string, any> | null = ref(null)
/**

View File

@ -31,7 +31,7 @@
</div>
</div>
<div class="flex items-center justify-center w-[110px] select-none">
<el-switch v-if="isEdit" v-model="childrenItem.status" :active-text="t('isEnable')" @change="enablePaymentMode(childrenItem)" />
<el-switch v-if="isEdit" v-model="childrenItem.status" :active-value="1" :inactive-value="0" :active-text="t('isEnable')" @change="enablePaymentMode(childrenItem)" />
<div v-else>
<el-tag v-if="childrenItem.status" class="ml-2" type="success">{{ t('open') }}</el-tag>
<el-tag v-else class="ml-2" type="info">{{ t('notOpen') }}</el-tag>
@ -69,6 +69,7 @@ import { img } from '@/utils/common'
import { ElMessage } from 'element-plus'
import Sortable, { SortableEvent } from 'sortablejs'
import { useRoute } from 'vue-router'
import { cloneDeep } from 'lodash-es'
const route = useRoute()
const pageName = route.meta.title
@ -109,8 +110,6 @@ const checkPayConfigList = () => {
if (item.is_default == 1) {
default_key = item.redio_key
}
item.status = Boolean(item.status)
pay_type.push(item)
})
@ -144,13 +143,13 @@ const configPayFn = (data:any) => {
}
//
const enablePaymentMode = async (data: object) => {
const enablePaymentMode = async (data: any) => {
if (payTypeRefs.value[data.key] && typeof payTypeRefs.value[data.key].enableVerify == 'function') {
payTypeRefs.value[data.key].setFormData(data)
const verify = payTypeRefs.value[data.key].enableVerify()
if (!verify) {
data.status = false
data.status = 0
ElMessage(t('configurePaymentMethod'))
return false
}
@ -193,11 +192,10 @@ const sortableFn = (item, index) => {
//
const saveFn = () => {
payLoading.value = true
const data = JSON.parse(JSON.stringify(payConfigData.value))
const data = cloneDeep(payConfigData.value)
Object.values(data).forEach((item, index) => {
item.pay_type.forEach((subItem:any, subIndex:any) => {
subItem.sort = subIndex
subItem.status = Number(subItem.status)
})
})

View File

@ -9,13 +9,12 @@
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="recordsTableData.searchParam" ref="searchFormRef">
<el-form-item :label="t('searchReceiver')" prop="receiver">
<el-form-item :label="t('searchReceiver')" prop="mobile">
<el-input v-model="recordsTableData.searchParam.mobile" :placeholder="t('receiverPlaceholder')" />
</el-form-item>
<el-form-item :label="t('noticeKey')" prop="key">
<el-select v-model="recordsTableData.searchParam.key" clearable :placeholder="t('noticeKeyPlaceholder')" class="input-width">
<el-option :label="t('selectPlaceholder')" value="" />
<el-option-group v-for="(group, gindex) in templateList" :key="gindex" :label="group.label">
<el-option :label="item.name" :value="item.value" :disabled="item.disabled ?? false" v-for="(item, index) in group.list" :key="index" />
</el-option-group>
@ -28,7 +27,7 @@
<el-form-item>
<el-button type="primary" @click="loadNoticeLogList()">{{ t('search') }}</el-button>
<el-button @click="searchFormRef?.resetFields()">{{ t('reset') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
@ -70,7 +69,7 @@
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getNoticeList, getSmsLog } from '@/app/api/notice'
import RecordsInfo from '@/app/views/setting/components/notice-records-info.vue'
import RecordsInfo from '@/app/views/setting/components/sms-records-info.vue'
import { FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
@ -152,6 +151,12 @@ const loadNoticeLogList = (page: number = 1) => {
}
loadNoticeLogList()
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadNoticeLogList()
}
const recordsDialog: Record<string, any> | null = ref(null)
/**

View File

@ -104,7 +104,7 @@ const formData = reactive<Record<string, string>>({
tel: ''
})
const setFormData = async (id: number = 0) => {
const setFormData = async () => {
const data = await (await getWebsite()).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]

View File

@ -38,18 +38,15 @@
<div v-show="formData.uid === 0">
<el-form-item :label="t('username')" prop="username">
<el-input v-model="formData.username" clearable :placeholder="t('usernamePlaceholder')" class="input-width" :readonly="user_name_input"
@click="inputClick('user_name_input')" @blur="user_name_input = true" />
<el-input v-model="formData.username" clearable :placeholder="t('usernamePlaceholder')" class="input-width" :readonly="user_name_input" @click="inputClick('user_name_input')" @blur="user_name_input = true" />
</el-form-item>
<el-form-item :label="t('password')" prop="password">
<el-input v-model="formData.password" clearable :placeholder="t('passwordPlaceholder')" class="input-width" :show-password="true" type="password" :readonly="password_input"
@click="inputClick('password_input')" @blur="password_input = true" />
<el-input v-model="formData.password" clearable :placeholder="t('passwordPlaceholder')" class="input-width" :show-password="true" type="password" :readonly="password_input" @click="inputClick('password_input')" @blur="password_input = true" />
</el-form-item>
<el-form-item :label="t('confirmPassword')" prop="confirm_password">
<el-input v-model="formData.confirm_password" :placeholder="t('confirmPasswordPlaceholder')" type="password" :show-password="true" clearable class="input-width" :readonly="confirm_password_input"
@click="inputClick('confirm_password_input')" @blur="confirm_password_input = true" />
<el-input v-model="formData.confirm_password" :placeholder="t('confirmPasswordPlaceholder')" type="password" :show-password="true" clearable class="input-width" :readonly="confirm_password_input" @click="inputClick('confirm_password_input')" @blur="confirm_password_input = true" />
</el-form-item>
</div>
</div>

View File

@ -30,7 +30,7 @@
{{ siteGroup[row.group_id] ? siteGroup[row.group_id].group_name : '' }}
</template>
</el-table-column>
<el-table-column :label="t('siteNum')">
<el-table-column :label="t('createSiteNum')">
<template #default="{ $index }">
<el-input v-model.number="formData.create_site_limit[$index].num">
</el-input>

View File

@ -27,7 +27,6 @@
<div class="max-w-[260px]"> {{ formData.roles[0].site_name }} </div>
<el-link class="ml-10 text-blue-700" href="/site/login" target="_blank" :underline="false">{{ t('enterSite') }}</el-link>
</div>
</el-form-item>
<el-form-item :label="t('isAdmin')">

View File

@ -65,10 +65,13 @@
{{ row.last_ip || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" align="right" fixed="right" width="150">
<el-table-column :label="t('operation')" align="right" fixed="right" width="200">
<template #default="{ row }">
<el-button type="primary" link @click="detailEvent(row.uid)">{{ t('detail') }}</el-button>
<el-button type="primary" link @click="detailEvent(row.uid, 'userCreateSiteLimit')" v-if="!row.is_super_admin">{{ t('userCreateSiteLimit') }}</el-button>
<template v-if="!row.is_super_admin">
<el-button type="primary" link @click="detailEvent(row.uid, 'userCreateSiteLimit')" >{{ t('userCreateSiteLimit') }}</el-button>
<el-button type="primary" link @click="deleteEvent(row.uid)" >{{ t('delete') }}</el-button>
</template>
</template>
</el-table-column>
</el-table>
@ -89,11 +92,13 @@
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getUserList } from '@/app/api/user'
import { getUserList, deleteUser } from '@/app/api/user'
import { img } from '@/utils/common'
import type { FormInstance } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
import userEdit from './components/user-edit.vue'
import {ElMessageBox} from "element-plus";
import {deleteSite} from "@/app/api/site";
const router = useRouter()
const route = useRoute()
@ -151,6 +156,24 @@ loadUserList()
const detailEvent = (uid: number, tab: string = '') => {
router.push({ path: '/admin/site/user_info', query: { uid, tab } })
}
/**
* 删除用户
*/
const deleteEvent = (uid: number) => {
ElMessageBox.confirm(t('userDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(() => {
deleteUser(uid).then(res => {
loadUserList()
}).catch(() => {
})
})
}
</script>
<style lang="scss" scoped></style>

View File

@ -8,7 +8,7 @@
</el-select>
</el-form-item>
<el-form-item :label="t('associatedName')" prop="name">
<el-input v-model="formData.name" :placeholder="t('associatedNamePlaceholder')" class="input-width" />
<el-input v-model.trim="formData.name" :placeholder="t('associatedNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('addons')" prop="addon">
<el-select v-model="formData.addon" :placeholder="t('addonsPlaceholder')" class="input-width" @change="addonChange">
@ -26,7 +26,7 @@
</el-select>
</el-form-item>
<el-form-item :label="t('foreignKey')" prop="foreign_key">
<el-input v-model="formData.foreign_key" :placeholder="t('foreignKeyPlaceholder')" class="input-width" />
<el-input v-model.trim="formData.foreign_key" :placeholder="t('foreignKeyPlaceholder')" class="input-width" />
</el-form-item>
</el-form>
<template #footer>

View File

@ -10,10 +10,10 @@
<el-tab-pane :label="t('basicSettings')" name="basicSettings">
<el-form :model="formData" label-width="70px" class="page-form">
<el-form-item :label="t('tableName')">
<el-input v-model="formData.table_name" disabled :placeholder="t('tableNamePlaceholder')" class="input-width" maxlength="64" />
<el-input v-model.trim="formData.table_name" disabled :placeholder="t('tableNamePlaceholder')" class="input-width" maxlength="64" />
</el-form-item>
<el-form-item :label="t('tableContent')">
<el-input v-model="formData.table_content" clearable :placeholder="t('tableContentPlaceholder')" class="input-width" maxlength="64" />
<el-input v-model.trim="formData.table_content" clearable :placeholder="t('tableContentPlaceholder')" class="input-width" maxlength="64" />
</el-form-item>
<el-form-item :label="t('addon')">
<el-select class="input-width" :placeholder="t('addonPlaceholder1')" v-model="formData.addon_name" filterable remote clearable :remote-method="getAddonDevelopFn" @change="addonChange">
@ -22,7 +22,7 @@
</el-form-item>
<el-form-item :label="t('moduleName')">
<div>
<el-input v-model="formData.module_name" clearable :placeholder="t('moduleNamePlaceholder')" class="input-width" />
<el-input v-model.trim="formData.module_name" clearable :placeholder="t('moduleNamePlaceholder')" class="input-width" />
<p class="text-[12px] text-[#a9a9a9] leading-normal mt-[5px]">生成代码所属功能模块对应路由名称例如会员模块充值模块订单模块等</p>
<p class="text-[12px] text-[#a9a9a9] leading-normal mt-[5px]">命名规范小写多个单词使用下划线连接,例如: memberarticle_category</p>
</div>
@ -30,7 +30,7 @@
</el-form-item>
<el-form-item :label="t('className')">
<div>
<el-input v-model="formData.class_name" clearable :placeholder="t('classNamePlaceholder')" class="input-width" />
<el-input v-model.trim="formData.class_name" clearable :placeholder="t('classNamePlaceholder')" class="input-width" />
<p class="text-[12px] text-[#a9a9a9] leading-normal mt-[5px]">生成代码所属文件名称controllermodelservice等类型文件名</p>
<p class="text-[12px] text-[#a9a9a9] leading-normal mt-[5px]">命名规范小写多个单词使用下划线连接,例如: article_category</p>
</div>
@ -47,7 +47,7 @@
<el-table-column :label="t('columnName')" prop="column_name" min-width="130px" />
<el-table-column :label="t('columnComment')" prop="" min-width="220px">
<template #default="{ row }">
<el-input v-model="row.column_comment" :placeholder="t('columnCommentPlaceholder')" />
<el-input v-model.trim="row.column_comment" :placeholder="t('columnCommentPlaceholder')" />
</template>
</el-table-column>
<el-table-column :label="t('columnType')" prop="column_type" width="100px" />
@ -327,6 +327,14 @@ const viewType = [
label: t('formImageSelect'),
value: 'imageSelect'
},
{
label: t('formFileSelect'),
value: 'fileSelect'
},
{
label: t('formVideoSelect'),
value: 'videoSelect'
},
{
label: t('formEditor'),
value: 'editor'

View File

@ -168,7 +168,6 @@ const getLinkFn = (callback:any=null)=> {
}
}
}
console.log('link',link.value)
childList.value = Object.values(link.value)[0].child_list
if (value.value.name != '') {

View File

@ -51,6 +51,7 @@ const baseUrl = import.meta.env.VITE_APP_BASE_URL.substr(-1) == '/' ? import.met
const editorConfig = ref({
debug: false,
UEDITOR_HOME_URL: import.meta.env.MODE == 'development' ? '/public/ueditor/' : '/admin/ueditor/',
UEDITOR_CORS_URL: import.meta.env.MODE == 'development' ? location.origin + '/ueditor/' : location.origin + '/admin/ueditor/',
serverUrl: `${baseUrl}sys/ueditor`,
serverHeaders,
//

View File

@ -64,12 +64,12 @@ const detectionExportFn = () => {
setTimeout(() => {
window.open(url.href)
}, 100)
}).catch(() => { })
})
} else {
emit('close', false)
ElMessage.error(res.msg)
}
}).catch(() => { })
})
}
//
const close = () => {

View File

@ -261,6 +261,8 @@ const attachmentParam = reactive({
* 查询分组
*/
const getAttachmentCategoryList = debounce(() => {
// todo js
const getFn = prop.type == 'icon' ? getIconCategoryList : attachmentCategoryList
getFn({
type: prop.type,

View File

@ -87,6 +87,10 @@ const videos: Record<string, any> = reactive({
data: []
})
const setValue = () => {
value.value = toRaw(videos.data).toString()
}
watch(() => value.value, () => {
videos.data = [
...value.value.split(',').filter((item: string) => {
@ -94,7 +98,7 @@ watch(() => value.value, () => {
})
]
setValue()
})
}, { immediate: true })
const style = computed(() => {
return {
@ -127,10 +131,6 @@ const removeVideo = (index: number = 0) => {
setValue()
}
const setValue = () => {
value.value = toRaw(videos.data).toString()
}
/**
* 查看视频
*/

View File

@ -88,7 +88,8 @@
"detectionLoginOperation": "确定",
"detectionLoginContent": "已检测到有其他账号登录,需要刷新后才能继续操作。",
"detectionLoginTip": "提示",
"layoutStyle": "布局风格"
"layoutStyle": "布局风格",
"tab": "开启标签栏"
},
"axios": {
"unknownError": "未知错误",

View File

@ -138,7 +138,6 @@ const submitForm = (formEl: FormInstance | undefined) => {
}
});
}
// --- end
</script>
<style lang="scss" scoped>

View File

@ -18,6 +18,13 @@
<el-color-picker v-model="theme" />
</div>
</div>
<!-- 标签栏 -->
<div class="setting-item flex items-center justify-between mb-[10px]">
<div class="title text-base text-tx-secondary">{{ t('layout.tab') }}</div>
<div>
<el-switch v-model="tab" :active-value="true" :inactive-value="false" />
</div>
</div>
</el-scrollbar>
</el-drawer>
</div>
@ -29,6 +36,7 @@ import useSystemStore from '@/stores/modules/system'
import { useDark, useToggle } from '@vueuse/core'
import { setThemeColor } from '@/utils/common'
import { t } from '@/lang'
import storage from "@/utils/storage";
const drawer = ref(false)
const systemStore = useSystemStore()
@ -47,6 +55,18 @@ const dark = computed({
}
})
const tab = computed({
get () {
return systemStore.tab
},
set (val) {
systemStore.$patch((state) => {
state.tab = val
storage.set({ key: 'tab', data: val })
})
}
})
const theme = computed({
get () {
return systemStore.theme

View File

@ -140,7 +140,6 @@ const submitForm = (formEl: FormInstance | undefined) => {
}
});
}
// --- end
</script>
<style lang="scss" scoped>

View File

@ -1,15 +1,15 @@
<template>
<div class="tab-wrap w-full px-[16px]">
<el-tabs :closable="tabbarStore.tabLength > 1" :model-value="route.path" @tab-click="tabClick" @tab-remove="removeTab">
<el-tab-pane v-for="(tab, key, index) in tabbarStore.tabs" :name="tab.path" :key="index">
<div class="tab-wrap w-full px-[16px]" v-show="systemStore.tab">
<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.name" :key="index">
<template #label>
<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>
<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="Right" :disabled="index == (tabbarStore.tabLength - 1)" @click="closeRight(tab.path)">{{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="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.name)">{{t('tabs.closeRight') }}</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>
</template>
</el-dropdown>
@ -22,10 +22,12 @@
<script lang="ts" setup>
import { watch, onMounted } from 'vue'
import useTabbarStore from '@/stores/modules/tabbar'
import useSystemStore from '@/stores/modules/system'
import { useRoute, useRouter } from 'vue-router'
import { t } from '@/lang'
const tabbarStore = useTabbarStore()
const systemStore = useSystemStore()
const route = useRoute()
const router = useRouter()
@ -43,7 +45,7 @@ watch(route, (nval: any) => {
*/
const tabClick = (content: any) => {
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
*/
const removeTab = (content: any) => {
if (route.path == content) {
if (route.name == content) {
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)
}
/**
* 关闭左侧
* @param path
* @param name
*/
const closeLeft = (path: string) => {
const closeLeft = (name: string) => {
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]]
}
router.push({ path })
router.push({ name })
}
/**
* 关闭右侧
* @param path
* @param name
*/
const closeRight = (path: string) => {
const closeRight = (name: string) => {
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]]
}
router.push({ path })
router.push({ name })
}
/**
* 关闭其他
* @param path
* @param name
*/
const closeOther = (path: string) => {
const closeOther = (name: string) => {
const tabs = Object.keys(tabbarStore.tabs)
tabs.forEach((key: string) => { key != path && delete tabbarStore.tabs[key] })
router.push({ path })
tabs.forEach((key: string) => { key != name && delete tabbarStore.tabs[key] })
router.push({ name })
}
</script>

View File

@ -11,6 +11,8 @@
</el-header>
<!-- 顶部 end -->
<layout-tab />
<!-- 主体 -->
<el-main class="h-full p-0 bg-page">
<el-scrollbar>
@ -32,6 +34,7 @@
import { computed } from 'vue'
import layoutHeader from './components/header/index.vue'
import layoutAside from './components/aside/index.vue'
import layoutTab from './components/tabs.vue'
import useAppStore from '@/stores/modules/app'
import useTabbarStore from '@/stores/modules/tabbar'
import useSystemStore from '@/stores/modules/system'

View File

@ -25,7 +25,7 @@
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useRoute } from 'vue-router'
import useSystemStore from '@/stores/modules/system'
import useUserStore from '@/stores/modules/user'
import menuItem from './menu-item.vue'

View File

@ -18,6 +18,13 @@
<el-color-picker v-model="theme" />
</div>
</div>
<!-- 标签栏 -->
<div class="setting-item flex items-center justify-between mb-[10px]">
<div class="title text-base text-tx-secondary">{{ t('layout.tab') }}</div>
<div>
<el-switch v-model="tab" :active-value="true" :inactive-value="false" />
</div>
</div>
</el-scrollbar>
</el-drawer>
</div>
@ -29,6 +36,7 @@ import useSystemStore from '@/stores/modules/system'
import { useDark, useToggle } from '@vueuse/core'
import { setThemeColor } from '@/utils/common'
import { t } from '@/lang'
import storage from "@/utils/storage";
const drawer = ref(false)
const systemStore = useSystemStore()
@ -47,6 +55,18 @@ const dark = computed({
}
})
const tab = computed({
get () {
return systemStore.tab
},
set (val) {
systemStore.$patch((state) => {
state.tab = val
storage.set({ key: 'tab', data: val })
})
}
})
const theme = computed({
get () {
return systemStore.theme

View File

@ -140,7 +140,6 @@ const submitForm = (formEl: FormInstance | undefined) => {
}
});
}
// --- end
</script>
<style lang="scss" scoped>

View File

@ -1,15 +1,15 @@
<template>
<div class="tab-wrap w-full px-[16px]">
<el-tabs :closable="tabbarStore.tabLength > 1" :model-value="route.path" @tab-click="tabClick" @tab-remove="removeTab">
<el-tab-pane v-for="(tab, key, index) in tabbarStore.tabs" :name="tab.path" :key="index">
<div class="tab-wrap w-full px-[16px]" v-show="systemStore.tab">
<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.name" :key="index">
<template #label>
<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>
<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="Right" :disabled="index == (tabbarStore.tabLength - 1)" @click="closeRight(tab.path)">{{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="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.name)">{{t('tabs.closeRight') }}</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>
</template>
</el-dropdown>
@ -22,10 +22,12 @@
<script lang="ts" setup>
import { watch, onMounted } from 'vue'
import useTabbarStore from '@/stores/modules/tabbar'
import useSystemStore from '@/stores/modules/system'
import { useRoute, useRouter } from 'vue-router'
import { t } from '@/lang'
const tabbarStore = useTabbarStore()
const systemStore = useSystemStore()
const route = useRoute()
const router = useRouter()
@ -43,7 +45,7 @@ watch(route, (nval: any) => {
*/
const tabClick = (content: any) => {
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
*/
const removeTab = (content: any) => {
if (route.path == content) {
if (route.name == content) {
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)
}
/**
* 关闭左侧
* @param path
* @param name
*/
const closeLeft = (path: string) => {
const closeLeft = (name: string) => {
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]]
}
router.push({ path })
router.push({ name })
}
/**
* 关闭右侧
* @param path
* @param name
*/
const closeRight = (path: string) => {
const closeRight = (name: string) => {
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]]
}
router.push({ path })
router.push({ name })
}
/**
* 关闭其他
* @param path
* @param name
*/
const closeOther = (path: string) => {
const closeOther = (name: string) => {
const tabs = Object.keys(tabbarStore.tabs)
tabs.forEach((key: string) => { key != path && delete tabbarStore.tabs[key] })
router.push({ path })
tabs.forEach((key: string) => { key != name && delete tabbarStore.tabs[key] })
router.push({ name })
}
</script>

View File

@ -11,6 +11,8 @@
</el-header>
<!-- 顶部 end -->
<layout-tab />
<!-- 主体 -->
<el-main class="h-full p-0 bg-page">
<el-scrollbar>
@ -32,6 +34,7 @@
import { computed } from 'vue'
import layoutHeader from './components/header/index.vue'
import layoutAside from './components/aside/index.vue'
import layoutTab from './components/tabs.vue'
import useAppStore from '@/stores/modules/app'
import useTabbarStore from '@/stores/modules/tabbar'
import useSystemStore from '@/stores/modules/system'

View File

@ -18,6 +18,13 @@
<el-color-picker v-model="theme" />
</div>
</div>
<!-- 标签栏 -->
<div class="setting-item flex items-center justify-between mb-[10px]">
<div class="title text-base text-tx-secondary">{{ t('layout.tab') }}</div>
<div>
<el-switch v-model="tab" :active-value="true" :inactive-value="false" />
</div>
</div>
</el-scrollbar>
</el-drawer>
</div>
@ -29,6 +36,7 @@ import useSystemStore from '@/stores/modules/system'
import { useDark, useToggle } from '@vueuse/core'
import { setThemeColor } from '@/utils/common'
import { t } from '@/lang'
import storage from "@/utils/storage";
const drawer = ref(false)
const systemStore = useSystemStore()
@ -47,6 +55,18 @@ const dark = computed({
}
})
const tab = computed({
get () {
return systemStore.tab
},
set (val) {
systemStore.$patch((state) => {
state.tab = val
storage.set({ key: 'tab', data: val })
})
}
})
const theme = computed({
get () {
return systemStore.theme

View File

@ -140,7 +140,6 @@ const submitForm = (formEl: FormInstance | undefined) => {
}
});
}
// --- end
</script>
<style lang="scss" scoped>

View File

@ -1,15 +1,15 @@
<template>
<div class="tab-wrap w-full px-[16px]">
<el-tabs :closable="tabbarStore.tabLength > 1" :model-value="route.path" @tab-click="tabClick" @tab-remove="removeTab">
<el-tab-pane v-for="(tab, key, index) in tabbarStore.tabs" :name="tab.path" :key="index">
<div class="tab-wrap w-full px-[16px]" v-show="systemStore.tab">
<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.name" :key="index">
<template #label>
<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>
<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="Right" :disabled="index == (tabbarStore.tabLength - 1)" @click="closeRight(tab.path)">{{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="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.name)">{{t('tabs.closeRight') }}</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>
</template>
</el-dropdown>
@ -22,10 +22,12 @@
<script lang="ts" setup>
import { watch, onMounted } from 'vue'
import useTabbarStore from '@/stores/modules/tabbar'
import useSystemStore from '@/stores/modules/system'
import { useRoute, useRouter } from 'vue-router'
import { t } from '@/lang'
const tabbarStore = useTabbarStore()
const systemStore = useSystemStore()
const route = useRoute()
const router = useRouter()
@ -43,7 +45,7 @@ watch(route, (nval: any) => {
*/
const tabClick = (content: any) => {
const tabRoute = tabbarStore.tabs[content.props.name]
router.push({ path: tabRoute.path, query: tabRoute.query })
router.push({ name: tabRoute.name, query: tabRoute.query })
}
/**
@ -51,9 +53,13 @@ const tabClick = (content: any) => {
* @param content
*/
const removeTab = (content: any) => {
if (route.path == content) {
if (route.name == content) {
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)
}
@ -62,34 +68,34 @@ const removeTab = (content: any) => {
* 关闭左侧
* @param path
*/
const closeLeft = (path: string) => {
const closeLeft = (name: string) => {
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]]
}
router.push({ path })
router.push({ name })
}
/**
* 关闭右侧
* @param path
*/
const closeRight = (path: string) => {
const closeRight = (name: string) => {
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]]
}
router.push({ path })
router.push({ name })
}
/**
* 关闭其他
* @param path
*/
const closeOther = (path: string) => {
const closeOther = (name: string) => {
const tabs = Object.keys(tabbarStore.tabs)
tabs.forEach((key: string) => { key != path && delete tabbarStore.tabs[key] })
router.push({ path })
tabs.forEach((key: string) => { key != name && delete tabbarStore.tabs[key] })
router.push({ name })
}
</script>

View File

@ -11,6 +11,8 @@
</el-header>
<!-- 顶部 end -->
<layout-tab />
<!-- 主体 -->
<el-main class="h-full p-0 bg-page">
<el-scrollbar>
@ -32,6 +34,7 @@
import { computed } from 'vue'
import layoutHeader from './components/header/index.vue'
import layoutAside from './components/aside/index.vue'
import layoutTab from './components/tabs.vue'
import useAppStore from '@/stores/modules/app'
import useTabbarStore from '@/stores/modules/tabbar'
import useSystemStore from '@/stores/modules/system'

View File

@ -61,6 +61,7 @@ import useUserStore from '@/stores/modules/user'
import { img, isUrl } from '@/utils/common'
import { findFirstValidRoute } from '@/router/routers'
import menuItem from './menu-item.vue'
import { cloneDeep } from 'lodash-es'
const route = useRoute()
const router = useRouter()
@ -145,7 +146,7 @@ const menuOption = ref([])
watch(twoMenuData.value, () => {
menuOption.value = [];
if(twoMenuData.value && Object.values(twoMenuData.value).length){
let data = JSON.parse(JSON.stringify(twoMenuData.value));
let data = cloneDeep(twoMenuData.value);
for(let key in data){
menuOption.value.push(data[key].name);
}

View File

@ -18,6 +18,13 @@
<el-color-picker v-model="theme" />
</div>
</div>
<!-- 标签栏 -->
<div class="setting-item flex items-center justify-between mb-[10px]">
<div class="title text-base text-tx-secondary">{{ t('layout.tab') }}</div>
<div>
<el-switch v-model="tab" :active-value="true" :inactive-value="false" />
</div>
</div>
</el-scrollbar>
</el-drawer>
</div>
@ -29,6 +36,7 @@ import useSystemStore from '@/stores/modules/system'
import { useDark, useToggle } from '@vueuse/core'
import { setThemeColor } from '@/utils/common'
import { t } from '@/lang'
import storage from "@/utils/storage";
const drawer = ref(false)
const systemStore = useSystemStore()
@ -47,6 +55,18 @@ const dark = computed({
}
})
const tab = computed({
get () {
return systemStore.tab
},
set (val) {
systemStore.$patch((state) => {
state.tab = val
storage.set({ key: 'tab', data: val })
})
}
})
const theme = computed({
get () {
return systemStore.theme

View File

@ -140,7 +140,6 @@ const submitForm = (formEl: FormInstance | undefined) => {
}
});
}
// --- end
</script>
<style lang="scss" scoped>

View File

@ -1,15 +1,15 @@
<template>
<div class="tab-wrap w-full px-[16px]">
<el-tabs :closable="tabbarStore.tabLength > 1" :model-value="route.path" @tab-click="tabClick" @tab-remove="removeTab">
<el-tab-pane v-for="(tab, key, index) in tabbarStore.tabs" :name="tab.path" :key="index">
<div class="tab-wrap w-full px-[16px]" v-show="systemStore.tab">
<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.name" :key="index">
<template #label>
<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>
<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="Right" :disabled="index == (tabbarStore.tabLength - 1)" @click="closeRight(tab.path)">{{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="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.name)">{{t('tabs.closeRight') }}</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>
</template>
</el-dropdown>
@ -22,10 +22,12 @@
<script lang="ts" setup>
import { watch, onMounted } from 'vue'
import useTabbarStore from '@/stores/modules/tabbar'
import useSystemStore from '@/stores/modules/system'
import { useRoute, useRouter } from 'vue-router'
import { t } from '@/lang'
const tabbarStore = useTabbarStore()
const systemStore = useSystemStore()
const route = useRoute()
const router = useRouter()
@ -43,7 +45,7 @@ watch(route, (nval: any) => {
*/
const tabClick = (content: any) => {
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
*/
const removeTab = (content: any) => {
if (route.path == content) {
if (route.name == content) {
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)
}
/**
* 关闭左侧
* @param path
* @param name
*/
const closeLeft = (path: string) => {
const closeLeft = (name: string) => {
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]]
}
router.push({ path })
router.push({ name })
}
/**
* 关闭右侧
* @param path
* @param name
*/
const closeRight = (path: string) => {
const closeRight = (name: string) => {
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]]
}
router.push({ path })
router.push({ name })
}
/**
* 关闭其他
* @param path
* @param name
*/
const closeOther = (path: string) => {
const closeOther = (name: string) => {
const tabs = Object.keys(tabbarStore.tabs)
tabs.forEach((key: string) => { key != path && delete tabbarStore.tabs[key] })
router.push({ path })
tabs.forEach((key: string) => { key != name && delete tabbarStore.tabs[key] })
router.push({ name })
}
</script>

View File

@ -11,6 +11,8 @@
</el-header>
<!-- 顶部 end -->
<layout-tab />
<!-- 主体 -->
<el-main class="h-full p-0 bg-page">
<el-scrollbar>
@ -32,6 +34,7 @@
import { computed } from 'vue'
import layoutHeader from './components/header/index.vue'
import layoutAside from './components/aside/index.vue'
import layoutTab from './components/tabs.vue'
import useAppStore from '@/stores/modules/app'
import useTabbarStore from '@/stores/modules/tabbar'
import useSystemStore from '@/stores/modules/system'

View File

@ -11,7 +11,7 @@ import { setWindowTitle, getAppType, urlToRouteRaw } from '@/utils/common'
const ADDON_ROUTE = []
const addonRoutes = import.meta.globEager('@/addon/**/router/index.ts')
for (const key in addonRoutes) {
const addon = addonRoutes[key]
const addon: any = addonRoutes[key]
addon.ROUTE && ADDON_ROUTE.push(...addon.ROUTE)
addon.NO_LOGIN_ROUTES && NO_LOGIN_ROUTES.push(...addon.NO_LOGIN_ROUTES)
}
@ -26,7 +26,7 @@ const router = createRouter({
*/
const originPush = router.push
router.push = (to: RouteLocationRaw) => {
const route = typeof to == 'string' ? urlToRouteRaw(to) : to
const route: any = typeof to == 'string' ? urlToRouteRaw(to) : to
if (route.path) {
const paths = route.path.split('/').filter((item: string) => { return item })
route.path = ['admin', 'site', 'home'].indexOf(paths[0]) == -1 ? `/${getAppType()}${route.path}` : route.path
@ -39,7 +39,7 @@ router.push = (to: RouteLocationRaw) => {
*/
const originResolve = router.resolve
router.resolve = (to: RouteLocationRaw, currentLocation?: RouteLocationNormalizedLoaded) => {
const route = typeof to == 'string' ? urlToRouteRaw(to) : to
const route: any = typeof to == 'string' ? urlToRouteRaw(to) : to
if (route.path) {
const paths = route.path.split('/').filter((item: string) => { return item })
route.path = ['admin', 'site', 'home'].indexOf(paths[0]) == -1 ? `/${getAppType()}${route.path}` : route.path
@ -48,7 +48,7 @@ router.resolve = (to: RouteLocationRaw, currentLocation?: RouteLocationNormalize
}
// 全局前置守卫
router.beforeEach(async (to, from, next) => {
router.beforeEach(async (to: any, from, next) => {
NProgress.configure({ showSpinner: false })
NProgress.start()
@ -106,7 +106,7 @@ router.beforeEach(async (to, from, next) => {
next({ path: '/home/index', replace: true })
}
} else {
await userStore.getAuthMenus()
await userStore.getAuthMenusFn()
// 设置首页路由
let firstRoute: symbol | string | undefined = findFirstValidRoute(userStore.routers)

View File

@ -129,7 +129,7 @@ interface Route {
*/
const createRoute = function (route: Route, parentRoute: RouteRecordRaw | null = null): RouteRecordRaw {
const record: RouteRecordRaw = {
path: `/${route.app_type}/${route.router_path}`,
path: `/${ route.app_type }/${ route.router_path }`,
name: route.menu_key,
meta: {
title: route.menu_name,
@ -146,7 +146,7 @@ const createRoute = function (route: Route, parentRoute: RouteRecordRaw | null =
if (route.menu_type == 0) {
record.component = parentRoute ? RouterView : () => Promise.resolve(Default)
} else {
record.component = route.addon ? addonModules[`/src/addon/${route.addon}/views/${route.view_path}.vue`] : modules[`/src/app/views/${route.view_path}.vue`]
record.component = route.addon ? addonModules[`/src/addon/${ route.addon }/views/${ route.view_path }.vue`] : modules[`/src/app/views/${ route.view_path }.vue`]
}
return record
}

View File

@ -1,8 +1,8 @@
import {defineStore} from 'pinia'
import {t} from '@/lang'
import {toRaw} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {cloneDeep} from 'lodash-es'
import { defineStore } from 'pinia'
import { t } from '@/lang'
import { toRaw } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { cloneDeep } from 'lodash-es'
const useDiyStore = defineStore('diy', {
state: () => {
@ -39,8 +39,8 @@ const useDiyStore = defineStore('diy', {
'hsla(209, 100%, 56%, 0.73)',
'#c7158577'
],
components: [], // 组件集合
position: ['top_fixed','right_fixed','bottom_fixed','left_fixed','fixed'],
components: <any>[], // 组件集合
position: ['top_fixed', 'right_fixed', 'bottom_fixed', 'left_fixed', 'fixed'],
global: {
title: "页面", // 页面标题(用于前台展示)
@ -58,12 +58,12 @@ const useDiyStore = defineStore('diy', {
bgColor: "#ffffff", // 头部背景颜色
rollBgColor: "#ffffff", // 滚动时,头部背景颜色
style: 'style-1', // 导航栏风格样式style-1文字style-2图片+文字style-3图片+搜索style-4定位
styleName: '风格1',
styleName: '风格1',
textColor: "#333333", // 文字颜色
rollTextColor: "#333333", // 滚动时,头部文字颜色
textAlign: 'center', // 文字对齐方式
inputPlaceholder : '请输入搜索关键词',
imgUrl:'', // 图片
inputPlaceholder: '请输入搜索关键词',
imgUrl: '', // 图片
link: { // 跳转链接
name: ""
}
@ -111,7 +111,7 @@ const useDiyStore = defineStore('diy', {
},
// 组件集合
value: []
value: <any>[]
}
},
getters: {
@ -143,12 +143,12 @@ const useDiyStore = defineStore('diy', {
bgColor: "#ffffff", // 头部背景颜色
rollBgColor: "#ffffff", // 滚动时,头部背景颜色
style: 'style-1', // 导航栏风格样式style-1文字style-2图片+文字style-3图片+搜索style-4定位
styleName: '风格1',
styleName: '风格1',
textColor: "#333333", // 文字颜色
rollTextColor: "#333333", // 滚动时,头部文字颜色
textAlign: 'center', // 文字对齐方式
inputPlaceholder : '请输入搜索关键词',
imgUrl:'', // 图片
inputPlaceholder: '请输入搜索关键词',
imgUrl: '', // 图片
link: { // 跳转链接
name: ""
}
@ -220,7 +220,7 @@ const useDiyStore = defineStore('diy', {
let template = cloneDeep(this.global.template);
Object.assign(component, template);
if(component.template){
if (component.template) {
// 按照组件初始的属性覆盖默认值
Object.assign(component, component.template);
delete component.template;
@ -230,19 +230,19 @@ const useDiyStore = defineStore('diy', {
// 组件最多只能添加n个
ElMessage({
type: 'warning',
message: `${component.componentTitle}${t('componentCanOnlyAdd')}${component.uses}${t('piece')}`,
message: `${ component.componentTitle }${ t('componentCanOnlyAdd') }${ component.uses }${ t('piece') }`,
});
return;
}
// 置顶组件,只能在第一个位置中添加
if(component.position && this.position.indexOf(component.position) != -1){
if (component.position && this.position.indexOf(component.position) != -1) {
this.currentIndex = 0;
// 指定位置添加组件
this.value.splice(0, 0, component);
}else if (this.currentIndex === -99) {
} else if (this.currentIndex === -99) {
this.value.push(component);
// 添加组件后(不是编辑调用的),选择最后一个
@ -317,16 +317,16 @@ const useDiyStore = defineStore('diy', {
var temp = cloneDeep(this.value[this.currentIndex]); // 当前选中组件
let prevIndex = this.currentIndex - 1;
var temp2 = cloneDeep(this.value[prevIndex]); // 上个组件
if ((this.currentIndex - 1) < 0 || temp2.position && this.position.indexOf(temp2.position) != -1) return; // 从0开始
temp.id = this.generateRandom(); // 更新id刷新组件数据
temp2.id = this.generateRandom(); // 更新id刷新组件数据
if(temp.position && this.position.indexOf(temp.position) != -1){
if (temp.position && this.position.indexOf(temp.position) != -1) {
ElMessage({
type: 'warning',
message: `${t('componentNotMoved')}`,
message: `${ t('componentNotMoved') }`,
});
return;
}
@ -348,10 +348,10 @@ const useDiyStore = defineStore('diy', {
var temp2 = cloneDeep(this.value[nextIndex]); // 下个组件
temp2.id = this.generateRandom(); // 更新id刷新组件数据
if(temp.position && this.position.indexOf(temp.position) != -1){
if (temp.position && this.position.indexOf(temp.position) != -1) {
ElMessage({
type: 'warning',
message: `${t('componentNotMoved')}`,
message: `${ t('componentNotMoved') }`,
});
return;
}
@ -372,15 +372,15 @@ const useDiyStore = defineStore('diy', {
if (!this.checkComponentIsAdd(component)) {
ElMessage({
type: 'warning',
message: `${t('notCopy')}${component.componentTitle}${t('componentCanOnlyAdd')}${component.uses}${t('piece')}`,
message: `${ t('notCopy') }${ component.componentTitle }${ t('componentCanOnlyAdd') }${ component.uses }${ t('piece') }`,
});
return;
}
if(component.position && this.position.indexOf(component.position) != -1){
if (component.position && this.position.indexOf(component.position) != -1) {
ElMessage({
type: 'warning',
message: `${t('notCopy')}${component.componentTitle}${t('componentCanOnlyAdd')}1${t('piece')}`,
message: `${ t('notCopy') }${ component.componentTitle }${ t('componentCanOnlyAdd') }1${ t('piece') }`,
});
return;
}

View File

@ -13,7 +13,8 @@ interface System {
sidebarStyle: string,
currHeadMenuName: any,
website: Object,
layoutConfig: Object
layoutConfig: Object,
tab: Boolean
}
const theme = storage.get('theme') ?? {}
@ -30,7 +31,8 @@ const useSystemStore = defineStore('system', {
sidebarStyle: theme.sidebarStyle ?? 'threeType',
currHeadMenuName: '',
website: {},
layoutConfig: {}
layoutConfig: {},
tab: storage.get('tab') ?? false
}
},
actions: {

View File

@ -1,10 +1,10 @@
import { defineStore } from 'pinia'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
import type { RouteLocationNormalizedLoaded, RouteRecordName } from 'vue-router'
interface Tabbar {
curr: string,
tabs: {
[key: string]: any
[key: RouteRecordName]: any
}
}
@ -18,11 +18,11 @@ const useTabbarStore = defineStore('tabbar', {
actions: {
addTab(roter: RouteLocationNormalizedLoaded) {
if (roter.meta && roter.meta.type != 1) return
if (this.tabs[roter.path]) {
this.tabs[roter.path].query = roter.query || {}
if (this.tabs[roter.name]) {
this.tabs[roter.name].query = roter.query || {}
return
}
this.tabs[roter.path] = {
this.tabs[roter.name] = {
path: roter.path,
title: roter.meta ? roter.meta.title : '',
name: roter.name,
@ -48,4 +48,4 @@ const useTabbarStore = defineStore('tabbar', {
}
})
export default useTabbarStore
export default useTabbarStore

View File

@ -6,7 +6,6 @@ import router from '@/router'
import { formatRouters, findFirstValidRoute } from '@/router/routers'
import useTabbarStore from './tabbar'
import Test from '@/utils/test'
import { setUserInfo } from '@/app/api/personal'
interface User {
token: string,
@ -41,8 +40,7 @@ const userStore = defineStore('user', {
},
login(form: object, app_type: any) {
return new Promise((resolve, reject) => {
login(form, app_type)
.then(async(res) => {
login(form, app_type).then(async(res) => {
if (app_type == 'admin' && Test.empty(res.data.userrole)) {
storage.setPrefix('site')
}
@ -56,8 +54,7 @@ const userStore = defineStore('user', {
storage.set({ key: 'comparisonSiteIdStorage', data: res.data.site_id || 0 })
storage.set({ key: 'comparisonTokenStorage', data: res.data.token })
resolve(res)
})
.catch((error) => {
}).catch((error) => {
reject(error)
})
})
@ -76,7 +73,7 @@ const userStore = defineStore('user', {
const login = getAppType() == 'admin' ? '/admin/login' : '/site/login'
router.push(login)
},
getAuthMenus() {
getAuthMenusFn() {
return new Promise((resolve, reject) => {
getAuthMenus({}).then((res) => {
this.routers = formatRouters(res.data)

View File

@ -159,7 +159,7 @@ export function strByteLength(str: string = ''): number {
* @param url
*/
export function urlToRouteRaw(url: string) {
const query = {}
const query: any = {}
const [path, param] = url.split('?')
param && param.split('&').forEach((str: string) => {
@ -204,7 +204,7 @@ export function deepClone(obj: object) {
* @param {Boolean} firstU
* @param {Number} radix
*/
export function guid(len = 10, firstU = true, radix = null) {
export function guid(len = 10, firstU = true, radix: any = null) {
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
const uuid = []
radix = radix || chars.length
@ -244,19 +244,19 @@ export function moneyFormat(money : string) : string {
/**
*
*/
export function timeStampTurnTime(timeStamp, type = "") {
export function timeStampTurnTime(timeStamp: any, type = "") {
if (timeStamp != undefined && timeStamp != "" && timeStamp > 0) {
var date = new Date();
date.setTime(timeStamp * 1000);
var y = date.getFullYear();
var m = date.getMonth() + 1;
var y: any = date.getFullYear();
var m: any = date.getMonth() + 1;
m = m < 10 ? ('0' + m) : m;
var d = date.getDate();
var d: any = date.getDate();
d = d < 10 ? ('0' + d) : d;
var h = date.getHours();
var h: any = date.getHours();
h = h < 10 ? ('0' + h) : h;
var minute = date.getMinutes();
var second = date.getSeconds();
var minute: any = date.getMinutes();
var second: any = date.getSeconds();
minute = minute < 10 ? ('0' + minute) : minute;
second = second < 10 ? ('0' + second) : second;
if (type) {
@ -305,3 +305,47 @@ export function filterSpecial(event:any){
event.target.value = event.target.value.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '')
event.target.value = event.target.value.replace(/[`~!@#$%^&*()_\-+=<>?:"{}|,.\/;'\\[\]·~@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g,'')
}
export function importIconFontCss() {
// const modulesFiles = {}; // import.meta.glob('@/styles/icon/official-iconfont.css', { eager: true })
// const modulesFiles = import.meta.glob('@/addon/**/assets/icon/*.css', { eager: true })
// // console.log('modulesFiles',modulesFiles)
//
// const modules:any = {}
// for (const [key, value] of Object.entries(modulesFiles)) {
// const moduleName:any = key.split('/').pop()
// const name = moduleName.split('.')[0]
// modules[name] = value.default
// }
//
// // console.log('modules',modules)
//
// for(let key in modules) {
// // console.log('modules[key]',modules[key])
// import(modules[key]).then((module) => {
// // console.log('module', module.default);
// }).catch((e) => {
// // console.log('caca', e)
// });
// }
}
export function getIcon() {
// const modulesFiles = import.meta.glob('@/styles/icon/*.json', { eager: true })
// const addonModulesFiles = import.meta.glob('@/addon/**/assets/icon/*.json', { eager: true })
// addonModulesFiles && Object.assign(modulesFiles, addonModulesFiles)
//
// // const modulesFiles = {}; // import.meta.glob('@/styles/icon/official-iconfont.css', { eager: true })
// // const modulesFiles = import.meta.glob('@/styles/icon/*.json', { eager: true })
// console.log('modulesFiles', modulesFiles)
//
// const modules = {}
// for (const [key, value] of Object.entries(modulesFiles)) {
// const moduleName = key.split('/').pop()
// console.log('moduleName',moduleName)
// const name = moduleName.split('.')[0]
// modules[name] = value.default
// }
// console.log('modules', modules)
// // const addonModulesFiles = import.meta.glob('@/addon/**/assets/icon/*.json', { eager: true })
}

Some files were not shown because too many files have changed in this diff Show More