mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2025-12-10 17:22:47 +00:00
0.1.1
This commit is contained in:
parent
b8fa07a257
commit
f7288afe80
18
admin/src/app/api/pc.ts
Normal file
18
admin/src/app/api/pc.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 获取pc配置
|
||||
* @returns
|
||||
*/
|
||||
export function getPcConfig() {
|
||||
return request.get('channel/pc/config')
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑h5配置
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function setPcConfig(params: Record<string, any>) {
|
||||
return request.put('channel/pc/config', params, {showSuccessMessage: true})
|
||||
}
|
||||
@ -4,5 +4,6 @@
|
||||
"copy": "复制",
|
||||
"clickVisit": "点击访问",
|
||||
"PCDomainName": "pc域名",
|
||||
"newInfo": "最新消息"
|
||||
}
|
||||
"newInfo": "最新消息",
|
||||
"isOpen": "是否开启"
|
||||
}
|
||||
|
||||
@ -1,123 +0,0 @@
|
||||
{
|
||||
"developTitle": "开发环境配置",
|
||||
"wapDomain": "wap域名(WAP_DOMAIN)",
|
||||
"wapDomainPlaceholder": "请输入wap域名",
|
||||
"pageSet": "页面设置",
|
||||
"tabEditContent": "内容",
|
||||
"tabEditStyle": "样式",
|
||||
"pageStyle": "页面样式",
|
||||
"pageContent": "页面内容",
|
||||
"pageName": "页面名称",
|
||||
"pageNamePlaceholder": "请输入页面名称",
|
||||
"pageBgColor": "页面颜色",
|
||||
"bgUrl": "背景图片",
|
||||
"marginSet": "边距设置",
|
||||
"componentStyleTitle": "组件样式",
|
||||
"bottomBgColor": "底部背景",
|
||||
"bottomBgTips": "底部背景包含边距和圆角",
|
||||
"componentBgColor": "组件背景",
|
||||
"marginTop": "上边距",
|
||||
"marginBottom": "下边距",
|
||||
"marginBoth": "左右边距",
|
||||
"topRounded": "上圆角",
|
||||
"bottomRounded": "下圆角",
|
||||
"warmPrompt": "温馨提示",
|
||||
"leavePageTitleTips": "确定离开此页面?",
|
||||
"leavePageContentTips": "系统可能不会保存您所做的更改。",
|
||||
"decorating": "正在装修",
|
||||
"moveUpComponent": "上移",
|
||||
"moveDownComponent": "下移",
|
||||
"copyComponent": "复制",
|
||||
"delComponent": "删除",
|
||||
"resetComponent": "重置",
|
||||
"tabbar": "底部导航",
|
||||
"tabbarSwitchTips": "此处控制当前页面底部导航菜单是否显示",
|
||||
"link": "链接地址",
|
||||
"delComponentTips": "确定要删除吗?",
|
||||
"notCopy": "无法复制",
|
||||
"componentCanOnlyAdd": "组件只能添加",
|
||||
"piece": "个",
|
||||
"resetComponentTips": "确认要重置组件默认数据吗?",
|
||||
"image": "图片上传",
|
||||
"imageUpload": "图片上传",
|
||||
"imageSet": "图片设置",
|
||||
"imageAdsTips": "建议上传尺寸相同的图片,推荐尺寸750*350",
|
||||
"addImageAd": "添加图片",
|
||||
"imageUrlTip": "请上传图片",
|
||||
"imageHeight": "图片高度",
|
||||
"imageHeightPlaceholder": "请输入图片高度",
|
||||
"imageHeightRegNum": "图片高度格式错误,请输入数字",
|
||||
"articleData": "文章数据",
|
||||
"articleStyle": "文章样式",
|
||||
"articleBgColor": "文章背景",
|
||||
"dataSources": "数据来源",
|
||||
"defaultSources": "默认",
|
||||
"manualSelectionSources": "手动选择",
|
||||
"articleNum": "文章数量",
|
||||
"selectPlaceholder": "请选择",
|
||||
"selectArticleTips": "文章选择",
|
||||
"articleTitle": "标题",
|
||||
"articleImage": "封面",
|
||||
"articleCategoryName": "栏目",
|
||||
"articleSummary": "摘要",
|
||||
"selected": "已选",
|
||||
"selectArticleTip": "请选择文章",
|
||||
"graphicNavModeTitle": "导航模式",
|
||||
"layoutMode": "排版模式",
|
||||
"layoutModeHorizontal": "横排",
|
||||
"layoutModeVertical": "竖排",
|
||||
"graphicNavSelectMode": "选择模式",
|
||||
"graphicNavModeGraphic": "图文导航",
|
||||
"graphicNavModeImg": "图片导航",
|
||||
"graphicNavModeText": "文字导航",
|
||||
"graphicNavImageSet": "图片设置",
|
||||
"graphicNavImageSize": "图片大小",
|
||||
"graphicNavAroundRadius": "图片圆角",
|
||||
"graphicNavShowStyle": "展示风格",
|
||||
"graphicNavStyleFixed": "固定显示",
|
||||
"graphicNavStyleSingleSlide": "单行滑动",
|
||||
"graphicNavStylePageSlide": "分页滑动",
|
||||
"graphicNavRowCount": "每行数量",
|
||||
"graphicNavPageCount": "每行数量",
|
||||
"graphicNavSetLabel": "导航设置",
|
||||
"line": "行",
|
||||
"graphicNavTips": "建议上传尺寸相同的图片,推荐尺寸60*60",
|
||||
"graphicNavTitle": "标题",
|
||||
"graphicNavTitlePlaceholder": "请输入标题",
|
||||
"addGraphicNav": "添加导航",
|
||||
"blankHeightSet": "高度设置",
|
||||
"blankHeight": "空白高度",
|
||||
"styleSet": "风格设置",
|
||||
"titleStyle": "标题样式",
|
||||
"selectStyle": "风格选择",
|
||||
"titleContent": "标题内容",
|
||||
"title": "标题名称",
|
||||
"titlePlaceholder": "请输入标题",
|
||||
"textAlign": "对齐方式",
|
||||
"textAlignLeft": "居左",
|
||||
"textAlignCenter": "居中",
|
||||
"textSet": "文字设置",
|
||||
"textFontSize": "文字大小",
|
||||
"textFontWeight": "文字粗细",
|
||||
"fontWeightBold": "加粗",
|
||||
"fontWeightNormal": "常规",
|
||||
"textColor": "文字颜色",
|
||||
"subTitleContent": "标题内容",
|
||||
"subTitle": "副标题",
|
||||
"subTitlePlaceholder": "请输入副标题",
|
||||
"moreContent": "“更多”按钮内容",
|
||||
"more": "文字",
|
||||
"morePlaceholder": "请输入文字",
|
||||
"moreIsShow": "是否显示",
|
||||
"memberStyle": "会员样式",
|
||||
"template": "模板",
|
||||
"imageGap": "图片间隙",
|
||||
"rubikCubeStyle": "魔方样式",
|
||||
"hotArea": "热区",
|
||||
"hotAreaSet": "热区设置",
|
||||
"addHotArea": "添加热区",
|
||||
"selectedAfterHotArea": "个热区",
|
||||
"hotAreaManage": "热区管理",
|
||||
"selectedHotArea": "请选择热区",
|
||||
"hotAreaLink": "的链接地址"
|
||||
}
|
||||
@ -51,21 +51,11 @@
|
||||
"imageHeight": "图片高度",
|
||||
"imageHeightPlaceholder": "请输入图片高度",
|
||||
"imageHeightRegNum": "图片高度格式错误,请输入数字",
|
||||
"articleData": "文章数据",
|
||||
"articleStyle": "文章样式",
|
||||
"articleBgColor": "文章背景",
|
||||
"dataSources": "数据来源",
|
||||
"defaultSources": "默认",
|
||||
"manualSelectionSources": "手动选择",
|
||||
"articleNum": "文章数量",
|
||||
"selectPlaceholder": "请选择",
|
||||
"selectArticleTips": "文章选择",
|
||||
"articleTitle": "标题",
|
||||
"articleImage": "封面",
|
||||
"articleCategoryName": "栏目",
|
||||
"articleSummary": "摘要",
|
||||
"selected": "已选",
|
||||
"selectArticleTip": "请选择文章",
|
||||
"graphicNavModeTitle": "导航模式",
|
||||
"layoutMode": "排版模式",
|
||||
"layoutModeHorizontal": "横排",
|
||||
@ -139,54 +129,13 @@
|
||||
"addonIcon": "应用图标",
|
||||
"selectAddon": "选择应用",
|
||||
"addAddon": "添加应用",
|
||||
"travel": "旅游",
|
||||
"tickets": "门票",
|
||||
"hotel": "酒店",
|
||||
"travelNum": "线路数量",
|
||||
"ticketsNum": "景点数量",
|
||||
"hotelNum": "酒店数量",
|
||||
"serve": "项目",
|
||||
"serveNum": "项目数量",
|
||||
"card": "卡项",
|
||||
"cardNum": "卡项数量",
|
||||
"isSet": "会员设置",
|
||||
"isMemberCode": "会员码",
|
||||
"show": "显示",
|
||||
"hideen": "隐藏",
|
||||
"nicknameStyle": "昵称样式",
|
||||
"UIDStyle": "UID样式",
|
||||
"accountStyle": "积分/余额样式",
|
||||
"accountNumberColor": "数值颜色",
|
||||
"accountNumberWeight": "数值粗细",
|
||||
"hidden": "隐藏",
|
||||
"goodsCategoryTitle":"商品分类",
|
||||
"customGoods":"手动选择",
|
||||
"goodsNum":"商品数量",
|
||||
"selectCategory":"选择分类",
|
||||
"categoryName": "分类名称",
|
||||
"categoryImage": "分类图片",
|
||||
"selectSource": "选择数据源",
|
||||
"goodsSelectPopupSelectGoodsButton": "选择商品",
|
||||
"goodsSelectPopupSelect": "已选",
|
||||
"goodsSelectPopupPiece": "个",
|
||||
"goodsSelectPopupSelectGoodsDialog": "商品选择",
|
||||
"goodsSelectPopupAllGoods": "全部商品",
|
||||
"goodsSelectPopupSelectedGoods": "已选商品",
|
||||
"goodsSelectPopupGoodsName": "商品名称",
|
||||
"goodsSelectPopupGoodsNamePlaceholder": "请输入商品名称",
|
||||
"goodsSelectPopupGoodsCategory": "商品分类",
|
||||
"goodsSelectPopupGoodsCategoryPlaceholder": "全部",
|
||||
"goodsSelectPopupGoodsType": "商品类型",
|
||||
"goodsSelectPopupGoodsTypePlaceholder": "请选择商品类型",
|
||||
"goodsSelectPopupGoodsInfo": "商品",
|
||||
"goodsSelectPopupPrice": "价格",
|
||||
"goodsSelectPopupStock": "库存",
|
||||
"goodsSelectPopupBeforeTip": "已选择",
|
||||
"goodsSelectPopupAfterTip": "个商品",
|
||||
"goodsSelectPopupClearGoods": "取消选择",
|
||||
"goodsSelectPopupGoodsMinTip": "所选商品数量不能少于",
|
||||
"goodsSelectPopupGoodsMaxTip": "所选商品数量不能超过",
|
||||
"confirm": "确定",
|
||||
"cancel": "取消"
|
||||
|
||||
|
||||
"selectSource": "选择数据源"
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"title": "页面名称",
|
||||
"typeName": "页面类型",
|
||||
"forAddon": "所属插件",
|
||||
"forAddon": "所属应用",
|
||||
"addPageTips": "创建新页面",
|
||||
"pageTypePlaceholder": "请选择页面类型",
|
||||
"nameMax": "名称不能超过12个字符",
|
||||
@ -19,7 +19,7 @@
|
||||
"titlePlaceholder": "请输入页面名称",
|
||||
"addDiyPage": "添加页面",
|
||||
"diyPageDeleteTips": "确定要删除该自定义页面吗?",
|
||||
"promote": "推广",
|
||||
"preview": "预览",
|
||||
"share": "分享",
|
||||
"shareSet": "分享设置",
|
||||
"sharePage": "分享页面",
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
"copy": "复制",
|
||||
"copySuccess": "复制成功",
|
||||
"titlePlaceholder": "请输入页面名称",
|
||||
"promote": "推广",
|
||||
"share": "分享",
|
||||
"shareSet": "分享设置",
|
||||
"sharePage": "分享页面",
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
{
|
||||
"registerChannel":"注册来源",
|
||||
"nickname":"会员名称",
|
||||
"nickname":"会员昵称",
|
||||
"memberNo":"会员编号",
|
||||
"mobile":"手机号",
|
||||
"createTime":"注册时间",
|
||||
"lastVisitTime":"最后访问时间",
|
||||
"addMember":"添加会员",
|
||||
"updateMember":"编辑会员",
|
||||
"nickNamePlaceholder":"请输入会员名称",
|
||||
"nickNamePlaceholder":"请输入会员昵称",
|
||||
"mobilePlaceholder":"请输入手机号",
|
||||
"channelPlaceholder":"请选择注册类型",
|
||||
"memberNoPlaceholder":"请选择会员编号",
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
"essentialInfo": "基本信息",
|
||||
"accountInfo": "账户信息",
|
||||
"urserName": "用户名",
|
||||
"nickname":"会员名称",
|
||||
"nickname":"会员昵称",
|
||||
"registeredSource": "注册来源",
|
||||
"lastVisitTime":"最后登录时间",
|
||||
"point": "积分",
|
||||
|
||||
@ -27,9 +27,12 @@
|
||||
"keywordsPlaceholder": "网站关键字",
|
||||
"logoPlaceholder": "网站Logo",
|
||||
"descPlaceholder": "网站简介",
|
||||
|
||||
"phonePlaceholder": "客服电话",
|
||||
"app" : "站点应用",
|
||||
"addon" : "站点插件"
|
||||
|
||||
"addon" : "站点插件",
|
||||
"siteDomain": "站点域名",
|
||||
"siteDomainPlaceholder": "请输入站点域名",
|
||||
"siteDomainTips": "站点域名的配置是针对站点的wap和web端",
|
||||
"siteDomainTipsTwo": "配置的站点域名需要先配置域名解析",
|
||||
"siteDomainTipsThree": "配置的站点域名需配置隐性解析到域名:"
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
"addSite":"添加站点",
|
||||
"editSite":"编辑站点",
|
||||
"updateSite":"编辑站点",
|
||||
"siteDeleteTips":"确定要删除该站点吗?",
|
||||
"statusExpire":"已到期",
|
||||
"phone":"客服电话",
|
||||
"groupIdPlaceholder":"请选择套餐",
|
||||
@ -45,5 +44,11 @@
|
||||
"managerPlaceholder": "请选择站点管理员",
|
||||
"newAddManager": "新增管理员",
|
||||
"edit": "编辑",
|
||||
"siteDeleteTips": "确定要删除该站点吗?该操作将删除该站点和站点相关数据,该操作无法退回,确定要继续删除吗?"
|
||||
"siteDeleteTips": "确定要删除该站点吗?该操作将删除该站点和站点相关数据,该操作无法退回,确定要继续删除吗?",
|
||||
"siteDomain": "站点域名",
|
||||
"siteDomainPlaceholder": "请输入站点域名",
|
||||
"siteDomainTips": "站点域名的配置是针对站点的wap和web端",
|
||||
"siteDomainTipsTwo": "配置的站点域名需要先配置域名解析",
|
||||
"siteDomainTipsThree": "配置的站点域名需配置隐性解析到域名:",
|
||||
"toSite": "访问站点"
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<div class="flex">
|
||||
<div class="bg-[#F3F6FF] mr-[14px] w-[402px] pt-[30px] pl-[32px] pr-[20px] pb-[60px] timeline-log-wrap">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-[20px]">版本信息</span>
|
||||
<span class="text-page-title">版本信息</span>
|
||||
<div class="flex-1 w-0 flex justify-end">
|
||||
<el-button class="text-[#4C4C4C] w-[78px] h-[32px] !bg-transparent" @click="getFrameworkVersionListFn" v-if="!newVersion || (newVersion && newVersion.version_no == versions)">检测更新</el-button>
|
||||
<el-button class="text-[#4C4C4C] w-[78px] h-[32px]" type="primary" @click="handleUpgrade" v-else>一键升级</el-button>
|
||||
@ -21,7 +21,7 @@
|
||||
<div class="flex-1 flex justify-between items-center bg-[#F3F6FF] pt-[34px] pl-[30px] pr-[60px] pb-[62px] timeline-log-wrap">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-wrap items-center">
|
||||
<p class="text-[20px] mr-[20px]">授权信息</p>
|
||||
<p class="text-page-title mr-[20px]">授权信息</p>
|
||||
<span class="text-[14px] text-[#666]">{{ authinfo.company_name || '--' }}</span>
|
||||
</div>
|
||||
<div class="mt-[46px] ml-[40px] flex flex-wrap">
|
||||
@ -96,7 +96,7 @@
|
||||
</el-card>
|
||||
|
||||
<el-card class="box-card !border-none " shadow="never" v-if="!loading">
|
||||
<div class="text-[20px] mb-[20px]">历史版本</div>
|
||||
<div class="text-page-title mb-[20px]">历史版本</div>
|
||||
<el-timeline>
|
||||
<el-timeline-item :timestamp="item['release_time'] + ' 版本:' + item['version_no']" v-for="(item,index) in frameworkVersionList" type="primary" :hollow="true" placement="top" :key="index">
|
||||
<div class="mt-[10px] p-[20px] bg-overlay rounded-md timeline-log-wrap whitespace-pre" v-if="item['upgrade_log']">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container w-full bg-white" v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">应用管理</span>
|
||||
<span class="text-page-title">应用管理</span>
|
||||
</div>
|
||||
<div class="flex flex-wrap plug-list pb-10 plug-large" v-if="appList.length">
|
||||
<div v-for="(item, index) in appList" :key="index + 'b'">
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
:render-after-expand="false" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('routePath')" prop="router_path" v-show="formData.menu_type != 2">
|
||||
<el-form-item :label="t('routePath')" prop="router_path" v-show="formData.menu_type == 1">
|
||||
<el-input v-model="formData.router_path" :placeholder="t('routePathPlaceholder')" class="input-width" />
|
||||
</el-form-item>
|
||||
|
||||
@ -155,7 +155,7 @@ const formRules = computed(() => {
|
||||
}
|
||||
],
|
||||
router_path: [
|
||||
{ required: formData.menu_type != 2, message: t('routePathPlaceholder'), trigger: 'blur' }
|
||||
{ required: formData.menu_type == 1, message: t('routePathPlaceholder'), trigger: 'blur' }
|
||||
],
|
||||
view_path: [
|
||||
{ required: formData.menu_type == 1, message: t('viewPathPlaceholder'), trigger: 'blur' }
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<el-button type="primary" class="w-[100px]" @click="addEvent">
|
||||
{{ t('addMenu') }}
|
||||
</el-button>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<el-button type="primary" class="w-[100px]" @click="addEvent">
|
||||
{{ t('addMenu') }}
|
||||
</el-button>
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
</div> -->
|
||||
<div class="w-full p-5 bg-white">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]">{{ t('title') }}</span>
|
||||
<span class="text-page-title">{{ t('title') }}</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-change="handleClick">
|
||||
<el-tab-pane :label="t('weappAccessFlow')" name="/channel/aliapp" />
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form" v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container" v-loading="loading">
|
||||
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
@ -9,6 +9,10 @@
|
||||
<img class="w-[500px]" src="@/app/assets/images/channel/preview.png" alt="">
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('isOpen')">
|
||||
<el-switch v-model="formData.is_open"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('PCDomainName')">
|
||||
<el-input :model-value="formData.request_url" class="input-width" :readonly="true">
|
||||
<template #append>
|
||||
@ -20,6 +24,12 @@
|
||||
</el-card>
|
||||
|
||||
</el-form>
|
||||
|
||||
<div class="fixed-footer-wrap">
|
||||
<div class="fixed-footer">
|
||||
<el-button type="primary" :loading="loading" @click="save(formRef)">{{ t('save') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -30,6 +40,7 @@ import { getUrl } from '@/app/api/sys'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { ElMessage, FormInstance } from 'element-plus'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { getPcConfig, setPcConfig } from "@/app/api/pc"
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
@ -50,6 +61,15 @@ getUrl().then(res => {
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
/**
|
||||
* 获取pc配置
|
||||
*/
|
||||
getPcConfig().then(res => {
|
||||
Object.assign(formData, res.data)
|
||||
formData.is_open = Boolean(Number(formData.is_open))
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
/**
|
||||
* 复制
|
||||
*/
|
||||
@ -78,6 +98,26 @@ watch(copied, () => {
|
||||
const visitFn = () => {
|
||||
window.open(formData.request_url)
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存
|
||||
*/
|
||||
const save = async (formEl: FormInstance | undefined) => {
|
||||
if (loading.value || !formEl) return
|
||||
|
||||
await formEl.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
const data = { ...formData }
|
||||
data.is_open = Number(data.is_open)
|
||||
setPcConfig(data).then(() => {
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="w-full p-5 bg-white">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]">{{ t('title') }}</span>
|
||||
<span class="text-page-title">{{ t('title') }}</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-change="handleClick">
|
||||
<el-tab-pane :label="t('weappAccessFlow')" name="/channel/weapp" />
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container min-h-[300px] p-5">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-change="handleClick">
|
||||
<el-tab-pane :label="t('weappAccessFlow')" name="/channel/weapp" />
|
||||
@ -23,7 +23,6 @@
|
||||
<el-table-column prop="status_name" :label="t('status')" align="left">
|
||||
<template #default="{ row }">
|
||||
<div>{{ row.status_name }}</div>
|
||||
<div class="text-error" v-if="row.status == -1">{{ t('failReason') }}{{ row.fail_reason }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" :label="t('createTime')" align="center" />
|
||||
@ -34,6 +33,8 @@
|
||||
<el-button type="primary" link>
|
||||
{{ t('preview') }}</el-button>
|
||||
</el-tooltip>
|
||||
<el-button type="primary" link v-if="row.status == -1" @click="handleFailReason(row)">
|
||||
{{ t('failReason') }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -66,6 +67,11 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="failReasonDialogVisible" :title="t('failReason')" width="60%">
|
||||
<el-scrollbar class="h-[60vh] w-full whitespace-pre p-[20px]">
|
||||
{{ failReason }}
|
||||
</el-scrollbar>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -248,6 +254,13 @@ const configElMessageBox = () => {
|
||||
}).catch((action: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
const failReason = ref('')
|
||||
const failReasonDialogVisible = ref(false)
|
||||
const handleFailReason = (data: any) => {
|
||||
failReason.value = data.fail_reason
|
||||
failReasonDialogVisible.value = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container p-5">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-change="handleClick">
|
||||
<el-tab-pane :label="t('weappAccessFlow')" name="/channel/weapp" />
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="w-full p-5 bg-white">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]">{{ t('title') }}</span>
|
||||
<span class="text-page-title">{{ t('title') }}</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-change="handleClick">
|
||||
<el-tab-pane :label="t('wechatAccessFlow')" name="/channel/wechat" />
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container p-5">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-change="handleClick">
|
||||
<el-tab-pane :label="t('wechatAccessFlow')" name="/channel/wechat" />
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container p-5">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-change="handleClick">
|
||||
<el-tab-pane :label="t('wechatAccessFlow')" name="/channel/wechat" />
|
||||
@ -10,7 +10,7 @@
|
||||
</el-tabs>
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<el-button type="primary" class="w-[100px]" @click="batchAcquisitionFn">{{ t('batchAcquisition')
|
||||
}}</el-button>
|
||||
</div>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
<el-button type="primary" @click="addEvent">
|
||||
{{ t('addDict') }}
|
||||
</el-button>
|
||||
|
||||
@ -1,162 +0,0 @@
|
||||
<template>
|
||||
<!-- 内容 -->
|
||||
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
|
||||
<div class="edit-attr-item-wrap">
|
||||
<h3 class="mb-[10px]">{{ t('addonListSet') }}</h3>
|
||||
<el-form label-width="100px" class="px-[10px]">
|
||||
<div ref="addonBoxRef">
|
||||
<div v-for="(item,index) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
|
||||
<div v-show="item.title" class="flex items-center pb-[10px]">
|
||||
<img class="w-[60px] h-[60px] rounded-md" :src="img(item.icon)" />
|
||||
<div class="flex flex-col justify-center ml-[10px] leading-[1]">
|
||||
<span class="text-[14px]">{{item.title}}</span>
|
||||
<span class="text-[12px] text-[#999] mt-[8px]">{{item.desc}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]" v-show="diyStore.editComponent.list.length > 1" @click="diyStore.editComponent.list.splice(index,1)">
|
||||
<icon name="element-CircleCloseFilled" color="#bbb" size="20px"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button class="w-full" @click="addAddon">{{ t('addAddon') }}</el-button>
|
||||
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="showDialog" :title="t('addonListTips')" width="600px" :close-on-press-escape="false" :close-on-click-modal="false">
|
||||
|
||||
<div>
|
||||
|
||||
<el-table :data="addonTableData.data" size="large" v-loading="addonTableData.loading" @current-change="handleCurrentChange" highlight-current-row max-height="500px">
|
||||
<template #empty>
|
||||
<span>{{ !addonTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
|
||||
<el-table-column :label="t('addonIcon')" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-image class="w-[50px] h-[50px]" v-if="row.icon" :src="img(row.icon)" fit="contain"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="title" :show-overflow-tooltip="true" width="120" :label="t('addonTitle')" />
|
||||
|
||||
<el-table-column prop="desc" :show-overflow-tooltip="true" :label="t('addonDesc')" />
|
||||
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<!-- 样式 -->
|
||||
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
|
||||
|
||||
<!-- 组件样式 -->
|
||||
<slot name="style"></slot>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from '@/lang'
|
||||
import useDiyStore from '@/stores/modules/diy'
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue'
|
||||
import { img } from '@/utils/common'
|
||||
import { getWapIndexList } from '@/app/api/sys'
|
||||
import Sortable from 'sortablejs'
|
||||
import { range } from 'lodash-es'
|
||||
|
||||
const diyStore = useDiyStore()
|
||||
diyStore.editComponent.ignore = [] // 忽略公共属性
|
||||
|
||||
// 组件验证
|
||||
diyStore.editComponent.verify = (index: number) => {
|
||||
const res = { code: true, message: '' }
|
||||
// if (diyStore.value[index].list.length === 0) {
|
||||
// res.code = false;
|
||||
// res.message = t('selectAddonTips');
|
||||
// }
|
||||
return res
|
||||
}
|
||||
|
||||
const showDialog = ref(false)
|
||||
|
||||
const addonBoxRef = ref()
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
const sortable = Sortable.create(addonBoxRef.value, {
|
||||
group: 'item-wrap',
|
||||
animation: 200,
|
||||
onEnd: event => {
|
||||
const temp = diyStore.editComponent.list[event.oldIndex!]
|
||||
diyStore.editComponent.list.splice(event.oldIndex!, 1)
|
||||
diyStore.editComponent.list.splice(event.newIndex!, 0, temp)
|
||||
sortable.sort(
|
||||
range(diyStore.editComponent.list.length).map(value => {
|
||||
return value.toString()
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const addonTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
title: '',
|
||||
key: '',
|
||||
}
|
||||
})
|
||||
|
||||
// 获取插件列表
|
||||
const loadAddonList = (page: number = 1) => {
|
||||
addonTableData.loading = true
|
||||
addonTableData.page = page
|
||||
|
||||
getWapIndexList({
|
||||
...addonTableData.searchParam
|
||||
}).then(res => {
|
||||
addonTableData.loading = false
|
||||
addonTableData.data = res.data
|
||||
addonTableData.total = res.data.length
|
||||
}).catch(() => {
|
||||
addonTableData.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
loadAddonList()
|
||||
|
||||
const handleCurrentChange = (val:any) => {
|
||||
const item:any = {
|
||||
id: diyStore.generateRandom(),
|
||||
key: '',
|
||||
title: '',
|
||||
url: '',
|
||||
icon: '',
|
||||
desc: ''
|
||||
}
|
||||
for (let k in val) {
|
||||
item[k] = val[k]
|
||||
}
|
||||
|
||||
diyStore.editComponent.list.push(item)
|
||||
showDialog.value = false
|
||||
}
|
||||
|
||||
const addAddon = () => {
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
@ -32,7 +32,7 @@
|
||||
<h3 class="mb-[10px]">{{ t('marginSet') }}</h3>
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
<el-form-item :label="t('marginBoth')">
|
||||
<el-slider v-model="diyStore.global.template.margin.both" show-input size="small" class="ml-[10px] horz-blank-slider"/>
|
||||
<el-slider v-model="diyStore.global.template.margin.both" show-input size="small" @input="inputBoth" class="ml-[10px] horz-blank-slider"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
@ -60,6 +60,15 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
// 改变页面的左右边距时,更新所有组件的数值
|
||||
const inputBoth = (value:any)=>{
|
||||
|
||||
diyStore.value.forEach((item,index)=>{
|
||||
item.margin.both = value;
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
</script>
|
||||
|
||||
|
||||
@ -20,11 +20,11 @@
|
||||
<el-form label-width="80px" class="px-[10px]">
|
||||
|
||||
<ul class="layout">
|
||||
<li v-for="(li,i) in selectTemplate.dimensionScale" :key="i" :class="[selectTemplate.className]" :style="{ width: rubikCubeList[i].widthStyle, height: rubikCubeList[i].imgHeight + 'px' }">
|
||||
<div class="have-preview-image" v-show="diyStore.editComponent.list[i].imageUrl">
|
||||
<img class="!w-full !h-full" :src="img(diyStore.editComponent.list[i].imageUrl)"/>
|
||||
<li v-for="(li,i) in selectTemplate.dimensionScale" :key="i" :class="[selectTemplate.className]">
|
||||
<div class="have-preview-image" v-show="diyStore.editComponent.list[i].imageUrl && diyStore.editComponent.list[i].imageUrl != 'static/resource/images/diy/figure.png'">
|
||||
<img :src="img(diyStore.editComponent.list[i].imageUrl)"/>
|
||||
</div>
|
||||
<div class="empty" :class="[selectTemplate.className]" v-show="!diyStore.editComponent.list[i].imageUrl">
|
||||
<div class="empty" :class="[selectTemplate.className]" v-show="!diyStore.editComponent.list[i].imageUrl || diyStore.editComponent.list[i].imageUrl == 'static/resource/images/diy/figure.png'">
|
||||
<p>{{li.name}}</p>
|
||||
<p>{{li.desc}}</p>
|
||||
</div>
|
||||
@ -267,25 +267,11 @@ const templateList = ref([
|
||||
}
|
||||
])
|
||||
|
||||
const rubikCubeList = ref([])
|
||||
const selectTemplate = computed(() => {
|
||||
let data
|
||||
templateList.value.forEach((item) => {
|
||||
if (item.className == diyStore.editComponent.mode) {
|
||||
data = item
|
||||
|
||||
rubikCubeList.value = JSON.parse(JSON.stringify(diyStore.editComponent.list))
|
||||
if (item.className == 'row2-lt-of2-rt') {
|
||||
calcFourSquare()
|
||||
} else if (item.className == 'row1-lt-of2-rt') {
|
||||
calcRowOneLeftOfTwoRight()
|
||||
} else if (item.className == 'row1-tp-of2-bm') {
|
||||
calcRowOneTopOfTwoBottom()
|
||||
} else if (item.className == 'row1-lt-of1-tp-of2-bm') {
|
||||
calcRowOneLeftOfOneTopOfTwoBottom()
|
||||
} else {
|
||||
calcSingleRow(item.className)
|
||||
}
|
||||
}
|
||||
})
|
||||
return data
|
||||
@ -343,152 +329,6 @@ const handleHeight = (isCalcHeight:boolean = false) => {
|
||||
}
|
||||
|
||||
defineExpose({})
|
||||
|
||||
/**
|
||||
* 魔方:单行多个,平分宽度
|
||||
* 公式:
|
||||
* 宽度:屏幕宽度/2,示例:375/2=187.5
|
||||
* 比例:原图高/原图宽,示例:322/690=0.46
|
||||
* 高度:宽度*比例,示例:187.5*0.46=86.25
|
||||
*/
|
||||
const calcSingleRow = (type:any) => {
|
||||
let maxHeight = 0
|
||||
let paramsRatio = 2
|
||||
let paramsWidth = 'calc(100% / 2)'
|
||||
if (type == 'row1-of3') {
|
||||
paramsRatio = 3
|
||||
paramsWidth = 'calc(100% / 3)'
|
||||
}
|
||||
if (type == 'row1-of4') {
|
||||
paramsRatio = 4
|
||||
paramsWidth = 'calc(100% / 4)'
|
||||
}
|
||||
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
const ratio = item.imgHeight / item.imgWidth
|
||||
|
||||
const width = 330
|
||||
item.imgWidth = width / paramsRatio
|
||||
item.imgHeight = item.imgWidth * ratio
|
||||
|
||||
if (maxHeight == 0 || maxHeight < item.imgHeight) maxHeight = item.imgHeight
|
||||
})
|
||||
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
item.widthStyle = paramsWidth
|
||||
item.imgHeight = maxHeight
|
||||
})
|
||||
};
|
||||
|
||||
/**
|
||||
* 魔方:四方型,各占50%
|
||||
*/
|
||||
const calcFourSquare = () => {
|
||||
let maxHeightFirst = 0
|
||||
let maxHeightTwo = 0
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
const ratio = item.imgHeight / item.imgWidth
|
||||
item.imgWidth = 330
|
||||
item.imgWidth = item.imgWidth / 2
|
||||
item.imgHeight = item.imgWidth * ratio
|
||||
|
||||
// 获取每行最大高度
|
||||
if (index <= 1) {
|
||||
if (maxHeightFirst == 0 || maxHeightFirst < item.imgHeight) {
|
||||
maxHeightFirst = item.imgHeight
|
||||
}
|
||||
} else if (index > 1) {
|
||||
if (maxHeightTwo == 0 || maxHeightTwo < item.imgHeight) {
|
||||
maxHeightTwo = item.imgHeight
|
||||
}
|
||||
}
|
||||
})
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
item.imgWidth = 'calc(100% / 2)'
|
||||
item.widthStyle = item.imgWidth
|
||||
if (index <= 1) {
|
||||
item.imgHeight = maxHeightFirst
|
||||
} else if (index > 1) {
|
||||
item.imgHeight = maxHeightTwo
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 魔方:1左2右
|
||||
*/
|
||||
const calcRowOneLeftOfTwoRight = () => {
|
||||
let rightHeight = 0 // 右侧两图平分高度
|
||||
let divide = 'left' // 划分规则,left:左,right:右
|
||||
if (rubikCubeList.value[1].imgWidth === rubikCubeList.value[2].imgWidth) divide = 'right'
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
if (index == 0) {
|
||||
const ratio = item.imgHeight / item.imgWidth // 获取左图的尺寸比例
|
||||
item.imgWidth = 330
|
||||
item.imgWidth = item.imgWidth / 2
|
||||
item.imgHeight = item.imgWidth * ratio
|
||||
rightHeight = item.imgHeight / 2
|
||||
item.imgWidth += 'px'
|
||||
} else {
|
||||
item.imgWidth = rubikCubeList.value[0].imgWidth
|
||||
item.imgHeight = rightHeight
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 魔方:1上2下
|
||||
*/
|
||||
const calcRowOneTopOfTwoBottom = () => {
|
||||
let maxHeight = 0
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
const ratio = item.imgHeight / item.imgWidth // 获取左图的尺寸比例
|
||||
if (index == 0) {
|
||||
item.imgWidth = 330
|
||||
} else if (index > 0) {
|
||||
item.imgWidth = 330
|
||||
item.imgWidth = item.imgWidth / 2
|
||||
}
|
||||
|
||||
item.imgHeight = item.imgWidth * ratio
|
||||
|
||||
// 获取最大高度
|
||||
if (index > 0 && (maxHeight == 0 || maxHeight < item.imgHeight)) {
|
||||
maxHeight = item.imgHeight
|
||||
}
|
||||
})
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
item.imgWidth += 'px'
|
||||
item.widthStyle = item.imgWidth
|
||||
if (index > 0) item.imgHeight = maxHeight
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 魔方:1左3右
|
||||
*/
|
||||
const calcRowOneLeftOfOneTopOfTwoBottom = () => {
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
// 左图
|
||||
if (index == 0) {
|
||||
const ratio = item.imgHeight / item.imgWidth // 获取左图的尺寸比例
|
||||
item.imgWidth = 330
|
||||
item.imgWidth = item.imgWidth / 2
|
||||
item.imgHeight = item.imgWidth * ratio
|
||||
} else if (index == 1) {
|
||||
item.imgWidth = rubikCubeList.value[0].imgWidth
|
||||
item.imgHeight = rubikCubeList.value[0].imgHeight / 2
|
||||
} else if (index > 1) {
|
||||
item.imgWidth = rubikCubeList.value[0].imgWidth / 2
|
||||
item.imgHeight = rubikCubeList.value[1].imgHeight
|
||||
}
|
||||
})
|
||||
|
||||
rubikCubeList.value.forEach((item:any, index) => {
|
||||
item.imgWidth += 'px'
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -675,6 +515,7 @@ const calcRowOneLeftOfOneTopOfTwoBottom = () => {
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 322px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
@ -684,9 +525,9 @@ const calcRowOneLeftOfOneTopOfTwoBottom = () => {
|
||||
border-bottom: 1px transparent solid;
|
||||
|
||||
div.have-preview-image {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
@ -697,6 +538,7 @@ const calcRowOneLeftOfOneTopOfTwoBottom = () => {
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
@ -744,6 +586,7 @@ const calcRowOneLeftOfOneTopOfTwoBottom = () => {
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 320px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
@ -756,6 +599,7 @@ const calcRowOneLeftOfOneTopOfTwoBottom = () => {
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
@ -768,6 +612,7 @@ const calcRowOneLeftOfOneTopOfTwoBottom = () => {
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
@ -779,6 +624,7 @@ const calcRowOneLeftOfOneTopOfTwoBottom = () => {
|
||||
div.have-preview-image {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
line-height: 160px;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<p class="absolute top-[54px] left-[50%] translate-x-[-50%] text-[14px] truncate w-[130px] text-center">{{ page.use_template.title }}</p>
|
||||
|
||||
<div v-show="page.use_template.url" class="w-[320px] h-[550px] mx-auto">
|
||||
<iframe :id="'previewIframe_' + key" v-show="page.loadingIframe" class="w-[320px] h-[550px] mx-auto" :src="page.use_template.wapPreview" frameborder="0"></iframe>
|
||||
<iframe :id="'previewIframe_' + type" v-show="page.loadingIframe" class="w-[320px] h-[550px] mx-auto" :src="page.use_template.wapPreview" frameborder="0"></iframe>
|
||||
<div v-show="page.loadingDev" class="w-[320px] h-[550px] mx-auto bg-body pt-[20px] px-[20px]">
|
||||
<div class="font-bold text-xl mb-[40px]">{{ t('developTitle') }}</div>
|
||||
<div class="mb-[20px] flex flex-col">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<el-button type="primary" class="w-[100px]" @click="dialogVisible = true">{{ t('addDiyPage') }}</el-button>
|
||||
</div>
|
||||
|
||||
@ -52,11 +52,11 @@
|
||||
|
||||
<el-table-column :label="t('operation')" fixed="right" align="right" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="toPreview(row)">{{ t('promote') }}</el-button>
|
||||
<el-button type="primary" link @click="toPreview(row)">{{ t('preview') }}</el-button>
|
||||
<el-button v-if="row.is_default == 0" type="primary" link @click="setUse(row.id)">{{ t('use') }}</el-button>
|
||||
<el-button v-if="row.type == 'DIY_PAGE'" type="primary" link @click="openShare(row)">{{ t('shareSet') }}</el-button>
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
|
||||
<el-button v-if="row.is_default == 0 || row.type == 'DIY_PAGE'" type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@ -163,10 +163,11 @@ const addEvent = async (formEl: FormInstance | undefined) => {
|
||||
if (valid) {
|
||||
dialogVisible.value = false
|
||||
const query = { type: formData.type, title: formData.title }
|
||||
router.push({
|
||||
const url = router.resolve({
|
||||
path: '/decorate/edit',
|
||||
query
|
||||
})
|
||||
window.open(url.href)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -350,4 +351,4 @@ const resetForm = (formEl: FormInstance | undefined) => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<p class="absolute top-[54px] left-[50%] translate-x-[-50%] text-[14px] truncate w-[130px] text-center">{{ page.use_template.title }}</p>
|
||||
|
||||
<div v-show="page.use_template.url" class="w-[320px] h-[550px] mx-auto">
|
||||
<iframe :id="'previewIframe_' + key" v-show="page.loadingIframe" class="w-[320px] h-[550px] mx-auto" :src="page.use_template.wapPreview" frameborder="0"></iframe>
|
||||
<iframe :id="'previewIframe_' + type" v-show="page.loadingIframe" class="w-[320px] h-[550px] mx-auto" :src="page.use_template.wapPreview" frameborder="0"></iframe>
|
||||
<div v-show="page.loadingDev" class="w-[320px] h-[550px] mx-auto bg-body pt-[20px] px-[20px]">
|
||||
<div class="font-bold text-xl mb-[40px]">{{ t('developTitle') }}</div>
|
||||
<div class="mb-[20px] flex flex-col">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
|
||||
<el-table class="mt-[20px]" :data="bottomNavTableData.data" size="large" v-loading="bottomNavTableData.loading">
|
||||
@ -87,4 +87,4 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[5px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<el-card class="box-card !border-none" shadow="never" v-loading="payLoading">
|
||||
<!-- 设置支付配置 -->
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-[10px]">
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container w-full pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[20px]">{{ t('editPersonal') }}</span>
|
||||
<span class="text-page-title">{{ t('editPersonal') }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form :model="saveInfo" label-width="90px" ref="formRef" class="page-form">
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
<span :class="['mr-[12px] cursor-pointer', {'text-[var(--el-color-primary)]': params.app == ''}]" @click="cutAppFn('')">所有应用</span>
|
||||
<span :class="['mr-[12px] cursor-pointer', {'text-[var(--el-color-primary)]': params.app == item.key}]" @click="cutAppFn(item.key)" v-for="(item,index) in addonList" :key="index">{{item.title}}</span>
|
||||
</div>
|
||||
<el-input v-model="params.keywords" class="!w-[300px] !h-[34px]" placeholder="输入要搜索的站点名称" @keyup.enter.native="query">
|
||||
<el-input v-model="params.keywords" class="!w-[300px] !h-[34px]" placeholder="请输入要搜索的站点名称" @keyup.enter.native="getHomeSiteFn()">
|
||||
<template #suffix>
|
||||
<el-icon @click.stop="getHomeSiteFn()" class="cursor-pointer">
|
||||
<Search />
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container w-full pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[20px]">{{ t("personal") }}</span>
|
||||
<span class="text-page-title">{{ t("personal") }}</span>
|
||||
<span class="text-[14px] text-[#999] cursor-pointer" @click="toEditPersonal">{{ t("editPersonal") }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container w-full pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[20px]">{{ t('editPersonal') }}</span>
|
||||
<span class="text-page-title">{{ t('editPersonal') }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<el-form :model="saveInfo" label-width="90px" ref="formRef" class="page-form">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container w-full pt-[64px] bg-white" v-loading="loading">
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[20px]">{{ t('personal') }}</span>
|
||||
<span class="text-page-title">{{ t('personal') }}</span>
|
||||
<span class="text-[14px] text-[#999] cursor-pointer" @click="toEditPersonal">{{ t('editPersonal') }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="pt-[59px] px-[20px] app-store" v-loading="authLoading">
|
||||
<div>
|
||||
<div class="flex justify-between items-center h-[32px] mb-4">
|
||||
<span class="text-[20px] text-[#222]">{{ t('localAppText') }}</span>
|
||||
<span class="text-page-title text-[#222]">{{ t('localAppText') }}</span>
|
||||
<el-input class="!w-[250px]" :placeholder="t('search')" v-model="search_name" @keyup.enter="query">
|
||||
<template #suffix>
|
||||
<el-icon class="el-input__icon cursor-pointer" size="14px" @click="query">
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="box-border pt-[64px]">
|
||||
<div class="text-[20px] text-[#222] mb-[32px] pl-[14px]">工具管理</div>
|
||||
<div class="text-page-title text-[#222] mb-[32px] pl-[14px]">工具管理</div>
|
||||
<div class="flex flex-wrap mt-[28px]">
|
||||
<div class="w-[256px] tools-item-shadow mb-[24px] mx-[14px] rounded-[8px] flex flex-col cursor-pointer leading-[1]" @click="toLink('/admin/tools/addon')">
|
||||
<div class="flex-1 pt-[18px] pb-[14px] px-[24px] flex flex-col">
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
<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">
|
||||
<template #prepend>
|
||||
<icon name="element-User" />
|
||||
@ -24,6 +25,7 @@
|
||||
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="form.password" :placeholder="t('passwordPlaceholder')" type="password"
|
||||
autocomplete="new-password"
|
||||
@keyup.enter="handleLogin(formRef)" :show-password="true"
|
||||
class="h-[40px] input-with-select">
|
||||
<template #prepend>
|
||||
@ -57,6 +59,7 @@
|
||||
<el-form :model="form" ref="formRef" :rules="formRules">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="form.username" @keyup.enter="handleLogin(formRef)"
|
||||
autocomplete="off"
|
||||
class="w-50 m-1 h-[40px]" :placeholder="t('userPlaceholder')">
|
||||
<template #prefix>
|
||||
<icon name="element-User" />
|
||||
@ -66,6 +69,7 @@
|
||||
|
||||
<el-form-item prop="password">
|
||||
<el-input type="password" v-model="form.password" @keyup.enter="handleLogin(formRef)"
|
||||
autocomplete="new-password"
|
||||
:show-password="true" class="w-50 m-1 h-[40px]"
|
||||
:placeholder="t('passwordPlaceholder')">
|
||||
<template #prefix>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[5px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[5px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('mobile')" prop="mobile">
|
||||
<el-input v-model="formData.mobile" clearable :placeholder="t('mobilePlaceholder')" type="number" class="input-width" />
|
||||
<el-input v-model="formData.mobile" clearable :placeholder="t('mobilePlaceholder')" @keyup="filterNumber($event)" class="input-width" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('nickname')">
|
||||
@ -37,6 +37,7 @@ import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { addMember, getMemberList, getMemberNo } from '@/app/api/member'
|
||||
import { filterNumber } from '@/utils/common'
|
||||
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<el-input v-model="formData.memo" type="textarea" rows="4" clearable :placeholder="t('memoPlaceholder')" class="input-width"/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('sort')" prop="sort">
|
||||
<el-input v-model="formData.sort" clearable :placeholder="t('sortPlaceholder')" class="input-width" type="number" />
|
||||
<el-input v-model="formData.sort" clearable :placeholder="t('sortPlaceholder')" class="input-width" @keyup="filterNumber($event)" />
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
@ -27,6 +27,7 @@ import { ref, reactive, computed } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { addMemberLabel, updateMemberLabel, getMemberLabelInfo } from '@/app/api/member'
|
||||
import { filterNumber } from '@/utils/common'
|
||||
|
||||
const showDialog = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
<el-button type="primary" @click="addEvent">{{ t('addMemberLabel') }}</el-button>
|
||||
</div>
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<el-button type="primary" @click="addEvent">{{ t('addMember') }}</el-button>
|
||||
</div>
|
||||
|
||||
@ -48,7 +48,7 @@
|
||||
<span>{{ !memberTableData.loading ? t('emptyData') : '' }}</span>
|
||||
</template>
|
||||
<el-table-column prop="member_no" :label="t('memberNo')" min-width="120" />
|
||||
<el-table-column prop="nickname" :show-overflow-tooltip="true" :label="t('nickname')" min-width="170">
|
||||
<el-table-column prop="nickname" :show-overflow-tooltip="true" :label="t('memberInfo')" min-width="170">
|
||||
<template #default="{ row }">
|
||||
<div class="flex items-center">
|
||||
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.headimg" :src="img(row.headimg)" alt="">
|
||||
@ -69,9 +69,9 @@
|
||||
<el-table-column prop="balance" :label="t('balance')" min-width="130" align="right" />
|
||||
<el-table-column prop="member_label" :label="t('lable')" min-width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<div class="flex flex-col items-start">
|
||||
<div class="flex flex-col items-center">
|
||||
<div v-for="(item, key) in row.member_label_array" class="my-[3px]" :key="key">
|
||||
<el-tag class="ml-[13px]" type="info">{{ item.label_name }}</el-tag>
|
||||
<el-tag type="info">{{ item.label_name }}</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[5px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none base-bg !px-[35px]" shadow="never">
|
||||
<el-row class="flex">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[5px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none table-search-wra base-bg !px-[35px]" shadow="never">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[5px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none table-search-wra base-bg !px-[35px]" shadow="never">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
|
||||
<el-form :model="formData" label-width="150px" ref="ruleFormRef" class="page-form" v-loading="loading">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
<div class="mt-[20px]">
|
||||
<el-table :data="agreementTableData.data" size="large" v-loading="agreementTableData.loading">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
<el-form :model="formData" label-width="150px" ref="ruleFormRef" :rules="rules" class="page-form" v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
@ -11,11 +11,11 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('cashWithdrawalAmount')" v-if="formData.is_open" prop="min">
|
||||
<el-input v-model="formData.min" type="number" class="input-width" :placeholder="t('cashWithdrawalAmountPlaceholder')" />
|
||||
<el-input v-model="formData.min" @keyup="filterDigit($event)" class="input-width" :placeholder="t('cashWithdrawalAmountPlaceholder')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('commissionRatio')" v-if="formData.is_open" prop="rate">
|
||||
<el-input v-model="formData.rate" type="number" class="input-width" :placeholder="t('commissionRatioPlaceholder')" />
|
||||
<el-input v-model="formData.rate" @keyup="filterDigit($event)" class="input-width" :placeholder="t('commissionRatioPlaceholder')" />
|
||||
<span class="ml-2">%</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('audit')" v-if="formData.is_open" class="items-center">
|
||||
@ -53,6 +53,7 @@ import { t } from '@/lang'
|
||||
import { getCashOutConfig, setCashOutConfig, getTransfertype } from '@/app/api/member'
|
||||
import { FormRules, FormInstance } from 'element-plus'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { filterDigit } from '@/utils/common'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
<el-form :model="formData" label-width="150px" ref="ruleFormRef" class="page-form" v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('length')" prop="length">
|
||||
<el-input v-model="formData.length" :placeholder="t('lengthPlaceholder')" class="input-width" clearable type="number" @change="getMemberNo(ruleFormRef)"/>
|
||||
<el-input v-model="formData.length" :placeholder="t('lengthPlaceholder')" class="input-width" clearable @keyup="filterNumber($event)" @change="getMemberNo(ruleFormRef)"/>
|
||||
<div class="form-tip">{{ t('lengthTips') }}</div>
|
||||
</el-form-item>
|
||||
|
||||
@ -32,6 +32,7 @@ import { reactive, ref } from 'vue'
|
||||
import { t } from '@/lang'
|
||||
import { getMemberConfig, setMemberConfig } from '@/app/api/member'
|
||||
import { FormInstance, FormRules } from 'element-plus'
|
||||
import { filterNumber } from '@/utils/common'
|
||||
|
||||
const loading = ref(true)
|
||||
const ruleFormRef = ref<FormInstance>({})
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container" v-loading="noticeTableData.loading">
|
||||
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<h3 class="panel-title !text-base">{{ t('buyerNotice') }}</h3>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<el-card class="box-card !border-none" shadow="never" v-loading="payLoading">
|
||||
<!-- 设置支付配置 -->
|
||||
<div class="flex justify-between items-center" v-if="!payLoading">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<el-button type="primary" @click="isEdit = true" ref="setConfigBtn">{{ t('setConfig') }}</el-button>
|
||||
</div>
|
||||
<el-card class="box-card box-pay-card !border-none mt-[20px]" shadow="never"
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
<div class="mt-[20px]">
|
||||
<el-table :data="smsTableData.data" size="large" v-loading="smsTableData.loading">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="recordsTableData.searchParam" ref="searchFormRef">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
<div class="mt-[16px]">
|
||||
<el-table :data="storageTableData.data" size="large" v-loading="loading">
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<el-form :model="formData" label-width="150px" ref="formRef" :rules="formRules" class="page-form"
|
||||
v-loading="loading">
|
||||
<el-form :model="formData" label-width="150px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<h3 class="panel-title !text-sm">{{ t('websiteInfo') }}</h3>
|
||||
|
||||
<el-form-item :label="t('siteName')" prop="site_name">
|
||||
<el-input v-model="formData.site_name" :placeholder="t('siteNamePlaceholder')" class="input-width"
|
||||
clearable maxlength="20" />
|
||||
<el-input v-model="formData.site_name" :placeholder="t('siteNamePlaceholder')" class="input-width" clearable maxlength="20" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('logo')">
|
||||
@ -25,20 +23,17 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('keywords')">
|
||||
<el-input v-model="formData.keywords" :placeholder="t('keywordsPlaceholder')" class="input-width"
|
||||
clearable maxlength="20" />
|
||||
<el-input v-model="formData.keywords" :placeholder="t('keywordsPlaceholder')" class="input-width" clearable maxlength="20" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('desc')">
|
||||
<el-input v-model="formData.desc" type="textarea" rows="4" clearable :placeholder="t('descPlaceholder')"
|
||||
class="input-width" maxlength="100" />
|
||||
<el-input v-model="formData.desc" type="textarea" rows="4" clearable :placeholder="t('descPlaceholder')" class="input-width" maxlength="100" />
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<h3 class="panel-title !text-sm">{{ t('frontEndInfo') }}</h3>
|
||||
<el-form-item :label="t('frontEndName')">
|
||||
<el-input v-model="formData.front_end_name" :placeholder="t('frontEndNamePlaceholder')"
|
||||
class="input-width" clearable maxlength="20" />
|
||||
<el-input v-model="formData.front_end_name" :placeholder="t('frontEndNamePlaceholder')" class="input-width" clearable maxlength="20" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('frontEndLogo')">
|
||||
@ -48,8 +43,7 @@
|
||||
<el-card class="box-card !border-none" shadow="never" v-if="app_type == 'admin'">
|
||||
<h3 class="panel-title !text-sm">{{ t('serviceInformation') }}</h3>
|
||||
<el-form-item :label="t('contactsTel')">
|
||||
<el-input v-model="formData.tel" :placeholder="t('contactsTelPlaceholder')" class="input-width"
|
||||
clearable maxlength="20" />
|
||||
<el-input v-model="formData.tel" :placeholder="t('contactsTelPlaceholder')" class="input-width" clearable maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('wechatCode')">
|
||||
<upload-image v-model="formData.wechat_code" />
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
</template>
|
||||
</el-alert>
|
||||
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
|
||||
<span class="text-[20px]">{{pageName}}</span>
|
||||
<span class="text-page-title">{{pageName}}</span>
|
||||
</div>
|
||||
<el-form :model="formData" label-width="200px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<el-button type="primary" @click="showEvent">{{ t('addVersion') }}</el-button>
|
||||
</div>
|
||||
<div class="mt-[10px]">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="main-container">
|
||||
<div class="flex ml-[18px] justify-between items-center mt-[20px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form" v-loading="loading">
|
||||
<el-card class="box-card !border-none mt-[5px]" shadow="never">
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
</el-form-item> -->
|
||||
|
||||
<el-form-item :label="t('manager')" prop="uid">
|
||||
<el-select v-model="formData.uid" :placeholder="t('managerPlaceholder')" class="input-width" filterable>
|
||||
<el-select v-model="formData.uid" :placeholder="t('managerPlaceholder')" class="input-width" filterable autocomplete="off">
|
||||
<el-option :label="t('newAddManager')" :value="0">
|
||||
<template #default>
|
||||
<div class="flex items-center">
|
||||
@ -45,17 +45,17 @@
|
||||
<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" />
|
||||
class="input-width" autocomplete="new-password"/>
|
||||
</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" />
|
||||
class="input-width" :show-password="true" type="password" autocomplete="new-password"/>
|
||||
</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" />
|
||||
type="password" :show-password="true" clearable class="input-width" autocomplete="new-password" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
@ -73,6 +73,16 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<el-form-item :label="t('siteDomain')" prop="site_domain">
|
||||
<el-input v-model="formData.site_domain" clearable :placeholder="t('siteDomainPlaceholder')"
|
||||
class="input-width" />
|
||||
<div>
|
||||
<p class="text-[12px] text-[#a9a9a9] leading-normal mt-[5px]">{{ t('siteDomainTips') }}</p>
|
||||
<p class="text-[12px] text-[#a9a9a9] leading-normal mt-[5px]">{{ t('siteDomainTipsTwo') }}</p>
|
||||
<p class="text-[12px] text-[#a9a9a9] leading-normal mt-[5px]">{{ t('siteDomainTipsThree') }}{{ domain }}</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('expireTime')" prop="expire_time" class="input-width">
|
||||
<el-date-picker class="flex-1 !flex" v-model="formData.expire_time" clearable type="datetime"
|
||||
:placeholder="t('expireTimePlaceholder')" />
|
||||
@ -102,6 +112,7 @@ const loading = ref(true)
|
||||
const groupList = ref([])
|
||||
const siteUser = ref([])
|
||||
const siteType = ref([])
|
||||
const domain = location.hostname
|
||||
getAllUserList({}).then(({ data }) => {
|
||||
siteUser.value = data
|
||||
}).catch()
|
||||
@ -121,6 +132,7 @@ const initialFormData = {
|
||||
password: '',
|
||||
confirm_password: '',
|
||||
expire_time: end,
|
||||
site_domain: '',
|
||||
group_id: ''
|
||||
}
|
||||
const formData: Record<string, any> = reactive({ ...initialFormData })
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<el-button type="primary" class="w-[100px]" @click="addEvent">
|
||||
{{ t('addSiteGroup') }}
|
||||
</el-button>
|
||||
|
||||
@ -3,10 +3,15 @@
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<el-button type="primary" class="w-[100px]" @click="addEvent">
|
||||
{{ t('addSite') }}
|
||||
</el-button>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<div>
|
||||
<el-button type="primary" class="w-[100px]" @click="addEvent">
|
||||
{{ t('addSite') }}
|
||||
</el-button>
|
||||
<el-button type="default" class="w-[100px]" @click="toSiteLink">
|
||||
{{ t('toSite') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
@ -15,6 +20,10 @@
|
||||
<el-input v-model="siteTableData.searchParam.keywords" :placeholder="t('siteNamePlaceholder')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('siteDomain')" prop="site_domain">
|
||||
<el-input v-model="siteTableData.searchParam.site_domain" :placeholder="t('siteDomainPlaceholder')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="t('app')" prop="app_id">
|
||||
<el-select v-model="siteTableData.searchParam.app" clearable @change="appChangeFn"
|
||||
:placeholder="t('appIdPlaceholder')" class="input-width">
|
||||
@ -92,6 +101,7 @@
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="group_name" :label="t('groupId')" width="150" :show-overflow-tooltip="true" />
|
||||
<el-table-column prop="site_domain" :label="t('siteDomain')" width="150" :show-overflow-tooltip="true" />
|
||||
<el-table-column prop="create_time" :label="t('createTime')" width="250"
|
||||
:show-overflow-tooltip="true" />
|
||||
<el-table-column prop="expire_time" :label="t('expireTime')" width="250" :show-overflow-tooltip="true">
|
||||
@ -114,16 +124,11 @@
|
||||
|
||||
<el-table-column :label="t('operation')" min-width="250" align="right" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="toSiteLink(row)">
|
||||
<!-- <a href="javascript:;" title="启动站点" class="iconfont iconicon_huojian"></a>-->
|
||||
访问站点
|
||||
</el-button>
|
||||
<el-button type="primary" link @click="openClose(row.status, row.site_id)"
|
||||
v-if="row.status == 1 || row.status == 3">{{ row.status == 1 ? t('closeTxt') : t('openTxt')
|
||||
}}</el-button>
|
||||
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
|
||||
<el-button type="primary" link @click="deleteEvent(row)">{{ t('delete') }}</el-button>
|
||||
<el-button type="primary" link @click="urlEvent(row)">{{ t('url') }}</el-button>
|
||||
<el-button type="primary" link @click="infoEvent(row)">{{ t('info') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -143,15 +148,14 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { img } from '@/utils/common'
|
||||
import { getToken, img } from '@/utils/common'
|
||||
import { t } from '@/lang'
|
||||
import { getSiteList, getSiteGroupAll, getStatusList, closeSite, openSite, deleteSite } from '@/app/api/site'
|
||||
import { ElMessageBox, FormInstance, ElMessage } from 'element-plus'
|
||||
import { ElMessageBox, FormInstance } from 'element-plus'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import EditSite from '@/app/views/site/components/edit-site.vue'
|
||||
import { getInstalledAddonList } from '@/app/api/addon'
|
||||
// import { CollectionTag } from '@element-plus/icons-vue'
|
||||
// import { deleteMenu } from "@/app/api/sys"
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
|
||||
const route = useRoute()
|
||||
const pageName = route.meta.title
|
||||
@ -173,9 +177,9 @@ const siteTableData = reactive({
|
||||
group_id: '',
|
||||
app: 'all',
|
||||
status: '',
|
||||
site_domain: '',
|
||||
create_time: [],
|
||||
expire_time: []
|
||||
|
||||
}
|
||||
})
|
||||
siteTableData.searchParam.status = route.query.id || ''
|
||||
@ -264,18 +268,6 @@ const infoEvent = (data: any) => {
|
||||
router.push({ path: '/admin/site/info', query: { id: data.site_id } })
|
||||
}
|
||||
|
||||
/**
|
||||
* 站点域名
|
||||
* @param data
|
||||
*/
|
||||
const urlEvent = (data: any) => {
|
||||
ElMessage({
|
||||
message: t('siteUrlDevelopMessage'),
|
||||
grouping: true,
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑站点详情
|
||||
* @param data
|
||||
@ -289,9 +281,11 @@ const editEvent = (data: any) => {
|
||||
* 站点登录
|
||||
* @param data
|
||||
*/
|
||||
const toSiteLink = (data: any) => {
|
||||
window.localStorage.setItem('site.siteId', data.site_id)
|
||||
window.open(`${location.origin}/site/`)
|
||||
const toSiteLink = () => {
|
||||
window.localStorage.setItem('site.token', getToken())
|
||||
window.localStorage.setItem('site.comparisonTokenStorage', getToken())
|
||||
window.localStorage.setItem('site.userinfo', JSON.stringify(useUserStore().userInfo))
|
||||
window.open(`${location.origin}/home/index`)
|
||||
}
|
||||
|
||||
const openClose = (i, site_id) => {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
|
||||
<el-form :inline="true" :model="userTableData.searchParam" ref="searchFormRef">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[10px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeName" class="demo-tabs">
|
||||
<el-tab-pane :label="t('developmentProcess')" name="developmentProcess">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[10px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<el-tabs v-model="activeName" class="demo-tabs">
|
||||
<el-tab-pane :label="t('codeGeneration')" name="codeGeneration">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container attachment-container min-h-[80vh]" v-loading="loading">
|
||||
<el-card class="box-card !border-none" shadow="never" v-if="Object.keys(systemService).length">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
</div>
|
||||
<div class="bg-[#fff] pb-[20px] mb-3">
|
||||
<p class="pt-[20px] pb-[10px] text-sm">{{ t('serverInformation') }}</p>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="main-container">
|
||||
<el-card class="box-card !border-none" shadow="never">
|
||||
<div class="flex justify-between items-center mb-[20px]">
|
||||
<span class="text-[20px]">{{ pageName }}</span>
|
||||
<span class="text-page-title">{{ pageName }}</span>
|
||||
<el-button type="primary" @click="showEvent">{{ t('addCron') }}</el-button>
|
||||
</div>
|
||||
<el-alert class="warm-prompt " type="info">
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<div @click="show">
|
||||
<slot>
|
||||
<el-input v-model="value.title" :placeholder="t('linkPlaceholder')" readonly>
|
||||
<el-input v-model="value.title" :placeholder="t('linkPlaceholder')" readonly class="link-input">
|
||||
<template #suffix>
|
||||
<div @click.stop="clear">
|
||||
<el-icon v-if="value.name">
|
||||
@ -207,4 +207,8 @@ defineExpose({
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss">
|
||||
.link-input .el-input__inner{
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -2,18 +2,15 @@
|
||||
<div>
|
||||
<div @click="show">
|
||||
<slot>
|
||||
<div v-if="value.heatMapData.length">{{ t('selected') }}<span class="text-primary p-[4px]">{{
|
||||
value.heatMapData.length }}</span>{{ t('selectedAfterHotArea') }}</div>
|
||||
<div v-else>{{ t('addHotArea') }}</div>
|
||||
<div v-if="value.heatMapData.length" class="cursor-pointer">{{ t('selected') }}<span class="text-primary p-[4px]">{{ value.heatMapData.length }}</span>{{ t('selectedAfterHotArea') }}</div>
|
||||
<div v-else class="cursor-pointer">{{ t('addHotArea') }}</div>
|
||||
</slot>
|
||||
</div>
|
||||
<el-dialog v-model="showDialog" :title="t('hotAreaSet')" width="45%" :close-on-press-escape="false"
|
||||
:destroy-on-close="true" :close-on-click-modal="false">
|
||||
<el-dialog v-model="showDialog" :title="t('hotAreaSet')" width="810px" :close-on-press-escape="false" :destroy-on-close="true" :close-on-click-modal="false">
|
||||
|
||||
<div class="flex">
|
||||
|
||||
<div class="content-box relative bg-cover bg-gray-100 border border-dashed border-gray-500"
|
||||
:style="{ backgroundImage: 'url(' + img(value.imageUrl) + ')', width: contentBoxWidth + 'px', height: contentBoxHeight + 'px' }">
|
||||
<div class="hot-area-img-wrap content-box relative bg-gray-100 border border-dashed border-gray-500 bg-no-repeat" :style="{ backgroundImage: 'url(' + img(value.imageUrl) + ')', width: contentBoxWidth + 'px', height: contentBoxHeight + 'px' }">
|
||||
<div v-for="(item, index) in dragBoxArr" :id="'box_' + index" :key="index"
|
||||
class="area-box border border-solid border-[#ccc] w-[100px] h-[100px] absolute top-0 left-0 select-none p-[5px]"
|
||||
:style="{ left: item.left + item.unit, top: item.top + item.unit, width: item.width + item.unit, height: item.height + item.unit }"
|
||||
@ -32,16 +29,14 @@
|
||||
|
||||
<el-form label-width="80px" class="pl-[20px]">
|
||||
<h3 class="mb-[10px] text-lg text-black">{{ t('hotAreaManage') }}</h3>
|
||||
<el-button type="primary" plain size="small" class="mb-[10px]" @click="addArea">{{ t('addHotArea')
|
||||
}}</el-button>
|
||||
<el-button type="primary" plain size="small" class="mb-[10px]" @click="addArea">{{ t('addHotArea') }}</el-button>
|
||||
<div class="overflow-y-auto h-[300px]">
|
||||
<template v-for="(item, index) in dragBoxArr" :key="index">
|
||||
<div class="mb-[16px]" v-if="item">
|
||||
<el-form-item :label="t('hotArea') + (index + 1)">
|
||||
<div class="flex items-center">
|
||||
<diy-link v-model="item.link" />
|
||||
<icon class="del cursor-pointer mx-[10px]" name="element-CircleCloseFilled"
|
||||
color="#bbb" size="20px" @click="dragBoxArr.splice(index, 1)" />
|
||||
<icon class="del cursor-pointer mx-[10px]" name="element-CircleCloseFilled" color="#bbb" size="20px" @click="dragBoxArr.splice(index, 1)" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
</div>
|
||||
@ -85,26 +80,42 @@ const value: any = computed({
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* 公式:
|
||||
* 宽度:400
|
||||
* 比例:原图高/原图宽,示例:466/698=0.66
|
||||
* 高度:宽度*比例,示例:400*0.66=264
|
||||
*/
|
||||
|
||||
const showDialog = ref(false)
|
||||
const contentBoxWidth = ref(400)
|
||||
const contentBoxHeight = ref(400)
|
||||
const num = ref(4)// 每行显示的数量
|
||||
const dragBoxArr: any = reactive([])
|
||||
|
||||
const imgRatio = ref(1); // 图片比例
|
||||
|
||||
// 热区尺寸
|
||||
const areaRadio = ref(0.25) // 占位她比例
|
||||
const areaWidth = ref(100)
|
||||
const areaHeight = ref(100)
|
||||
const areaNum = ref(4); // 每行显示的数量
|
||||
|
||||
// 添加热区
|
||||
const addArea = () => {
|
||||
let left = dragBoxArr.length % num.value * 100
|
||||
let top = Math.floor(dragBoxArr.length / num.value) * 100
|
||||
if (top >= contentBoxWidth.value) {
|
||||
let left = dragBoxArr.length % areaNum.value * areaWidth.value
|
||||
let top = Math.floor(dragBoxArr.length / areaNum.value) * areaHeight.value
|
||||
let edgeHeight = top + (areaHeight.value / 2)
|
||||
if (top >= contentBoxHeight.value || edgeHeight >= contentBoxHeight.value) {
|
||||
top = 0
|
||||
left = 0
|
||||
}
|
||||
|
||||
dragBoxArr.push({
|
||||
left: left,
|
||||
top: top,
|
||||
width: 100,
|
||||
height: 100,
|
||||
left,
|
||||
top,
|
||||
width: areaWidth.value,
|
||||
height: areaHeight.value,
|
||||
unit: 'px',
|
||||
link: {
|
||||
name: ''
|
||||
@ -530,6 +541,17 @@ const show = () => {
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 计算图片比例
|
||||
imgRatio.value = value.value.imgHeight / value.value.imgWidth;
|
||||
|
||||
// 根据图片比例,调整图片高度
|
||||
contentBoxHeight.value = Math.floor(contentBoxWidth.value * imgRatio.value);
|
||||
|
||||
areaWidth.value = Math.floor(areaRadio.value * contentBoxHeight.value);
|
||||
areaHeight.value = areaWidth.value;
|
||||
areaNum.value = Math.floor(contentBoxWidth.value / areaWidth.value)
|
||||
|
||||
if (Object.keys(value.value.heatMapData).length) {
|
||||
dragBoxArr.splice(0, dragBoxArr.length, ...value.value.heatMapData)
|
||||
} else {
|
||||
@ -577,6 +599,10 @@ defineExpose({
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.hot-area-img-wrap{
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.box1,
|
||||
.box2,
|
||||
.box3,
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="flex border-t border-b main-wrap border-color w-full" :class="scene == 'select' ? 'h-[40vh]' : 'h-full'">
|
||||
|
||||
<!-- 分组 -->
|
||||
<div class="group-wrap w-[180px] p-[15px] h-full border-r border-color flex flex-col">
|
||||
|
||||
<el-input v-model="categoryParam.name" class="m-0" :placeholder="t('upload.attachmentCategoryPlaceholder')"
|
||||
clearable prefix-icon="Search" @input="getAttachmentCategoryList()" />
|
||||
<div class="group-list flex-1 my-[10px]">
|
||||
<div class="group-list flex-1 my-[10px] h-0">
|
||||
<el-scrollbar>
|
||||
<div class="group-item p-[10px] leading-none text-xs rounded cursor-pointer"
|
||||
:class="{ active: attachmentParam.cate_id == 0 }" @click="attachmentParam.cate_id = 0">
|
||||
<div class="group-item p-[10px] leading-none text-xs rounded cursor-pointer" :class="{ active: attachmentParam.cate_id == 0 }" @click="attachmentParam.cate_id = 0">
|
||||
{{ t('selectPlaceholder') }}
|
||||
</div>
|
||||
<div class="group-item px-[10px] text-xs rounded cursor-pointer flex"
|
||||
@ -24,8 +24,7 @@
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item class="text-center">
|
||||
<popover-input :placeholder="t('upload.attachmentCategoryPlaceholder')"
|
||||
@confirm="updateAttachmentCategory($event, index)" v-model="item.name">
|
||||
<popover-input :placeholder="t('upload.attachmentCategoryPlaceholder')" @confirm="updateAttachmentCategory($event, index)" v-model="item.name">
|
||||
<span>{{ t('edit') }}</span>
|
||||
</popover-input>
|
||||
</el-dropdown-item>
|
||||
@ -40,11 +39,11 @@
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<!-- 添加分组 -->
|
||||
<popover-input :placeholder="t('upload.attachmentCategoryPlaceholder')" @confirm="addAttachmentCategory" v-model="attachmentCategoryName"
|
||||
v-if="prop.type != 'icon'">
|
||||
<popover-input :placeholder="t('upload.attachmentCategoryPlaceholder')" @confirm="addAttachmentCategory" v-model="attachmentCategoryName" v-if="prop.type != 'icon'">
|
||||
<el-button>{{ t('upload.addAttachmentCategory') }}</el-button>
|
||||
</popover-input>
|
||||
</div>
|
||||
|
||||
<!-- 素材 -->
|
||||
<div class="attachment-list-wrap flex flex-col p-[15px] flex-1 overflow-hidden">
|
||||
<el-row :gutter="15" class="h-[32px]">
|
||||
@ -54,11 +53,8 @@
|
||||
<el-button type="primary">{{ t('upload.upload' + type) }} {{ isOpen }}</el-button>
|
||||
</el-upload>
|
||||
<div v-if="scene == 'attachment' && prop.type != 'icon'">
|
||||
<el-button v-if="operate === false" class="ml-[10px]" type="primary"
|
||||
@click="operate = true">{{ t('edit') }}
|
||||
</el-button>
|
||||
<el-button v-else class="ml-[10px]" type="primary" @click="operate = false">{{ t('complete')
|
||||
}}</el-button>
|
||||
<el-button v-if="operate === false" class="ml-[10px]" type="primary" @click="operate = true">{{ t('edit') }}</el-button>
|
||||
<el-button v-else class="ml-[10px]" type="primary" @click="operate = false">{{ t('complete') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
@ -71,38 +67,36 @@
|
||||
<div class="flex-1 my-[15px] h-0" v-loading="attachment.loading">
|
||||
<el-scrollbar>
|
||||
<!-- 选择弹出框 -->
|
||||
<div class="flex flex-wrap"
|
||||
v-if="attachment.data.length && (operate === true || scene != 'attachment')">
|
||||
<div class="attachment-item mr-[10px]" :class="scene == 'select' ? 'w-[100px]' : 'w-[120px]'"
|
||||
v-for="(item, index) in attachment.data" :key="index">
|
||||
<div class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center"
|
||||
:class="scene == 'select' ? 'h-[100px]' : 'h-[120px]'" @click="selectFile(item)">
|
||||
<el-image :src="img(item.url)" fit="contain" v-if="type == 'image'"></el-image>
|
||||
<video :src="img(item.url)" v-else-if="type == 'video'"></video>
|
||||
<icon :name="item.url" size="40px" v-else-if="type == 'icon'"></icon>
|
||||
<div class="absolute z-[1] flex items-center justify-center w-full h-full inset-0 bg-black bg-opacity-60"
|
||||
v-show="selectedFile[item.att_id]">
|
||||
<div class="flex flex-wrap" v-if="attachment.data.length && (operate === true || scene != 'attachment')">
|
||||
<div class="attachment-item mr-[10px]" :class="scene == 'select' ? 'w-[100px]' : 'w-[120px]'" v-for="(item, index) in attachment.data" :key="index">
|
||||
<div class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center" :class="scene == 'select' ? 'h-[100px]' : 'h-[120px]'" @click="selectFile(item)">
|
||||
|
||||
<el-image :src="img(item.url)" fit="contain" v-if="type == 'image'"/>
|
||||
<video :src="img(item.url)" v-else-if="type == 'video'"/>
|
||||
<icon :name="item.url" size="40px" v-else-if="type == 'icon'"/>
|
||||
<div class="absolute z-[1] flex items-center justify-center w-full h-full inset-0 bg-black bg-opacity-60" v-show="selectedFile[item.att_id]">
|
||||
<icon name="element-Select" color="#fff" size="40px" />
|
||||
<div class="file-box-active absolute z-[1] bottom-0 right-0 w-full h-full">
|
||||
<span class="absolute bottom-[2px] right-[2px] text-white z-[2] leading-none">{{ getFileIndex(item.att_id) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<el-tooltip placement="top">
|
||||
<template #content>{{ item.real_name }}</template>
|
||||
<div class="truncate my-[10px] cursor-pointer text-base flex-1 text-center">{{
|
||||
item.real_name }}</div>
|
||||
<div class="truncate my-[10px] cursor-pointer text-base flex-1 text-center">{{ item.real_name }}</div>
|
||||
</el-tooltip>
|
||||
<!-- 图片操作 -->
|
||||
<el-dropdown :hide-on-click="false" v-if="scene == 'attachment'"
|
||||
class="attachment-action hidden ">
|
||||
<el-dropdown :hide-on-click="false" v-if="scene == 'attachment'" class="attachment-action hidden ">
|
||||
<icon name="element-MoreFilled" class="cursor-pointer ml-[8px]" size="14px" />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item class="text-center" @click="previewImage(index)"
|
||||
v-if="item.att_type == 'image'">
|
||||
<el-dropdown-item class="text-center" @click="previewImage(index)" v-if="item.att_type == 'image'">
|
||||
<div class="text-center w-full">{{ t('lookOver') }}</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item class="text-center" @click="previewVideo(index)"
|
||||
v-if="item.att_type == 'video'">
|
||||
<el-dropdown-item class="text-center" @click="previewVideo(index)" v-if="item.att_type == 'video'">
|
||||
<div class="text-center w-full">{{ t('lookOver') }}</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item class="text-center" @click="moveAttachmentEvent(index)">
|
||||
@ -120,20 +114,16 @@
|
||||
|
||||
<!-- 素材管理 -->
|
||||
<div class="flex flex-wrap" v-else-if="attachment.data.length && operate === false">
|
||||
<div class="attachment-item mr-[10px] w-[120px]" v-for="(item, index) in attachment.data"
|
||||
:key="index">
|
||||
<div
|
||||
class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center h-[120px]">
|
||||
<el-image :src="img(item.url)" fit="contain" v-if="type == 'image'"
|
||||
:preview-src-list="item.image_list"></el-image>
|
||||
<div class="attachment-item mr-[10px] w-[120px]" v-for="(item, index) in attachment.data" :key="index">
|
||||
<div class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center h-[120px]">
|
||||
<el-image :src="img(item.url)" fit="contain" v-if="type == 'image'" :preview-src-list="item.image_list"/>
|
||||
<video :src="img(item.url)" v-else-if="type == 'video'"></video>
|
||||
<icon :name="item.url" size="40px" v-else-if="type == 'icon'"></icon>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<el-tooltip placement="top">
|
||||
<template #content>{{ item.real_name }}</template>
|
||||
<div class="truncate my-[10px] cursor-pointer text-base flex-1 text-center">{{
|
||||
item.real_name }}</div>
|
||||
<div class="truncate my-[10px] cursor-pointer text-base flex-1 text-center">{{ item.real_name }}</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
@ -149,10 +139,8 @@
|
||||
<el-col :span="8" v-if="scene == 'attachment' && operate === true">
|
||||
<div class="flex items-center">
|
||||
<el-checkbox v-model="selectAll" :label="t('selectAll')" size="large" />
|
||||
<el-button class="ml-[15px]" :disabled="batchOperateDisabled"
|
||||
@click="deleteAttachmentEvent()">{{ t('delete') }}</el-button>
|
||||
<el-button :disabled="batchOperateDisabled" @click="moveAttachmentEvent()">{{ t('upload.move')
|
||||
}}</el-button>
|
||||
<el-button class="ml-[15px]" :disabled="batchOperateDisabled" @click="deleteAttachmentEvent()">{{ t('delete') }}</el-button>
|
||||
<el-button :disabled="batchOperateDisabled" @click="moveAttachmentEvent()">{{ t('upload.move') }}</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="scene == 'attachment' ? 16 : 24">
|
||||
@ -172,8 +160,7 @@
|
||||
<el-form label-width="60px">
|
||||
<el-form-item :label="t('upload.moveTo')" style="margin-bottom: 0;">
|
||||
<el-select v-model="moveAttachmentData.cateId" class="input-width">
|
||||
<el-option :label="item.name" :value="item.id" v-for="(item, index) in attachmentCategory.data"
|
||||
:key="index" />
|
||||
<el-option :label="item.name" :value="item.id" v-for="(item, index) in attachmentCategory.data" :key="index" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -181,19 +168,16 @@
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="moveAttachmentData.visible = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" :loading="moveAttachmentData.loading"
|
||||
@click="moveAttachmentData.confirm()">{{ t('confirm') }}</el-button>
|
||||
<el-button type="primary" :loading="moveAttachmentData.loading" @click="moveAttachmentData.confirm()">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 图片预览 -->
|
||||
<el-image-viewer :url-list="previewImageList" v-if="imageViewer.show" @close="imageViewer.show = false"
|
||||
:initial-index="imageViewer.index" :zoom-rate="1" />
|
||||
<el-image-viewer :url-list="previewImageList" v-if="imageViewer.show" @close="imageViewer.show = false" :initial-index="imageViewer.index" :zoom-rate="1" />
|
||||
|
||||
<!-- 视频预览 -->
|
||||
<el-dialog v-model="videoViewer.visible" width="50%" align-center :destroy-on-close="true"
|
||||
custom-class="video-preview">
|
||||
<el-dialog v-model="videoViewer.visible" width="50%" align-center :destroy-on-close="true" custom-class="video-preview">
|
||||
<video-player :src="videoViewer.src" width="100%" />
|
||||
</el-dialog>
|
||||
|
||||
@ -241,6 +225,8 @@ const prop = defineProps({
|
||||
// 选中的文件
|
||||
const selectedFile: Record<string, any> = reactive({})
|
||||
|
||||
const selectedFileIndex:any = reactive([])
|
||||
|
||||
const attachmentCategory: Record<string, any> = reactive({
|
||||
data: []
|
||||
})
|
||||
@ -275,8 +261,8 @@ const attachmentParam = reactive({
|
||||
})
|
||||
|
||||
/**
|
||||
* 查询分组
|
||||
*/
|
||||
* 查询分组
|
||||
*/
|
||||
const getAttachmentCategoryList = debounce(() => {
|
||||
const getFn = prop.type == 'icon' ? getIconCategoryList : attachmentCategoryList
|
||||
getFn({
|
||||
@ -292,8 +278,8 @@ const getAttachmentCategoryList = debounce(() => {
|
||||
getAttachmentCategoryList()
|
||||
|
||||
/**
|
||||
* 查询图片
|
||||
*/
|
||||
* 查询图片
|
||||
*/
|
||||
const getAttachmentList = debounce((page: number = 1) => {
|
||||
const getFn = prop.type == 'icon' ? getIconList : attachmentList
|
||||
|
||||
@ -327,8 +313,8 @@ watch(() => attachmentParam.cate_id, () => {
|
||||
})
|
||||
|
||||
/**
|
||||
* 添加分组
|
||||
*/
|
||||
* 添加分组
|
||||
*/
|
||||
const addAttachmentCategory = (name: string) => {
|
||||
addCategory({
|
||||
type: prop.type,
|
||||
@ -342,10 +328,10 @@ const addAttachmentCategory = (name: string) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑分组
|
||||
* @param name
|
||||
* @param index
|
||||
*/
|
||||
* 编辑分组
|
||||
* @param name
|
||||
* @param index
|
||||
*/
|
||||
const updateAttachmentCategory = (name: string, index: number) => {
|
||||
updateCategory({
|
||||
id: attachmentCategory.data[index].id,
|
||||
@ -358,8 +344,8 @@ const updateAttachmentCategory = (name: string, index: number) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分组
|
||||
*/
|
||||
* 删除分组
|
||||
*/
|
||||
const deleteAttachmentCategory = (index: number) => {
|
||||
ElMessageBox.confirm(t('upload.deleteCategoryTips'), t('warning'),
|
||||
{
|
||||
@ -416,8 +402,8 @@ watch(selectAll, () => {
|
||||
})
|
||||
|
||||
/**
|
||||
* 清空选中
|
||||
*/
|
||||
* 清空选中
|
||||
*/
|
||||
const clearSelected = () => {
|
||||
const keys = Object.keys(toRaw(selectedFile))
|
||||
if (keys.length) {
|
||||
@ -429,29 +415,42 @@ const clearSelected = () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择文件
|
||||
*/
|
||||
* 选择文件
|
||||
*/
|
||||
const selectFile = (data: any) => {
|
||||
if (selectedFile[data.att_id]) delete selectedFile[data.att_id]
|
||||
else if (prop.scene == 'select') {
|
||||
if (selectedFile[data.att_id]) {
|
||||
delete selectedFile[data.att_id]
|
||||
selectedFileIndex.splice(selectedFileIndex.indexOf(data.att_id),1);
|
||||
} else if (prop.scene == 'select') {
|
||||
const keys = Object.keys(toRaw(selectedFile))
|
||||
const length = keys.length
|
||||
if (prop.limit == 1 && length == prop.limit) {
|
||||
delete selectedFile[keys[0]]
|
||||
selectedFileIndex.splice(selectedFileIndex.indexOf(keys[0]),1);
|
||||
} else if (length >= prop.limit) {
|
||||
ElMessage.info(t('upload.triggerUpperLimit'))
|
||||
return
|
||||
}
|
||||
selectedFile[data.att_id] = toRaw(data)
|
||||
selectedFileIndex.push(data.att_id);
|
||||
} else {
|
||||
selectedFile[data.att_id] = toRaw(data)
|
||||
selectedFileIndex.push(data.att_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取当前选中文件的下标
|
||||
const getFileIndex = (att_id:any)=>{
|
||||
let index = selectedFileIndex.indexOf(att_id);
|
||||
if(index == -1) return 0;
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除附件
|
||||
* @param index
|
||||
*/
|
||||
* 删除附件
|
||||
* @param index
|
||||
*/
|
||||
const deleteAttachmentEvent = (index: number | null = null) => {
|
||||
const ids = index === null ? Object.keys(toRaw(selectedFile)) : [attachment.data[index].att_id]
|
||||
|
||||
@ -470,13 +469,14 @@ const deleteAttachmentEvent = (index: number | null = null) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动附件
|
||||
*/
|
||||
* 移动附件
|
||||
*/
|
||||
const moveAttachmentData: Record<string, any> = reactive({
|
||||
cateId: '',
|
||||
loading: false,
|
||||
visible: false
|
||||
})
|
||||
|
||||
const moveAttachmentEvent = (index: number | null = null) => {
|
||||
const ids = index === null ? Object.keys(toRaw(selectedFile)) : [attachment.data[index].att_id]
|
||||
moveAttachmentData.visible = true
|
||||
@ -501,8 +501,8 @@ watch(selectedFile, () => {
|
||||
})
|
||||
|
||||
/**
|
||||
* 查看图片
|
||||
*/
|
||||
* 查看图片
|
||||
*/
|
||||
const imageViewer = reactive({
|
||||
show: false,
|
||||
index: 0
|
||||
@ -519,12 +519,13 @@ const previewImageList = computed(() => {
|
||||
})
|
||||
|
||||
/**
|
||||
* 视频预览
|
||||
*/
|
||||
* 视频预览
|
||||
*/
|
||||
const videoViewer = reactive({
|
||||
visible: false,
|
||||
src: ''
|
||||
})
|
||||
|
||||
const previewVideo = (index: number) => {
|
||||
videoViewer.visible = true
|
||||
videoViewer.src = img(attachment.data[index].url)
|
||||
@ -570,8 +571,27 @@ defineExpose({
|
||||
.attachment-wrap {
|
||||
background: var(--el-border-color-extra-light);
|
||||
}
|
||||
}</style>
|
||||
<style lang="scss">.video-preview {
|
||||
}
|
||||
.file-box-active {
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
border: 15px solid;
|
||||
border-bottom-color: var(--el-color-primary);
|
||||
border-right-color: var(--el-color-primary);
|
||||
border-top-color: transparent;
|
||||
border-left-color: transparent;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
span{
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.video-preview {
|
||||
background: none !important;
|
||||
box-shadow: none !important;
|
||||
|
||||
|
||||
@ -23,7 +23,8 @@ let i18n = createI18n({
|
||||
messages: {
|
||||
"zh-cn": zhCn,
|
||||
en
|
||||
}
|
||||
},
|
||||
silentFallbackWarn: true
|
||||
});
|
||||
|
||||
const language = new Language(i18n);
|
||||
|
||||
@ -1,51 +1,25 @@
|
||||
<template>
|
||||
<el-aside :class="['layout-aside w-full ease-in duration-200', { 'bright': !dark }]">
|
||||
<div v-if="currHeadMenuName == 'setting_manage'" class="pt-[20px] pl-[80px] pr-[70px]">
|
||||
<div class="flex flex-wrap items-center">
|
||||
<template v-for="(item,index) in settingMenu" :key="index">
|
||||
<div
|
||||
v-if="item.meta.show"
|
||||
@click="settingMenuFn(item)"
|
||||
:class="['flex items-center h-[32px] border-[1px] border-solid my-[3px] border-[#E0E0E0] rounded-full px-[10px] mr-[24px] cursor-pointer bg-[#f8f8f8] hover:bg-[#fff]',{'text-[#fff] !bg-[#000] border-[#000]': menuActive == item.name || menuTwoActive && menuTwoActive == item.name}]">
|
||||
<icon v-if="item.meta.icon" :name="item.meta.icon" class="!w-auto mr-[4px] !leading-[14px]" size="14px" :title="item.meta.title"/>
|
||||
<span class="text-[14px]">{{ item.meta.title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<el-tabs v-model="menuActive" class="mt-[20px]" @tab-click="settingHandleClick" v-if="settingTwoMenu.length">
|
||||
<template v-for="(item,index) in settingTwoMenu" :key="index">
|
||||
<el-tab-pane :label="item.meta.title" :name="item.name" :path="item.path" v-if="item.meta.show" @click="settingMenuFn(item)"></el-tab-pane>
|
||||
</template>
|
||||
</el-tabs>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center pt-[20px] pl-[80px] pr-[70px]" v-if="currHeadMenuName == 'site_manage'">
|
||||
<template v-for="(item,index) in siteMenu" :key="index">
|
||||
<div class="flex flex-wrap items-center pt-[20px] pb-[10px] pl-[80px] pr-[70px]"
|
||||
v-if="twoMenuData.length">
|
||||
<template v-for="(item,index) in twoMenuData" :key="index">
|
||||
<div
|
||||
v-if="item.meta.show"
|
||||
@click="siteMenuFn(item)"
|
||||
@click="redirect(item)"
|
||||
:class="['flex items-center h-[32px] border-[1px] border-solid my-[3px] border-[#E0E0E0] rounded-full px-[10px] mr-[24px] cursor-pointer bg-[#f8f8f8] hover:bg-[#fff]',{'text-[#fff] !bg-[#000] border-[#000]': menuActive == item.name || menuTwoActive && menuTwoActive == item.name}]">
|
||||
<icon v-if="item.meta.icon" :name="item.meta.icon" class="!w-auto mr-[4px] !leading-[14px]" size="14px" :title="item.meta.title"/>
|
||||
<span class="text-[14px]">{{ item.meta.title }}</span>
|
||||
<icon v-if="item.meta.icon" :name="item.meta.icon" class="!w-auto mr-[4px] !leading-[14px]" size="14px"
|
||||
:title="item.meta.title" />
|
||||
<span class="text-[14px]">{{ item.meta.short_title || item.meta.title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="pt-[20px] pl-[80px] pr-[70px]" v-if="currHeadMenuName == 'tool'">
|
||||
<div class="flex flex-wrap items-center">
|
||||
<template v-for="(item,index) in appToolsMenu" :key="index">
|
||||
<div
|
||||
v-if="item.meta.show"
|
||||
@click="toolsMenuFn(item)"
|
||||
:class="['flex items-center h-[32px] border-[1px] border-solid my-[3px] border-[#E0E0E0] rounded-full px-[10px] mr-[24px] cursor-pointer bg-[#f8f8f8] hover:bg-[#fff]',{'text-[#fff] !bg-[#000] border-[#000]': menuActive == item.name || menuTwoActive && menuTwoActive == item.name}]">
|
||||
<icon v-if="item.meta.icon" :name="item.meta.icon" class="!w-auto mr-[4px] !leading-[14px]" size="14px" :title="item.meta.title"/>
|
||||
<span class="text-[14px]">{{ item.meta.title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<el-tabs v-model="menuActive" class="mt-[20px]" @tab-click="toolsHandleClick" v-if="appToolsTwoMenu.length">
|
||||
<template v-for="(item,index) in appToolsTwoMenu" :key="index">
|
||||
<el-tab-pane :label="item.meta.title" :name="item.name" :path="item.path" v-if="item.meta.show" @click="settingMenuFn(item)"></el-tab-pane>
|
||||
<!-- 三级菜单 -->
|
||||
<div class="pt-[20px] pl-[80px] pr-[70px]" v-if="threeMenuData.length">
|
||||
<el-tabs v-model="menuTwoActive" @tab-click="toolsHandleClick">
|
||||
<template v-for="(item,index) in threeMenuData" :key="index">
|
||||
<el-tab-pane :label="item.meta.title" :name="item.name" :path="item.path" v-if="item.meta.show"
|
||||
@click="settingMenuFn(item)"></el-tab-pane>
|
||||
</template>
|
||||
</el-tabs>
|
||||
</div>
|
||||
@ -55,206 +29,41 @@
|
||||
<script lang="ts" setup>
|
||||
import { watch, ref, computed } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import side from './side.vue'
|
||||
import useSystemStore from '@/stores/modules/system'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import storage from '@/utils/storage'
|
||||
import { CollectionTag } from '@element-plus/icons-vue'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const route = useRoute()
|
||||
const systemStore = useSystemStore()
|
||||
|
||||
const router = useRouter()
|
||||
const dark = computed(() => {
|
||||
return systemStore.dark
|
||||
})
|
||||
|
||||
const currHeadMenuName = computed(()=>{
|
||||
return systemStore.currHeadMenuName
|
||||
})
|
||||
let menuData = JSON.parse(JSON.stringify(userStore.routers));
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const menuActive = computed(() => {
|
||||
return String(route.name)
|
||||
})
|
||||
const twoMenuData = ref<Record<string, any>[]>([])
|
||||
const threeMenuData = ref<Record<string, any>[]>([])
|
||||
const menuActive = ref('')
|
||||
const menuTwoActive = ref('')
|
||||
// 控制高度
|
||||
const emit = defineEmits(['complete'])
|
||||
|
||||
watch(route, () => {
|
||||
systemStore.$patch(state => {
|
||||
state.menuDrawer = false
|
||||
})
|
||||
resetFn();
|
||||
twoMenuData.value = route.matched[1].children ?? []
|
||||
threeMenuData.value = route.matched[2].children ?? []
|
||||
menuActive.value = route.matched[2] ? route.matched[2].name : ''
|
||||
menuTwoActive.value = route.matched[3] ? route.matched[3].name : ''
|
||||
}, { immediate: true })
|
||||
|
||||
let currMenuName = '';
|
||||
menuData.forEach((item,index) => {
|
||||
if(item.name == route.name){
|
||||
currMenuName = item.name;
|
||||
}else if(item.children && item.children.length){
|
||||
item.children.forEach((twoItem, twoIndex) => {
|
||||
if(twoItem.name == route.name){
|
||||
currMenuName = item.name;
|
||||
}else if(twoItem.children && twoItem.children.length){
|
||||
twoItem.children.forEach((threeItem, threeIndex) => {
|
||||
if(threeItem.name == route.name){
|
||||
currMenuName = item.name;
|
||||
// 刷新后选中三级菜单
|
||||
if(currMenuName == 'setting_manage' && !menuTwoActive.value){
|
||||
menuTwoActive.value = twoItem.name;
|
||||
settingTwoMenu.value = twoItem.children;
|
||||
}
|
||||
if(currMenuName == 'tool' && !menuTwoActive.value){
|
||||
menuTwoActive.value = twoItem.name;
|
||||
appToolsTwoMenu.value = twoItem.children;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 控制页面内容高度
|
||||
emit('complete')
|
||||
|
||||
// 设置菜单
|
||||
let menuIndexArr = {setting_manage: 'setting_manage', site_manage: 'site_manage', tool:'tool', app_auth:'tool'};
|
||||
if(Object.keys(menuIndexArr).indexOf(currMenuName) != -1){
|
||||
systemStore.setHeadMenu(menuIndexArr[currMenuName]);
|
||||
return false;
|
||||
}
|
||||
systemStore.setHeadMenu('');
|
||||
})
|
||||
|
||||
|
||||
let settingMenu = ref([]);
|
||||
let settingTwoMenu = ref([]);
|
||||
let siteMenu = ref([]);
|
||||
let appToolsMenu = ref([]);
|
||||
let appToolsTwoMenu = ref([]);
|
||||
|
||||
userStore.routers.forEach((item, index) => {
|
||||
item.meta.class = 1
|
||||
if (item.children) {
|
||||
item.children.forEach((subItem, subIndex) => {
|
||||
subItem.meta.class = 2
|
||||
if (subItem.children) {
|
||||
subItem.children.forEach((threeItem, threeIndex) => {
|
||||
threeItem.meta.class = 3
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
// 控制台
|
||||
if(item.name == 'setting_manage'){
|
||||
settingMenu.value = item.children;
|
||||
}
|
||||
|
||||
// 站点
|
||||
if(item.name == 'site_manage'){
|
||||
siteMenu.value = item.children;
|
||||
}
|
||||
|
||||
// 开发
|
||||
if(item.name == 'tool'){
|
||||
appToolsMenu.value = item.children;
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
// 控制台跳转 start
|
||||
const settingMenuFn = (data)=>{
|
||||
let obj = '/setting/';
|
||||
menuTwoActive.value = '';
|
||||
settingTwoMenu.value = [];
|
||||
|
||||
if(data.children){
|
||||
menuTwoActive.value = data.name;
|
||||
settingTwoMenu.value = data.children;
|
||||
obj = obj + data.path + '/' + data.children[0].path;
|
||||
router.push(obj)
|
||||
}else{
|
||||
obj = obj + data.path;
|
||||
router.push(obj)
|
||||
}
|
||||
}
|
||||
|
||||
const settingHandleClick = (tab, event: Event) => {
|
||||
let obj = '/setting/';
|
||||
|
||||
settingMenu.value.forEach((item,index)=>{
|
||||
if(item.children && item.children.length){
|
||||
item.children.forEach((subItem,subIndex) => {
|
||||
if(subItem.name == tab.props.name){
|
||||
obj = obj + item.path + '/' + subItem.path;
|
||||
router.push(obj)
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
// 控制台跳转 end
|
||||
|
||||
// 站点跳转 start
|
||||
const siteMenuFn = (data)=>{
|
||||
let obj = '/admin/site/';
|
||||
menuTwoActive.value = '';
|
||||
|
||||
if(data.children){
|
||||
menuTwoActive.value = data.name;
|
||||
obj = obj + data.path + '/' + data.children[0].path;
|
||||
router.push(obj)
|
||||
}else{
|
||||
obj = obj + data.path;
|
||||
router.push(obj)
|
||||
}
|
||||
}
|
||||
// 站点跳转 end
|
||||
|
||||
// 开发跳转 start
|
||||
const toolsMenuFn = (data)=>{
|
||||
let obj = '/admin/tools/';
|
||||
menuTwoActive.value = '';
|
||||
appToolsTwoMenu.value = [];
|
||||
|
||||
if(data.children){
|
||||
menuTwoActive.value = data.name;
|
||||
appToolsTwoMenu.value = data.children;
|
||||
obj = obj + data.path + '/' + data.children[0].path;
|
||||
router.push(obj)
|
||||
}else{
|
||||
obj = obj + data.path;
|
||||
router.push(obj)
|
||||
/**
|
||||
* 跳转
|
||||
* @param data
|
||||
*/
|
||||
const redirect = (data: any) => {
|
||||
if (data.children) {
|
||||
router.push(data.children[0].path)
|
||||
} else {
|
||||
router.push(data.path)
|
||||
}
|
||||
}
|
||||
|
||||
const toolsHandleClick = (tab, event: Event) => {
|
||||
let obj = '/tools/';
|
||||
|
||||
appToolsMenu.value.forEach((item,index)=>{
|
||||
if(item.children && item.children.length){
|
||||
item.children.forEach((subItem,subIndex) => {
|
||||
if(subItem.name == tab.props.name){
|
||||
obj = obj + item.path + '/' + subItem.path;
|
||||
router.push(obj)
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
// 开发跳转 end
|
||||
|
||||
// 重置变量
|
||||
const resetFn = ()=>{
|
||||
menuTwoActive.value= '';
|
||||
settingTwoMenu.value = [];
|
||||
}
|
||||
|
||||
// 跳转链接
|
||||
const toLink = (path) => {
|
||||
router.push({path})
|
||||
router.push({name: tab.props.name})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -3,16 +3,14 @@
|
||||
<!-- :class="['h-full px-[10px]',{'layout-header border-b border-color': !dark}]" -->
|
||||
<div class="flex items-center text-[14px] leading-[1]">
|
||||
<span class="iconfont icontuodong !text-[25px] mr-[6px]"></span>
|
||||
<span class="cursor-pointer" @click="toLink('/admin/index')">首页</span>
|
||||
<span class="mx-2 text-[#4F5563] mx-[15px]">|</span>
|
||||
<span class="cursor-pointer" @click="toLink('/admin/setting/website/system','setting_manage')">配置</span>
|
||||
<span class="mx-2 text-[#4F5563] mx-[15px]">|</span>
|
||||
<span class="cursor-pointer" @click="toLink('/admin/site/list','site_manage')">站点</span>
|
||||
<template v-if="app_debug">
|
||||
<span class="mx-2 text-[#4F5563] mx-[15px]">|</span>
|
||||
<span class="cursor-pointer" @click="toLink('/admin/app_manage/app_store','')">应用</span>
|
||||
<span class="mx-2 text-[#4F5563] mx-[15px]">|</span>
|
||||
<span class="cursor-pointer" @click="toLink('/admin/app_manage/tools','tool')">开发</span>
|
||||
|
||||
<template v-for="(item, index) in oneMenuData">
|
||||
<template v-if="item.meta.show">
|
||||
<span class="mx-2 text-[#4F5563] mx-[15px]" v-if="index">|</span>
|
||||
<span class="cursor-pointer" @click="router.push({ name: item.name })" >
|
||||
{{ item.meta.short_title || item.meta.title }}
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
<div class="right-panel h-full flex items-center justify-end">
|
||||
@ -20,25 +18,6 @@
|
||||
<div class="navbar-item flex items-center h-full cursor-pointer" @click="refreshRouter">
|
||||
<icon name="element-Refresh" />
|
||||
</div>
|
||||
<!-- 预览 只有站点时展示-->
|
||||
<i class="iconfont iconlingdang-xianxing cursor-pointer px-[8px]" :title="t('newInfo')" v-if="appType == 'site'"></i>
|
||||
<!-- 切换首页 -->
|
||||
<div class="navbar-item flex items-center h-full cursor-pointer" v-if="appType == 'site'" @click="checkIndexList">
|
||||
<icon name="iconfont-iconqiehuan" :title="t('indexSwitch')"/>
|
||||
</div>
|
||||
<!-- 切换语言 -->
|
||||
<!-- <div class="navbar-item flex items-center h-full cursor-pointer">
|
||||
<switch-lang />
|
||||
</div> -->
|
||||
<!-- 切换全屏 -->
|
||||
<!-- <div class="navbar-item flex items-center h-full cursor-pointer" @click="toggleFullscreen">
|
||||
<icon name="iconfont-icontuichuquanping" v-if="isFullscreen" />
|
||||
<icon name="iconfont-iconquanping" v-else />
|
||||
</div> -->
|
||||
<!-- 布局设置 -->
|
||||
<!-- <div class="navbar-item flex items-center h-full cursor-pointer">
|
||||
<layout-setting />
|
||||
</div> -->
|
||||
<!-- 用户信息 -->
|
||||
<div class="navbar-item flex items-center h-full cursor-pointer">
|
||||
<user-info />
|
||||
@ -79,51 +58,38 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, onMounted, watch } from 'vue'
|
||||
import layoutSetting from './layout-setting.vue'
|
||||
import switchLang from './switch-lang.vue'
|
||||
import userInfo from './user-info.vue'
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
import useSystemStore from '@/stores/modules/system'
|
||||
import { ref } from 'vue'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { t } from '@/lang'
|
||||
import storage from '@/utils/storage'
|
||||
import { getIndexList, setIndexList, getEnv } from '@/app/api/sys'
|
||||
import userInfo from './user-info.vue'
|
||||
import { findFirstValidRoute } from "@/router/routers"
|
||||
|
||||
const router = useRouter()
|
||||
const appType = storage.get('app_type')
|
||||
const { toggle: toggleFullscreen, isFullscreen } = useFullscreen()
|
||||
const systemStore = useSystemStore()
|
||||
const appStore = useAppStore()
|
||||
const route = useRoute()
|
||||
const screenWidth = ref(window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth)
|
||||
const userStore = useUserStore()
|
||||
const routers = userStore.routers
|
||||
|
||||
const dark = computed(()=>{
|
||||
return systemStore.dark
|
||||
const oneMenuData = ref<Record<string, any>[]>([])
|
||||
routers.forEach(item => {
|
||||
item.original_name = item.name
|
||||
if (item.children && item.children.length) {
|
||||
item.name = findFirstValidRoute(item.children)
|
||||
}
|
||||
oneMenuData.value.push(item)
|
||||
})
|
||||
|
||||
// 是否是debug模式 start
|
||||
let app_debug = ref(true)
|
||||
const getEnvFn = () => {
|
||||
getEnv().then(res => {
|
||||
// app_debug.value = res.data.app_debug;
|
||||
}).catch(() => {})
|
||||
}
|
||||
getEnvFn();
|
||||
// 是否是debug模式 end
|
||||
|
||||
// 检测登录 start
|
||||
const detectionLoginDialog = ref(false)
|
||||
const comparisonToken = ref('')
|
||||
const comparisonSiteId = ref('')
|
||||
if (storage.get('comparisonTokenStorage')) {
|
||||
comparisonToken.value = storage.get('comparisonTokenStorage')
|
||||
// storage.remove(['comparisonTokenStorage']);
|
||||
}
|
||||
if (storage.get('comparisonSiteIdStorage')) {
|
||||
comparisonSiteId.value = storage.get('comparisonSiteIdStorage')
|
||||
// storage.remove(['comparisonSiteIdStorage']);
|
||||
}
|
||||
// 监听标签页面切换
|
||||
document.addEventListener('visibilitychange', e => {
|
||||
@ -134,65 +100,17 @@ document.addEventListener('visibilitychange', e => {
|
||||
|
||||
const detectionLoginFn = () => {
|
||||
detectionLoginDialog.value = false
|
||||
location.reload();
|
||||
location.reload()
|
||||
}
|
||||
// 检测登录 end
|
||||
|
||||
onMounted(() => {
|
||||
// 监听窗体宽度变化
|
||||
window.onresize = () => {
|
||||
return (() => {
|
||||
screenWidth.value = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
|
||||
})()
|
||||
}
|
||||
})
|
||||
|
||||
// 刷新路由
|
||||
const refreshRouter = () => {
|
||||
if (!appStore.routeRefreshTag) return
|
||||
appStore.refreshRouterView()
|
||||
}
|
||||
|
||||
// 面包屑导航
|
||||
const breadcrumb = computed(() => {
|
||||
const matched = route.matched.filter(item => { return item.meta.title })
|
||||
if (matched[0] && matched[0].path == '/') matched.splice(0, 1)
|
||||
return matched
|
||||
})
|
||||
|
||||
// 返回上一页
|
||||
const backFn = () => {
|
||||
router.go(-1)
|
||||
}
|
||||
|
||||
const indexList = ref();
|
||||
const showDialog = ref(false)
|
||||
const checkIndexList = () => {
|
||||
getIndexList().then(res => {
|
||||
showDialog.value = true
|
||||
indexList.value = res.data
|
||||
for(let i = 0 ; i < indexList.value.length; i ++){
|
||||
if(indexList.value[i].is_use == 1){
|
||||
index_path.value = indexList.value[i].view_path
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const index_path = ref('');
|
||||
const submitIndex = () => {
|
||||
setIndexList({
|
||||
view_path: index_path.value
|
||||
}).then(() => {
|
||||
showDialog.value = false
|
||||
router.go(0)
|
||||
})
|
||||
}
|
||||
storage.set({ key: 'currHeadMenuName', data: ""})
|
||||
const toLink = (link,type)=>{
|
||||
// systemStore.setHeadMenu(type);
|
||||
router.push(link);
|
||||
}
|
||||
storage.set({ key: 'currHeadMenuName', data: "" })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -14,11 +14,12 @@
|
||||
<el-scrollbar class="h-[calc( 100vh - 64px )]">
|
||||
<el-menu :default-active="oneMenuActive" :router="true" class="aside-menu" unique-opened="true" :collapse="systemStore.menuIsCollapse">
|
||||
<template v-for="(item, index) in oneMenuData" :key="index">
|
||||
<el-menu-item :index="item.path" @click="router.push({ name: item.name })" v-if="item.meta.show">
|
||||
<el-menu-item :index="item.original_name" @click="router.push({ name: item.name })" v-if="item.meta.show">
|
||||
<div v-if="item.meta.icon" class="w-[16px] h-[16px] relative flex justify-center">
|
||||
<el-image class="w-[16px] h-[16px] rounded-[50%] overflow-hidden" :src="item.meta.icon" fit="fill" v-if="isUrl(item.meta.icon)"/>
|
||||
<icon :name="item.meta.icon" class="absolute top-[50%] -translate-y-[50%]" v-else />
|
||||
</div>
|
||||
<div v-else class="w-[16px] h-[16px]"></div>
|
||||
<template #title>
|
||||
<div class="relative flex-1 w-0">
|
||||
<span class="ml-[10px] w-full truncate">{{ item.meta.short_title || item.meta.title }}</span>
|
||||
@ -63,6 +64,7 @@ const twoMenuData = ref<Record<string, any>[]>([])
|
||||
const addonRouters: Record<string, any> = {}
|
||||
|
||||
routers.forEach(item => {
|
||||
item.original_name = item.name
|
||||
if (item.meta.addon == '') {
|
||||
if (item.children && item.children.length) {
|
||||
item.name = findFirstValidRoute(item.children)
|
||||
@ -71,7 +73,7 @@ routers.forEach(item => {
|
||||
} else if (item.meta.addon != '' && siteInfo?.apps.length <= 1 && siteInfo?.apps[0].key == item.meta.addon) {
|
||||
if (item.children) {
|
||||
item.children.forEach((citem: Record<string, any>) => {
|
||||
citem.path = `${item.path}/${citem.path}`
|
||||
citem.original_name = citem.name
|
||||
if (citem.children && citem.children.length) {
|
||||
citem.name = findFirstValidRoute(citem.children)
|
||||
}
|
||||
@ -98,29 +100,30 @@ if (siteInfo?.apps.length > 1) {
|
||||
app: item.app,
|
||||
show: true
|
||||
},
|
||||
original_name: item.key,
|
||||
name: addonIndexRoute[item.key]
|
||||
})
|
||||
})
|
||||
oneMenuData.value.unshift(...routers)
|
||||
}
|
||||
|
||||
const oneMenuActive = ref(route.matched[1].path)
|
||||
const oneMenuActive = ref(route.matched[1].name)
|
||||
|
||||
watch(route, () => {
|
||||
// 多应用
|
||||
if (siteInfo?.apps.length > 1) {
|
||||
twoMenuData.value = route.matched[1].children
|
||||
oneMenuActive.value = route.matched[1].path
|
||||
oneMenuActive.value = route.matched[1].name
|
||||
} else {
|
||||
// 单应用
|
||||
if (route.meta.addon == '') {
|
||||
oneMenuActive.value = route.matched[1].path
|
||||
oneMenuActive.value = route.matched[1].name
|
||||
twoMenuData.value = route.matched[1].children ?? []
|
||||
} else if (route.meta.addon && route.meta.addon != siteInfo?.apps[0].key) {
|
||||
oneMenuActive.value = '/site/app'
|
||||
twoMenuData.value = route.matched[1].children ?? []
|
||||
} else {
|
||||
oneMenuActive.value = route.matched[2].path
|
||||
oneMenuActive.value = route.matched[2].name
|
||||
twoMenuData.value = route.matched[2].children ?? []
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ document.addEventListener('visibilitychange', e => {
|
||||
|
||||
const detectionLoginFn = () => {
|
||||
detectionLoginDialog.value = false
|
||||
location.reload()
|
||||
location.href = `${location.origin}/site/`
|
||||
}
|
||||
// 检测登录 end
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ router.push = (to: RouteLocationRaw) => {
|
||||
const route = typeof to == 'string' ? urlToRouteRaw(to) : to
|
||||
if (route.path) {
|
||||
const paths = route.path.split('/').filter((item: string) => { return item })
|
||||
route.path = ['admin', 'site', 'decorate', 'home'].indexOf(paths[0]) == -1 ? `/${getAppType()}${route.path}` : route.path
|
||||
route.path = ['admin', 'site', 'home'].indexOf(paths[0]) == -1 ? `/${getAppType()}${route.path}` : route.path
|
||||
}
|
||||
return originPush(route)
|
||||
}
|
||||
@ -34,7 +34,7 @@ router.resolve = (to: RouteLocationRaw, currentLocation?: RouteLocationNormalize
|
||||
const route = typeof to == 'string' ? urlToRouteRaw(to) : to
|
||||
if (route.path) {
|
||||
const paths = route.path.split('/').filter((item: string) => { return item })
|
||||
route.path = ['admin', 'site', 'decorate', 'home'].indexOf(paths[0]) == -1 ? `/${getAppType()}${route.path}` : route.path
|
||||
route.path = ['admin', 'site', 'home'].indexOf(paths[0]) == -1 ? `/${getAppType()}${route.path}` : route.path
|
||||
}
|
||||
return originResolve(route, currentLocation)
|
||||
}
|
||||
@ -74,7 +74,7 @@ router.beforeEach(async (to, from, next) => {
|
||||
matched = appType
|
||||
}
|
||||
|
||||
const loginPath = to.path == '/' ? '/admin/login' : `${matched}/login`
|
||||
const loginPath = to.path == '/' ? '/admin/login' : `/${matched == '/admin' ? 'admin' : 'site'}/login`
|
||||
|
||||
// 判断是否需登录
|
||||
if (NO_LOGIN_ROUTES.includes(to.path)) {
|
||||
@ -100,9 +100,10 @@ router.beforeEach(async (to, from, next) => {
|
||||
|
||||
// 设置首页路由
|
||||
let firstRoute: symbol | string | undefined = findFirstValidRoute(userStore.routers)
|
||||
if (getAppType() != 'admin' && userStore.siteInfo?.apps.length > 1) {
|
||||
if (getAppType() != 'admin') {
|
||||
firstRoute = userStore.addonIndexRoute[ userStore.siteInfo?.apps[0].key ]
|
||||
}
|
||||
|
||||
ROOT_ROUTER.redirect = { name: firstRoute }
|
||||
router.addRoute(ROOT_ROUTER)
|
||||
|
||||
@ -133,13 +134,11 @@ router.beforeEach(async (to, from, next) => {
|
||||
router.addRoute(SITE_ROUTE.name, route)
|
||||
}
|
||||
})
|
||||
|
||||
next({ path: to.path, query: to.query, replace: true })
|
||||
next(to)
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
// userStore.logout()
|
||||
next({ path: loginPath, query: { redirect: to.fullPath } })
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ interface Route {
|
||||
*/
|
||||
const createRoute = function (route: Route, parentRoute: RouteRecordRaw | null = null): RouteRecordRaw {
|
||||
const record: RouteRecordRaw = {
|
||||
path: parentRoute ? route.router_path : route.router_path != 'decorate' ? `/${route.app_type}/${route.router_path}` : `/${route.router_path}`,
|
||||
path: `/${route.app_type}/${route.router_path}`,
|
||||
name: route.menu_key,
|
||||
meta: {
|
||||
title: route.menu_name,
|
||||
@ -214,7 +214,7 @@ export function formatRouters(routes: Route[], parentRoute: RouteRecordRaw | nul
|
||||
*/
|
||||
export function findFirstValidRoute(routes: RouteRecordRaw[]): string | undefined {
|
||||
for (const route of routes) {
|
||||
if (route.meta?.type == 1) {
|
||||
if (route.meta?.type == 1 && route.meta?.show) {
|
||||
return route.name as string
|
||||
}
|
||||
if (route.children) {
|
||||
|
||||
@ -1 +1,2 @@
|
||||
@import "addon/tourism/iconfont.css";
|
||||
@import "addon/o2o/iconfont.css";
|
||||
|
||||
38
admin/src/styles/icon/addon/o2o/iconfont.css
Normal file
38
admin/src/styles/icon/addon/o2o/iconfont.css
Normal file
@ -0,0 +1,38 @@
|
||||
@font-face {
|
||||
font-family: "o2o"; /* Project id 4412516 */
|
||||
src: url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.woff2?t=1705720131974') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.woff?t=1705720131974') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.ttf?t=1705720131974') format('truetype');
|
||||
}
|
||||
|
||||
.o2o {
|
||||
font-family: "o2o" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.o2o-icon-danhanghuadong:before {
|
||||
content: "\e66f";
|
||||
}
|
||||
|
||||
.o2o-icon-yuanjiao:before {
|
||||
content: "\e6c0";
|
||||
}
|
||||
|
||||
.o2o-icon-gl-square:before {
|
||||
content: "\ea92";
|
||||
}
|
||||
|
||||
.o2o-icon-sousuo12:before {
|
||||
content: "\e699";
|
||||
}
|
||||
|
||||
.o2o-icon-sousuo11:before {
|
||||
content: "\e6d4";
|
||||
}
|
||||
|
||||
.o2o-icon-jishi:before {
|
||||
content: "\e600";
|
||||
}
|
||||
51
admin/src/styles/icon/addon/o2o/iconfont.json
Normal file
51
admin/src/styles/icon/addon/o2o/iconfont.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"id": "4412516",
|
||||
"name": "上门服务",
|
||||
"font_family": "o2o",
|
||||
"css_prefix_text": "o2o-icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "30621139",
|
||||
"name": "单行滑动",
|
||||
"font_class": "danhanghuadong",
|
||||
"unicode": "e66f",
|
||||
"unicode_decimal": 58991
|
||||
},
|
||||
{
|
||||
"icon_id": "7149037",
|
||||
"name": "圆角",
|
||||
"font_class": "yuanjiao",
|
||||
"unicode": "e6c0",
|
||||
"unicode_decimal": 59072
|
||||
},
|
||||
{
|
||||
"icon_id": "7594344",
|
||||
"name": "20gl-square",
|
||||
"font_class": "gl-square",
|
||||
"unicode": "ea92",
|
||||
"unicode_decimal": 60050
|
||||
},
|
||||
{
|
||||
"icon_id": "10133070",
|
||||
"name": "搜索",
|
||||
"font_class": "sousuo12",
|
||||
"unicode": "e699",
|
||||
"unicode_decimal": 59033
|
||||
},
|
||||
{
|
||||
"icon_id": "14652583",
|
||||
"name": "搜索",
|
||||
"font_class": "sousuo11",
|
||||
"unicode": "e6d4",
|
||||
"unicode_decimal": 59092
|
||||
},
|
||||
{
|
||||
"icon_id": "6818781",
|
||||
"name": "技师",
|
||||
"font_class": "jishi",
|
||||
"unicode": "e600",
|
||||
"unicode_decimal": 58880
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -224,3 +224,63 @@ export function guid(len = 10, firstU = true, radix = null) {
|
||||
}
|
||||
return uuid.join('')
|
||||
}
|
||||
|
||||
/**
|
||||
* 金额格式化
|
||||
*/
|
||||
export function moneyFormat(money : string) : string {
|
||||
return isNaN(parseFloat(money)) ? money : parseFloat(money).toFixed(2)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 时间戳转日期格式
|
||||
* @param {Object} timeStamp
|
||||
*/
|
||||
export function timeStampTurnTime(timeStamp, type = "") {
|
||||
if (timeStamp != undefined && timeStamp != "" && timeStamp > 0) {
|
||||
var date = new Date();
|
||||
date.setTime(timeStamp * 1000);
|
||||
var y = date.getFullYear();
|
||||
var m = date.getMonth() + 1;
|
||||
m = m < 10 ? ('0' + m) : m;
|
||||
var d = date.getDate();
|
||||
d = d < 10 ? ('0' + d) : d;
|
||||
var h = date.getHours();
|
||||
h = h < 10 ? ('0' + h) : h;
|
||||
var minute = date.getMinutes();
|
||||
var second = date.getSeconds();
|
||||
minute = minute < 10 ? ('0' + minute) : minute;
|
||||
second = second < 10 ? ('0' + second) : second;
|
||||
if (type) {
|
||||
if (type == 'yearMonthDay') {
|
||||
return y + '年' + m + '月' + d + '日';
|
||||
}
|
||||
return y + '-' + m + '-' + d;
|
||||
} else {
|
||||
return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
|
||||
}
|
||||
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤小数点
|
||||
* @param event
|
||||
*/
|
||||
export function filterDigit(event:any){
|
||||
event.target.value = event.target.value.replace(/[^\d\.]/g,'');
|
||||
event.target.value = event.target.value.replace(/^\./g,'');
|
||||
event.target.value = event.target.value.replace(/\.{2,}/g,'.');
|
||||
event.target.value = event.target.value.replace('.','$#$').replace(/\./g,'').replace('$#$','.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤整数
|
||||
* @param event
|
||||
*/
|
||||
export function filterNumber(event:any){
|
||||
event.target.value = event.target.value.replace(/[^\d]/g,'');
|
||||
}
|
||||
@ -37,7 +37,7 @@ class Storage {
|
||||
const json: any = window.localStorage.getItem(`${this.prefix}.${key}`)
|
||||
return JSON.parse(json)
|
||||
} catch (error) {
|
||||
return null
|
||||
return window.localStorage.getItem(`${this.prefix}.${key}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,8 +2,6 @@
|
||||
|
||||
return [
|
||||
'HELLO_WORLD_LINK' => [
|
||||
'key' => 'hello_world',
|
||||
'addon_title' => get_lang('dict_diy.hello_world_title'),
|
||||
'title' => get_lang('dict_diy.hello_world_link'),
|
||||
'child_list' => [
|
||||
[
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
return [
|
||||
'DIY_HELLO_WORLD_INDEX' => [
|
||||
'title' => get_lang('dict_diy.page_hello_world_index'),
|
||||
'page' => '/hello_world/pages/index',
|
||||
'page' => '/addon/hello_world/pages/index',
|
||||
'action' => ''
|
||||
],
|
||||
'DIY_HELLO_WORLD_INFO' => [
|
||||
'title' => get_lang('dict_diy.page_hello_world_info'),
|
||||
'page' => '/hello_world/pages/info',
|
||||
'page' => '/addon/hello_world/pages/info',
|
||||
'action' => ''
|
||||
],
|
||||
];
|
||||
@ -1,17 +1,3 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
[
|
||||
'menu_name' => '插件菜单',
|
||||
'menu_key' => 'niucloud_hello',
|
||||
'menu_type' => 1,
|
||||
'icon' => 'iconfont-iconyingyongshichang',
|
||||
'api_url' => '',
|
||||
'router_path' => 'hello_world',
|
||||
'view_path' => 'hello_world/index',
|
||||
'methods' => '',
|
||||
'sort' => 90,
|
||||
'status' => 1,
|
||||
'is_show' => 1,
|
||||
],
|
||||
];
|
||||
return [
|
||||
];
|
||||
@ -1,36 +1,16 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
[
|
||||
'menu_name' => '插件站点菜单',
|
||||
'menu_key' => 'niucloud_site_hello',
|
||||
'menu_type' => 1,
|
||||
'icon' => 'iconfont-iconyingyongshichang',
|
||||
'api_url' => '',
|
||||
'router_path' => 'hello_world',
|
||||
'view_path' => 'hello_world/site',
|
||||
'methods' => '',
|
||||
'sort' => 100,
|
||||
'status' => 1,
|
||||
'is_show' => 1,
|
||||
],
|
||||
/* [
|
||||
'menu_name' => '会员列表',
|
||||
'menu_key' => 'member_list',
|
||||
'parent_key' => 'member',
|
||||
'menu_type' => 1,
|
||||
'icon' => 'iconfont-iconhuiyuanliebiao',
|
||||
'api_url' => 'member/member',
|
||||
'router_path' => 'hello_world_member_list',
|
||||
'view_path' => 'hello_world/member',
|
||||
'methods' => 'get',
|
||||
'sort' => 100,
|
||||
'status' => 1,
|
||||
'is_show' => 1,
|
||||
'children' => [
|
||||
|
||||
]
|
||||
],
|
||||
"delete" => "member" //针对修改系统菜单处理方式,可以删除系统菜单,设置对应key值,也可删除不需要的菜单处理
|
||||
*/
|
||||
];
|
||||
return [
|
||||
[
|
||||
'menu_name' => '插件站点菜单',
|
||||
'menu_key' => 'niucloud_site_hello',
|
||||
'menu_type' => 1,
|
||||
'icon' => 'iconfont-iconyingyongshichang',
|
||||
'api_url' => '',
|
||||
'router_path' => 'hello_world',
|
||||
'view_path' => 'hello_world/site',
|
||||
'methods' => '',
|
||||
'sort' => 100,
|
||||
'status' => 1,
|
||||
'is_show' => 1,
|
||||
]
|
||||
];
|
||||
|
||||
@ -3,7 +3,7 @@ return [
|
||||
'pages' => <<<EOT
|
||||
// PAGE_BEGIN
|
||||
{
|
||||
"path": "addon/{{addon_name}}/pages/index",
|
||||
"path": "hello_world/pages/index",
|
||||
"style": {
|
||||
// #ifdef H5
|
||||
"navigationStyle": "custom",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 128 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 673 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user