This commit is contained in:
全栈小学生 2025-03-14 18:30:18 +08:00
parent e94d59134b
commit e9e353effd
89 changed files with 6128 additions and 5525 deletions

View File

@ -219,6 +219,29 @@ export function getDiyTheme(params: Record<string, any>) {
return request.get(`diy/theme`, {params})
}
/**
*
* @param params
*/
export function addTheme(params: Record<string, any>) {
return request.post(`diy/theme/add`, params)
}
/**
*
* @param params
*/
export function editTheme(params: Record<string, any>) {
return request.put(`diy/theme/edit/${params.id}`, params, {showSuccessMessage: true})
}
/**
*
* @param params
*/
export function deleteTheme(id: number) {
return request.delete(`diy/theme/delete/${id}`, {showSuccessMessage: true})
}
/**
*

View File

@ -19,6 +19,14 @@ export function getDiyFormPageList(params: Record<string, any>) {
export function getDiyFormList(params: Record<string, any>) {
return request.get(`diy/form/list`, { params })
}
/**
*
* @param params
* @returns
*/
export function getDiyFormSelectPageList(params: Record<string, any>) {
return request.get(`diy/form/select`, { params })
}
/**
*
@ -225,4 +233,4 @@ export function getFormRecordsMember(params: Record<string, any>) {
*/
export function copyForm(params: Record<string, any>) {
return request.post(`diy/form/copy`, params, { showSuccessMessage: true })
}
}

View File

@ -359,6 +359,14 @@ export function getCashOutDetail(id: number) {
export function memberAudit(params: Record<string, any>) {
return request.put(`member/cash_out/audit/${params.id}/${params.action}`, params, { showSuccessMessage: true })
}
/**
*
* @param params
*/
export function memberCancel(params: Record<string, any>) {
return request.put(`member/cash_out/cancel/${params.id}`, params, { showSuccessMessage: true,showErrorMessage: true })
}
/**
*

View File

@ -99,3 +99,25 @@ export function pay(params: Record<string, any>) {
export function getFriendsPay(tradeType : string, tradeId : number, channel: string) {
return request.get(`pay/friendspay/info/${tradeType}/${tradeId}/${channel}`, { showErrorMessage: false })
}
/**
*
*/
export function getTransferScene() {
return request.get(`pay/transfer_scene`)
}
/**
* id
*/
export function setSceneId(params: Record<string, any>) {
return request.post(`pay/transfer_scene/set_scene_id/${params.scene}`, params, { showSuccessMessage: true })
}
/**
*
*/
export function setTradeScene(params: Record<string, any>) {
return request.post(`pay/transfer_scene/set_trade_scene/${params.type}`, params)
}

View File

@ -585,6 +585,13 @@ export function clearSchemaCache(params: Record<string, any>) {
return request.post(`sys/schema/clear`, {}, { showSuccessMessage: true })
}
/**
*
*/
export function clearCache(params: Record<string, any>) {
return request.post(`sys/cache/clear`, {}, { showSuccessMessage: true })
}
/***************************************************** 获取应用 ****************************************************/
/**
*

View File

@ -194,6 +194,7 @@ const open = async () => {
} else {
loading.value = false
cloudBuildCheck.value = data
showDialog.value = true
}
}).catch(() => {
showDialog.value = false

View File

@ -20,11 +20,6 @@
"adminDisabled":"超级管理员不可编辑",
"userUnlockTips":"确定要解锁该管理员吗?",
"userLockTips":"确定要锁定该管理员吗?",
"userType": "用户类型",
"adminAdministrators": "平台管理员",
"siteAdministrators": "站点管理员",
"userTypePlaceholder": "请选择用户类型",
"siteAdministratorsDisabled": "站点管理员不可编辑",
"manager": "用户",
"managerPlaceholder": "请选择用户",
"managerTips": "选择或者新增用户作为管理员",

View File

@ -257,8 +257,9 @@
"horzLineStyleDashed": "虚线",
"horzLineBorderColor": "线条颜色",
"horzLineBorderWidth": "线条宽度",
"floatBtnBtton": "按钮位置",
"floatBtnButton": "按钮位置",
"floatBtnOffset": "上下偏移",
"lateralBtnOffset": "左右偏移",
"floatBtnImageSet": "图片设置",
"floatBtnImageSize": "图片大小",
"floatBtnAroundRadius": "图片圆角",

View File

@ -258,8 +258,9 @@
"horzLineStyleDashed": "虚线",
"horzLineBorderColor": "线条颜色",
"horzLineBorderWidth": "线条宽度",
"floatBtnBtton": "按钮位置",
"floatBtnButton": "按钮位置",
"floatBtnOffset": "上下偏移",
"lateralBtnOffset": "左右偏移",
"floatBtnImageSet": "图片设置",
"floatBtnImageSize": "图片大小",
"floatBtnAroundRadius": "图片圆角",
@ -361,7 +362,7 @@
"imageLimitErrorTips":"限制数量格式输入错误",
"imageLimitErrorTipsTwo":"限制数量不能小于0",
"imageLimitErrorTipsThree":"限制数量必须大于0",
"imafeLimitErrorTipsFour":"限制数量最大不能超过20",
"imafeLimitErrorTipsFour":"限制数量最大不能超过9",
"defaultValueTips":"设置后,默认值会自动填充到输入框,填表人可在此基础上进行修改。",
"defaultErrorTips":"默认值格式输入错误",

View File

@ -47,7 +47,7 @@
"batchEmptySelectedFormsTips": "请选择要删除的表单",
"batchFormsDeleteTips": "确定要删除选中的表单吗?",
"promotion":"推广",
"submirSuccess":"提交成功页",
"submitSuccess":"提交成功页",
"writeSet":"填写设置",
"export":"导出",
"detail":"详情",

View File

@ -41,7 +41,7 @@
"cashOutMoney": "转账金额",
"auditTime": "审核时间",
"transferTime": "转账时间",
"memberInfoPlaceholder": "请输入会员名称/会员昵称/手机号",
"memberInfoPlaceholder": "请输入会员编号/昵称/手机号搜索",
"cashOutNumber": "提现单号",
"cashOutNumberPlaceholder": "请输入提现单号",
"alipayAccount": "支付宝账号",
@ -60,5 +60,7 @@
"transferRemark":"转账补充说明",
"transferRemarkPlaceholder":"请输入转账补充说明",
"notes":"备注",
"check":"检查打款进度"
"check":"检查打款进度",
"cancelWithdrawal":"取消",
"cancelTips":"确定要取消提现吗?"
}

View File

@ -3,7 +3,6 @@
"todayData": "今日数据",
"memberNumb": "新增会员数",
"orderMoney": "订单金额",
"numberOfSites": "站点数量",
"numberOfVisitors": "今日访客数",
"commonlyUsedFunction": "常用功能",
"articleList": "文章列表",

View File

@ -1,6 +1,6 @@
{
"memberId":"会员编号",
"memberInfoPlaceholder":"请输入会员信息",
"memberInfoPlaceholder":"请输入会员编码/昵称/手机号搜索",
"memberInfo":"会员信息",
"mobile":"手机号码",
"nickName":"会员昵称",

View File

@ -6,7 +6,7 @@
"isMobile": "手机验证码登录",
"isMobileTip": "开启之后可以使用手机+验证码进行注册和登录或者快捷登录/注册",
"isBindMobile": "强制绑定手机",
"isBindMobileTip": "开启之后,会员注册时会强制绑定手机号,并且在相关页面也会引导会员强制绑定手机账号,否则将影响功能正常使用,方便会员在不同端口统一账号,也方便商家进行管理",
"isBindMobileTip": "开启之后,会员注册时会强制绑定手机号,并且在相关页面也会引导会员强制绑定手机账号,否则将影响功能正常使用,方便会员在不同端口统一账号,也方便商家进行管理,已注册会员不受影响",
"agreement": "政策协议",
"agreementTips": "注册时服务协议和隐私协议是否进行展示",
"tripartiteSetting": "第三方设置",
@ -20,4 +20,4 @@
"bgUrlPlaceholder": "建议图片尺寸750*669像素图片格式jpg、png、jpeg",
"desc": "描述",
"descPlaceholder": "请输入描述"
}
}

View File

@ -27,7 +27,6 @@
"appPublicCertPathTips": "上传appCertPublicKey文件",
"alipayPublicCertPathTips": "上传alipayCertPublicKey文件",
"alipayRootCertPathTips": "上传alipayRootCert文件",
"operationTip": "温馨提示:打款设置用于会员提现转账,发放红包等场景",
"transferTips":"注意:应微信方规定,在2025年1月15日前开通商家转账到零钱服务的商户号可正常使用转账功能,之后开通的不支持使用转账到零钱服务"
"operationTip": "温馨提示:打款设置用于会员提现转账,发放红包等场景"
}

View File

@ -0,0 +1,10 @@
{
"transferSceneId":"转账场景ID",
"transferType":"业务类型",
"recvPerception":"收款感知",
"recvPerceptionTips":"请选择收款感知",
"reportInfos":"报备背景",
"operation":"操作",
"deploy":"配置",
"noData":"暂无数据"
}

View File

@ -1,7 +1,6 @@
{
"refresh":"刷新",
"refreshMenu":"刷新菜单",
"refreshMenuDesc":"新增/修改插件菜单后,需要刷新插件菜单",
"dataCache":"数据缓存",
"dataCacheDesc":"新增/修改数据表后,需要清除数据表缓存"
}
"dataCache":"清除缓存",
"dataCacheDesc":"清除系统的所有缓存",
"refresh": "立即清除",
"clearCacheTips": "确定要清除缓存吗?"
}

View File

@ -27,11 +27,8 @@
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { ref, reactive } from 'vue'
import { t } from '@/lang'
import { getAreaListByPid } from '@/app/api/sys'
import { addMemberAddress } from '@/app/api/member'
import { filterNumber } from '@/utils/common'
import type { FormInstance } from 'element-plus'
import { FormRules } from 'element-plus'
import { cloneDeep } from 'lodash-es'
@ -39,7 +36,7 @@ import useDiyStore from '@/stores/modules/diy'
const diyStore = useDiyStore()
const dialogThemeVisible = ref(false)
let confirmRepeat = false
const confirmRepeat = ref(false)
const emit = defineEmits(['confirm'])
/**
* 表单数据
@ -99,8 +96,10 @@ const formRules = reactive<FormRules>({
})
const confirmFn = async (formEl: FormInstance | undefined) => {
if (confirmRepeat || !formEl) return
if (confirmRepeat.value || !formEl) return
await formEl.validate(async (valid) => {
if (confirmRepeat.value) return
confirmRepeat.value = true
if (valid) {
emit('confirm', cloneDeep(formData));
dialogThemeVisible.value = false;

View File

@ -10,6 +10,7 @@
<el-radio label="static">{{ t('carouselSearchShowWayStatic') }}</el-radio>
<el-radio label="fixed">{{ t('carouselSearchShowWayFixed') }}</el-radio>
</el-radio-group>
<div v-if="diyStore.editComponent.positionWay == 'fixed'" class="text-sm text-gray-400 mb-[10px]">滑动页面查看效果</div>
</el-form-item>
<el-form-item :label="t('carouselSearchFixedBgColor')" v-show="diyStore.editComponent.positionWay == 'fixed'">
<el-color-picker v-model="diyStore.editComponent.fixedBgColor" show-alpha :predefine="diyStore.predefineColors"/>

View File

@ -1,8 +1,8 @@
<template>
<!-- 内容 -->
<div class="content-wrap float-btn" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap float-btn" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<div class="edit-attr-item-wrap">
<!-- <h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('selectStyle')" class="flex">
@ -28,60 +28,68 @@
</template>
</el-dialog> -->
<h3 class="mb-[10px]">{{ t('floatBtnBtton') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('floatBtnBtton')">
<span>{{ selectTemplate.name }}</span>
<h3 class="mb-[10px]">{{ t('floatBtnButton') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('floatBtnButton')">
<span>{{ selectTemplate.name }}</span>
<ul class="ml-[10px] flex items-center">
<template v-for="(item,i) in templateList" :key="i">
<li v-if="diyStore.editComponent.style==='style-1'||(diyStore.editComponent.style==='style-2'&&i>1)" :class="['w-[50px] h-[32px] flex items-center justify-center border-solid border-[1px] border-[#eee] cursor-pointer', {'border-r-transparent': templateList.length != (i+1)}, (item.className == diyStore.editComponent.bottomPosition) ? '!border-[var(--el-color-primary)]' : '' ]" @click="changeTemplateList(item)">
<li v-if="diyStore.editComponent.style==='style-1'||(diyStore.editComponent.style==='style-2'&&i>1)"
:class="['w-[50px] h-[32px] flex items-center justify-center border-solid border-[1px] border-[#eee] cursor-pointer', {'border-r-transparent': templateList.length != (i+1)}, (item.className == diyStore.editComponent.bottomPosition) ? '!border-[var(--el-color-primary)]' : '' ]"
@click="changeTemplateList(item)">
<span :class="['iconfont !text-[20px]', item.src]"></span>
</li>
</template>
</ul>
</el-form-item>
</el-form-item>
<el-form-item :label="t('floatBtnOffset')">
<el-slider v-model="diyStore.editComponent.offset" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100"/>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('floatBtnImageSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-slider v-model="diyStore.editComponent.offset" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100" />
</el-form-item>
<el-form-item :label="t('lateralBtnOffset')">
<el-slider v-model="diyStore.editComponent.lateralOffset" show-input size="small" class="ml-[10px] diy-nav-slider" :max="15" :min="-10" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('floatBtnImageSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('floatBtnImageSize')">
<el-slider v-model="diyStore.editComponent.imageSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="30" :max="100"/>
</el-form-item>
<el-form-item :label="t('floatBtnAroundRadius')">
<el-slider v-model="diyStore.editComponent.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50"/>
</el-form-item>
<el-slider v-model="diyStore.editComponent.imageSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="30" :max="100" />
</el-form-item>
<el-form-item :label="t('floatBtnAroundRadius')">
<el-slider v-model="diyStore.editComponent.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item>
<div class="text-[12px] text-[#999] mb-[15px] mt-[5px]">{{t('floatBtnImageSuggest')}}</div>
<div ref="imageBoxRef">
<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]">
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1" />
</el-form-item>
<div class="text-[12px] text-[#999] mb-[15px] mt-[5px]">{{ t('floatBtnImageSuggest') }}</div>
<div ref="imageBoxRef">
<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]">
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1" />
</el-form-item>
<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 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>
<el-form-item :label="t('link')">
<diy-link v-model="item.link"/>
</el-form-item>
</div>
</div>
</el-form>
<el-form-item :label="t('link')">
<diy-link v-model="item.link" />
</el-form-item>
</div>
</div>
</el-form>
<el-button v-show="diyStore.editComponent.list.length < 3" class="w-full" @click="addImageAd">{{ t('addImageAd') }}</el-button>
</div>
</div>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>
@ -94,7 +102,7 @@ import { img } from '@/utils/common'
import { range } from 'lodash-es'
const diyStore = useDiyStore()
diyStore.editComponent.ignore = ['pageBgColor','marginTop','marginBottom','marginBoth','componentBgUrl'] //
diyStore.editComponent.ignore = ['pageBgColor', 'marginTop', 'marginBottom', 'marginBoth', 'componentBgUrl'] //
//
diyStore.editComponent.verify = (index: number) => {
@ -134,7 +142,7 @@ const showCouponStyle = () => {
// }
// ])
//
const changeCouponStyle = (item:any) => {
const changeCouponStyle = (item: any) => {
selectCouponStyle.title = item.title;
selectCouponStyle.value = item.value;
}

View File

@ -1,145 +1,150 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('graphicNavModeTitle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('graphicNavModeTitle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('layoutMode')">
<el-radio-group v-model="diyStore.editComponent.layout">
<el-radio :label="'horizontal'">{{t('layoutModeHorizontal')}}</el-radio>
<el-radio :label="'vertical'">{{t('layoutModeVertical')}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('layoutMode')">
<el-radio-group v-model="diyStore.editComponent.layout">
<el-radio :label="'horizontal'">{{ t('layoutModeHorizontal') }}</el-radio>
<el-radio :label="'vertical'">{{ t('layoutModeVertical') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('graphicNavSelectMode')">
<el-radio-group v-model="diyStore.editComponent.mode">
<el-radio :label="'graphic'">{{t('graphicNavModeGraphic')}}</el-radio>
<el-radio :label="'img'">{{t('graphicNavModeImg')}}</el-radio>
<el-radio :label="'text'">{{t('graphicNavModeText')}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('graphicNavSelectMode')">
<el-radio-group v-model="diyStore.editComponent.mode">
<el-radio :label="'graphic'">{{ t('graphicNavModeGraphic') }}</el-radio>
<el-radio :label="'img'">{{ t('graphicNavModeImg') }}</el-radio>
<el-radio :label="'text'">{{ t('graphicNavModeText') }}</el-radio>
</el-radio-group>
</el-form-item>
<view v-show="diyStore.editComponent.layout == 'horizontal'">
<view v-show="diyStore.editComponent.layout == 'horizontal'">
<el-form-item :label="t('graphicNavPageCount')">
<el-radio-group v-model="diyStore.editComponent.pageCount" @change="changePageCount">
<el-radio :label="1">{{t('singleLine')}}</el-radio>
<el-radio :label="2">{{t('multiline')}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('graphicNavPageCount')">
<el-radio-group v-model="diyStore.editComponent.pageCount" @change="changePageCount">
<el-radio :label="1">{{ t('singleLine') }}</el-radio>
<el-radio :label="2">{{ t('multiline') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('graphicNavShowStyle')">
<el-radio-group v-model="diyStore.editComponent.showStyle" @change="changeShowStyle">
<el-radio :label="'fixed'">{{t('graphicNavStyleFixed')}}</el-radio>
<el-radio :label="'singleSlide'">{{diyStore.editComponent.pageCount == 2 ? t('graphicNavStyleMultiLine') : t('graphicNavStyleSingleSlide')}}</el-radio>
<el-radio :label="'pageSlide'">{{t('graphicNavStylePageSlide')}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('graphicNavShowStyle')">
<el-radio-group v-model="diyStore.editComponent.showStyle" @change="changeShowStyle">
<el-radio :label="'fixed'">{{ t('graphicNavStyleFixed') }}</el-radio>
<el-radio :label="'singleSlide'">{{ diyStore.editComponent.pageCount == 2 ? t('graphicNavStyleMultiLine') : t('graphicNavStyleSingleSlide') }}</el-radio>
<el-radio :label="'pageSlide'">{{ t('graphicNavStylePageSlide') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('graphicNavRowCount')">
<el-radio-group v-model="diyStore.editComponent.rowCount">
<el-radio :label="3">3{{t('piece')}}</el-radio>
<el-radio :label="4">4{{t('piece')}}</el-radio>
<el-radio :label="5">5{{t('piece')}}</el-radio>
</el-radio-group>
</el-form-item>
</view>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('graphicNavSetLabel') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('graphicNavRowCount')">
<el-radio-group v-model="diyStore.editComponent.rowCount">
<el-radio :label="3">3{{ t('piece') }}</el-radio>
<el-radio :label="4">4{{ t('piece') }}</el-radio>
<el-radio :label="5">5{{ t('piece') }}</el-radio>
</el-radio-group>
</el-form-item>
</view>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('graphicNavSetLabel') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<p class="text-sm text-gray-400 mb-[10px]">{{ t('graphicNavTips') }}</p>
<p class="text-sm text-gray-400 mb-[10px]">{{ t('graphicNavTips') }}</p>
<div ref="imageBoxRef">
<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]">
<el-form-item :label="t('image')" v-show="diyStore.editComponent.mode === 'graphic' || diyStore.editComponent.mode === 'img'">
<upload-image v-model="item.imageUrl" :limit="1"/>
</el-form-item>
<div ref="imageBoxRef">
<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]">
<el-form-item :label="t('image')" v-show="diyStore.editComponent.mode === 'graphic' || diyStore.editComponent.mode === 'img'">
<upload-image v-model="item.imageUrl" :limit="1" />
</el-form-item>
<el-form-item :label="t('graphicNavTitle')" v-show="diyStore.editComponent.mode === 'graphic' || diyStore.editComponent.mode === 'text'">
<el-input v-model.trim="item.title" :placeholder="t('graphicNavTitlePlaceholder')" clearable maxlength="20" show-word-limit/>
</el-form-item>
<el-form-item :label="t('graphicNavTitle')" v-show="diyStore.editComponent.mode === 'graphic' || diyStore.editComponent.mode === 'text'">
<el-input v-model.trim="item.title" :placeholder="t('graphicNavTitlePlaceholder')" clearable maxlength="20" show-word-limit />
</el-form-item>
<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 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>
<el-form-item :label="t('link')">
<diy-link v-model="item.link"/>
</el-form-item>
</div>
</div>
<el-form-item :label="t('link')">
<diy-link v-model="item.link" />
</el-form-item>
</div>
</div>
<el-button v-show="diyStore.editComponent.list.length < 50" class="w-full" @click="addGraphicNav">{{ t('addGraphicNav') }}</el-button>
<el-button v-show="diyStore.editComponent.list.length < 50" class="w-full" @click="addGraphicNav">
{{ t('addGraphicNav') }}
</el-button>
</el-form>
</div>
</div>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap" v-show="['graphic','img'].includes(diyStore.editComponent.mode)">
<h3 class="mb-[10px]">{{ t('graphicNavImageSet') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('graphicNavImageSize')">
<el-slider v-model="diyStore.editComponent.imageSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="20" :max="60"/>
</el-form-item>
<el-form-item :label="t('graphicNavAroundRadius')">
<el-slider v-model="diyStore.editComponent.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50"/>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap" v-show="['graphic','text'].includes(diyStore.editComponent.mode)">
<h3 class="mb-[10px]">{{ t('textSet') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.font.size" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="16"/>
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.font.weight">
<el-radio :label="'normal'">{{t('fontWeightNormal')}}</el-radio>
<el-radio :label="'bold'">{{t('fontWeightBold')}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.font.color" show-alpha :predefine="diyStore.predefineColors"/>
</el-form-item>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap" v-show="['graphic','img'].includes(diyStore.editComponent.mode)">
<h3 class="mb-[10px]">{{ t('graphicNavImageSet') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('graphicNavImageSize')">
<el-slider v-model="diyStore.editComponent.imageSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="20" :max="60" />
</el-form-item>
<el-form-item :label="t('graphicNavAroundRadius')">
<el-slider v-model="diyStore.editComponent.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap" v-show="['graphic','text'].includes(diyStore.editComponent.mode)">
<h3 class="mb-[10px]">{{ t('textSet') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.font.size" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="16" />
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.font.weight">
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.font.color" show-alpha :predefine="diyStore.predefineColors" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.showStyle == 'pageSlide' && diyStore.editComponent.layout == 'horizontal'">
<h3 class="mb-[10px]">{{ t('carouselSearchSwiperIndicatorSet') }}</h3>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('carouselSearchSwiperIndicatorStyle')">
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorStyle">
<el-radio label="style-1">{{ t('carouselSearchSwiperIndicatorStyle1') }}</el-radio>
<el-radio label="style-2">{{ t('carouselSearchSwiperIndicatorStyle2') }}</el-radio>
<el-radio label="style-3">{{ t('carouselSearchSwiperIndicatorStyle3') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('carouselSearchSwiperIndicatorAlign')">
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorAlign">
<el-radio label="left">{{ t('alignLeft') }}</el-radio>
<el-radio label="center">{{ t('alignCenter') }}</el-radio>
<el-radio label="right">{{ t('alignRight') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('noColor')">
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorColor" show-alpha :predefine="diyStore.predefineColors"/>
</el-form-item>
<el-form-item :label="t('selectColor')">
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorActiveColor" show-alpha :predefine="diyStore.predefineColors"/>
</el-form-item>
</el-form>
</div>
</el-form>
</div>
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.showStyle == 'pageSlide' && diyStore.editComponent.layout == 'horizontal'">
<h3 class="mb-[10px]">{{ t('carouselSearchSwiperIndicatorSet') }}</h3>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('carouselSearchSwiperIndicatorStyle')">
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorStyle">
<el-radio label="style-1">{{ t('carouselSearchSwiperIndicatorStyle1') }}</el-radio>
<el-radio label="style-2">{{ t('carouselSearchSwiperIndicatorStyle2') }}</el-radio>
<el-radio label="style-3">{{ t('carouselSearchSwiperIndicatorStyle3') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('carouselSearchSwiperIndicatorAlign')">
<el-radio-group v-model="diyStore.editComponent.swiper.indicatorAlign">
<el-radio label="left">{{ t('alignLeft') }}</el-radio>
<el-radio label="center">{{ t('alignCenter') }}</el-radio>
<el-radio label="right">{{ t('alignRight') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('noColor')">
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorColor" show-alpha :predefine="diyStore.predefineColors" />
</el-form-item>
<el-form-item :label="t('selectColor')">
<el-color-picker v-model="diyStore.editComponent.swiper.indicatorActiveColor" show-alpha :predefine="diyStore.predefineColors" />
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
@ -184,7 +189,7 @@ watch(
diyStore.editComponent.list.forEach((item: any) => {
const image = new Image()
image.src = img(item.imageUrl)
image.onload = async () => {
image.onload = async() => {
item.imgWidth = image.width
item.imgHeight = image.height
}
@ -232,31 +237,31 @@ onMounted(() => {
})
})
const changePageCount = (value:any)=>{
if(value == '1'){
const changePageCount = (value: any) => {
if (value == '1') {
diyStore.editComponent.showStyle = 'singleSlide';
}else if(value == '2'){
} else if (value == '2') {
diyStore.editComponent.showStyle = 'fixed';
}
}
}
defineExpose({})
</script>
<style lang="scss" scoped>
.edit-graphic-nav {
.edit-graphic-nav {
.item-wrap {
.del {
display: none;
}
.item-wrap {
.del {
display: none;
}
&:hover {
.del {
display: block;
}
}
}
}
&:hover {
.del {
display: block;
}
}
}
}
</style>

View File

@ -1,22 +1,22 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('blankHeightSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('blankHeight')">
<el-slider v-model="diyStore.editComponent.height" show-input size="small" max="200" class="ml-[10px] diy-nav-slider"/>
</el-form-item>
</el-form>
</div>
</div>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('blankHeightSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('blankHeight')">
<el-slider v-model="diyStore.editComponent.height" show-input size="small" max="200" class="ml-[10px] diy-nav-slider" />
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>

View File

@ -1,31 +1,32 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('horzLineStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('styleLabel')">
<el-radio-group v-model="diyStore.editComponent.borderStyle">
<el-radio label="solid">{{ t('horzLineStyleSolid') }}</el-radio>
<el-radio label="dashed">{{ t('horzLineStyleDashed') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('horzLineBorderColor')">
<el-color-picker v-model="diyStore.editComponent.borderColor" show-alpha :predefine="diyStore.predefineColors"/>
</el-form-item>
<el-form-item :label="t('horzLineBorderWidth')">
<el-slider v-model="diyStore.editComponent.borderWidth" show-input size="small" class="ml-[10px] diy-nav-slider" :min="1" :max="10"/>
</el-form-item>
</el-form>
</div>
</div>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('horzLineStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('styleLabel')">
<el-radio-group v-model="diyStore.editComponent.borderStyle">
<el-radio label="solid">{{ t('horzLineStyleSolid') }}</el-radio>
<el-radio label="dashed">{{ t('horzLineStyleDashed') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('horzLineBorderColor')">
<el-color-picker v-model="diyStore.editComponent.borderColor" show-alpha :predefine="diyStore.predefineColors" />
</el-form-item>
<el-form-item :label="t('horzLineBorderWidth')">
<el-slider v-model="diyStore.editComponent.borderWidth" show-input size="small"
class="ml-[10px] diy-nav-slider" :min="1" :max="10" />
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>
@ -34,7 +35,7 @@ import { t } from '@/lang'
import useDiyStore from '@/stores/modules/diy'
const diyStore = useDiyStore()
diyStore.editComponent.ignore = ['pageBgColor','componentBgColor', 'componentBgUrl', 'topRounded', 'bottomRounded'] //
diyStore.editComponent.ignore = ['pageBgColor', 'componentBgColor', 'componentBgUrl', 'topRounded', 'bottomRounded'] //
defineExpose({})

View File

@ -1,34 +1,34 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('hotAreaSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('hotAreaSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<div ref="imageBoxRef">
<div class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
<el-form-item :label="t('hotAreaBackground')">
<upload-image v-model="diyStore.editComponent.imageUrl" :limit="1" @change="selectImg"/>
</el-form-item>
<div ref="imageBoxRef">
<div class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
<el-form-item :label="t('hotAreaBackground')">
<upload-image v-model="diyStore.editComponent.imageUrl" :limit="1" @change="selectImg" />
</el-form-item>
<el-form-item :label="t('hotAreaSet')">
<heat-map v-model="diyStore.editComponent"/>
</el-form-item>
</div>
</div>
<el-form-item :label="t('hotAreaSet')">
<heat-map v-model="diyStore.editComponent" />
</el-form-item>
</div>
</div>
</el-form>
</div>
</el-form>
</div>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>
@ -59,7 +59,7 @@ const selectImg = (url: string) => {
const handleHeight = () => {
const image = new Image()
image.src = img(diyStore.editComponent.imageUrl)
image.onload = async () => {
image.onload = async() => {
diyStore.editComponent.imgWidth = image.width
diyStore.editComponent.imgHeight = image.height
}

View File

@ -1,50 +1,54 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('imageSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('sameScreen')" v-if="diyStore.currentIndex == 0">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('imageSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('sameScreen')" v-if="diyStore.currentIndex == 0">
<el-switch v-model="diyStore.editComponent.isSameScreen" />
<div class="text-sm text-gray-400 leading-[1.4]">{{ t('imageAdsSameScreenTips') }}</div>
</el-form-item>
</el-form-item>
<el-form-item :label="t('imageHeight')" class="display-block">
<el-input v-model.trim="diyStore.editComponent.imageHeight" :placeholder="t('imageHeightPlaceholder')" clearable maxlength="10" @blur="blurImageHeight">
<template #append>px</template>
</el-input>
<div class="text-sm text-gray-400 mb-[10px]">{{ t('imageAdsTips') }}</div>
</el-form-item>
<el-form-item :label="t('imageHeight')" class="display-block">
<el-input v-model.trim="diyStore.editComponent.imageHeight" :placeholder="t('imageHeightPlaceholder')" clearable maxlength="10" @blur="blurImageHeight">
<template #append>px</template>
</el-input>
<div class="text-sm text-gray-400 mb-[10px]">{{ t('imageAdsTips') }}</div>
</el-form-item>
<div ref="imageBoxRef">
<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]">
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1" @change="selectImg" />
</el-form-item>
<div ref="imageBoxRef">
<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]">
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1" @change="selectImg" />
</el-form-item>
<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 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>
<el-form-item :label="t('link')">
<diy-link v-model="item.link"/>
</el-form-item>
</div>
</div>
<el-form-item :label="t('link')">
<diy-link v-model="item.link" />
</el-form-item>
</div>
</div>
<el-button v-show="diyStore.editComponent.list.length < 10" class="w-full" @click="addImageAd">{{ t('addImageAd') }}</el-button>
<el-button v-show="diyStore.editComponent.list.length < 10" class="w-full" @click="addImageAd">
{{ t('addImageAd') }}
</el-button>
</el-form>
</div>
</div>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>
@ -105,22 +109,22 @@ const addImageAd = () => {
})
}
const selectImg = (url:string) => {
const selectImg = (url: string) => {
handleHeight(true)
}
//
const handleHeight = (isCalcHeight:boolean = false)=> {
const handleHeight = (isCalcHeight: boolean = false) => {
diyStore.editComponent.list.forEach((item: any, index: number) => {
const image = new Image()
image.src = img(item.imageUrl)
image.onload = async () => {
image.onload = async() => {
item.imgWidth = image.width
item.imgHeight = image.height
//
if (isCalcHeight && index == 0) {
const ratio = item.imgHeight / item.imgWidth
item.width = 375 - (diyStore.editComponent.margin.both*2)
item.width = 375 - (diyStore.editComponent.margin.both * 2)
item.height = item.width * ratio
diyStore.editComponent.imageHeight = parseInt(item.height)
}
@ -158,18 +162,18 @@ defineExpose({})
</script>
<style lang="scss" scoped>
.edit-image-ads {
.edit-image-ads {
.item-wrap {
.del {
display: none;
}
.item-wrap {
.del {
display: none;
}
&:hover {
.del {
display: block;
}
}
}
}
&:hover {
.del {
display: block;
}
}
}
}
</style>

View File

@ -1,30 +1,30 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('bgUrl')">
<upload-image v-model="diyStore.editComponent.bgUrl" :limit="1"/>
</el-form-item>
</el-form>
</div>
</div>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('bgUrl')">
<upload-image v-model="diyStore.editComponent.bgUrl" :limit="1" />
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor"/>
</el-form-item>
</el-form>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('memberStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor" />
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>
<script lang="ts" setup>

View File

@ -1,46 +1,49 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer" @click="showStyle">{{ diyStore.editComponent.styleName }}</span>
<el-icon>
<ArrowRight />
</el-icon>
</el-form-item>
</el-form>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer"
@click="showStyle">{{ diyStore.editComponent.styleName }}</span>
<el-icon>
<ArrowRight />
</el-icon>
</el-form-item>
</el-form>
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="660px">
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="660px">
<div class="flex flex-wrap">
<template v-for="(item,index) in styleList" :key="index">
<div :class="{ 'border-primary': selectStyle.value == item.value, '!mr-[0]': [(index+1)%3] == 0 }" @click="changeStyle(item)" class="flex my-[5px] items-center justify-center overflow-hidden w-[200px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50">
<img :src="img(item.url)" />
</div>
</template>
</div>
<div class="flex flex-wrap">
<template v-for="(item,index) in styleList" :key="index">
<div
:class="{ 'border-primary': selectStyle.value == item.value, '!mr-[0]': [(index+1)%3] == 0 }"
@click="changeStyle(item)"
class="flex my-[5px] items-center justify-center overflow-hidden w-[200px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50">
<img :src="img(item.url)" />
</div>
</template>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" @click="confirmStyle">{{ t('confirm') }}</el-button>
</span>
</template>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" @click="confirmStyle">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</div>
</div>
</el-dialog>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -50,7 +53,7 @@ import { img } from '@/utils/common'
import { ref, reactive } from 'vue'
const diyStore = useDiyStore()
diyStore.editComponent.ignore = ['componentBgColor','componentBgUrl'] //
diyStore.editComponent.ignore = ['componentBgColor', 'componentBgUrl'] //
const selectStyle = reactive({
title: diyStore.editComponent.styleName,
@ -94,7 +97,7 @@ const styleList = reactive([
}
])
const changeStyle = (item:any) => {
const changeStyle = (item: any) => {
selectStyle.title = item.title;
selectStyle.value = item.value;
}
@ -108,22 +111,22 @@ const confirmStyle = () => {
const initStyle = (style: any) => {
if (style == 'style-1') {
diyStore.editComponent.bottomRounded = 0;
diyStore.editComponent.topRounded = 12;
} else if (style == 'style-2') {
diyStore.editComponent.bottomRounded = 0;
diyStore.editComponent.topRounded = 12;
} else if (style == 'style-3') {
diyStore.editComponent.bottomRounded = 12;
diyStore.editComponent.topRounded = 12;
} else if (style == 'style-4') {
diyStore.editComponent.bottomRounded = 12;
diyStore.editComponent.topRounded = 12;
} else if (style == 'style-5') {
diyStore.editComponent.bottomRounded = 12;
diyStore.editComponent.topRounded = 12;
}
if (style == 'style-1') {
diyStore.editComponent.bottomRounded = 0;
diyStore.editComponent.topRounded = 12;
} else if (style == 'style-2') {
diyStore.editComponent.bottomRounded = 0;
diyStore.editComponent.topRounded = 12;
} else if (style == 'style-3') {
diyStore.editComponent.bottomRounded = 12;
diyStore.editComponent.topRounded = 12;
} else if (style == 'style-4') {
diyStore.editComponent.bottomRounded = 12;
diyStore.editComponent.topRounded = 12;
} else if (style == 'style-5') {
diyStore.editComponent.bottomRounded = 12;
diyStore.editComponent.topRounded = 12;
}
}

View File

@ -1,101 +1,104 @@
<template>
<!-- 内容 -->
<div class="content-wrap notice-content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('noticeStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('noticeType')">
<el-radio-group v-model="diyStore.editComponent.noticeType">
<el-radio label="img">{{ t('noticeTypeImg') }}</el-radio>
<el-radio label="text">{{ t('noticeTypeText') }}</el-radio>
</el-radio-group>
</el-form-item>
<div class="flex items-center flex-wrap py-[8px] px-[10px] bg-[#f4f3f7] rounded mb-[18px] mx-[18px]" v-show="diyStore.editComponent.noticeType == 'img'">
<div :class="['mr-[10px] rounded cursor-pointer border-[1px] border-solid', {'border-[var(--el-color-primary)]': diyStore.editComponent.systemUrl == 'style_1' && diyStore.editComponent.imgType == 'system'}]">
<img src="@/app/assets/images/diy/notice/style_1.png" :class="['h-[28px] px-[10px] py-[5px]']" @click="changeStyle('style_1')"/>
</div>
<!-- 内容 -->
<div class="content-wrap notice-content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('noticeStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('noticeType')">
<el-radio-group v-model="diyStore.editComponent.noticeType">
<el-radio label="img">{{ t('noticeTypeImg') }}</el-radio>
<el-radio label="text">{{ t('noticeTypeText') }}</el-radio>
</el-radio-group>
</el-form-item>
<div class="flex items-center flex-wrap py-[8px] px-[10px] bg-[#f4f3f7] rounded mb-[18px] mx-[18px]" v-show="diyStore.editComponent.noticeType == 'img'">
<div :class="['mr-[10px] rounded cursor-pointer border-[1px] border-solid', {'border-[var(--el-color-primary)]': diyStore.editComponent.systemUrl == 'style_1' && diyStore.editComponent.imgType == 'system'}]">
<img src="@/app/assets/images/diy/notice/style_1.png" :class="['h-[28px] px-[10px] py-[5px]']" @click="changeStyle('style_1')" />
</div>
<div :class="['mr-[10px] rounded cursor-pointer w-[100px] border-[1px] border-solid', {'border-[var(--el-color-primary)]': diyStore.editComponent.systemUrl == 'style_2' && diyStore.editComponent.imgType == 'system'}]">
<img src="@/app/assets/images/diy/notice/style_2.png" class="px-[10px] py-[5px]" @click="changeStyle('style_2')"/>
</div>
<div @click.stop="diyStore.editComponent.imgType = 'diy'" :class="['mr-[10px] rounded cursor-pointer diy-upload-img border-[1px] border-solid', {'border-[var(--el-color-primary)]': (diyStore.editComponent.imageUrl && diyStore.editComponent.imgType == 'diy') }]">
<upload-image v-model="diyStore.editComponent.imageUrl" :limit="1"/>
</div>
</div>
<div :class="['mr-[10px] rounded cursor-pointer w-[100px] border-[1px] border-solid', {'border-[var(--el-color-primary)]': diyStore.editComponent.systemUrl == 'style_2' && diyStore.editComponent.imgType == 'system'}]">
<img src="@/app/assets/images/diy/notice/style_2.png" class="px-[10px] py-[5px]" @click="changeStyle('style_2')" />
</div>
<div @click.stop="diyStore.editComponent.imgType = 'diy'"
:class="['mr-[10px] rounded cursor-pointer diy-upload-img border-[1px] border-solid', {'border-[var(--el-color-primary)]': (diyStore.editComponent.imageUrl && diyStore.editComponent.imgType == 'diy') }]">
<upload-image v-model="diyStore.editComponent.imageUrl" :limit="1" />
</div>
</div>
<el-form-item :label="t('noticeTitle')" v-show="diyStore.editComponent.noticeType == 'text'">
<el-input v-model.trim="diyStore.editComponent.noticeTitle" :placeholder="t('titlePlaceholder')" clearable maxlength="20" show-word-limit/>
</el-form-item>
<el-form-item :label="t('noticeTitle')" v-show="diyStore.editComponent.noticeType == 'text'">
<el-input v-model.trim="diyStore.editComponent.noticeTitle" :placeholder="t('titlePlaceholder')" clearable maxlength="20" show-word-limit />
</el-form-item>
</el-form>
</el-form>
</div>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('noticeText') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('noticeText') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('noticeScrollWay')">
<el-radio-group v-model="diyStore.editComponent.scrollWay">
<el-radio label="upDown">{{ t('noticeUpDown') }}</el-radio>
<el-radio label="horizontal">{{ t('noticeHorizontal') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('noticeShowType')">
<el-radio-group v-model="diyStore.editComponent.showType">
<el-radio label="popup">{{ t('noticeShowPopUp') }}</el-radio>
<el-radio label="link">{{ t('noticeShowLink') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('noticeScrollWay')">
<el-radio-group v-model="diyStore.editComponent.scrollWay">
<el-radio label="upDown">{{ t('noticeUpDown') }}</el-radio>
<el-radio label="horizontal">{{ t('noticeHorizontal') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('noticeShowType')">
<el-radio-group v-model="diyStore.editComponent.showType">
<el-radio label="popup">{{ t('noticeShowPopUp') }}</el-radio>
<el-radio label="link">{{ t('noticeShowLink') }}</el-radio>
</el-radio-group>
</el-form-item>
<p class="text-sm text-gray-400 mb-[10px]">{{ t('dragMouseAdjustOrder') }}</p>
<p class="text-sm text-gray-400 mb-[10px]">{{ t('dragMouseAdjustOrder') }}</p>
<div ref="noticeBoxRef">
<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 ref="noticeBoxRef">
<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]">
<el-form-item :label="t('noticeText')">
<el-input v-model.trim="item.text" :placeholder="t('noticePlaceholderText')" clearable maxlength="40" show-word-limit/>
</el-form-item>
<el-form-item :label="t('noticeText')">
<el-input v-model.trim="item.text" :placeholder="t('noticePlaceholderText')" clearable maxlength="40" show-word-limit />
</el-form-item>
<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 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>
<el-form-item :label="t('link')" v-if="diyStore.editComponent.showType == 'link'">
<diy-link v-model="item.link"/>
</el-form-item>
</div>
</div>
<el-form-item :label="t('link')" v-if="diyStore.editComponent.showType == 'link'">
<diy-link v-model="item.link" />
</el-form-item>
</div>
</div>
<el-button class="w-full" @click="addNotice">{{ t('addNotice') }}</el-button>
<el-button class="w-full" @click="addNotice">{{ t('addNotice') }}</el-button>
</el-form>
</div>
</el-form>
</div>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('textSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="20"/>
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.fontWeight">
<el-radio :label="'normal'">{{t('fontWeightNormal')}}</el-radio>
<el-radio :label="'bold'">{{t('fontWeightBold')}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor"/>
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('textSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="20" />
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.fontWeight">
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor" />
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>
@ -105,6 +108,7 @@ import useDiyStore from '@/stores/modules/diy'
import { ref, watch, onMounted, nextTick } from 'vue'
import { range } from 'lodash-es'
import Sortable from 'sortablejs'
const diyStore = useDiyStore()
diyStore.editComponent.ignore = [] //
@ -112,8 +116,8 @@ diyStore.editComponent.ignore = [] // 忽略公共属性
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
if(diyStore.value[index].noticeType == 'text'){
if(diyStore.value[index].noticeTitle == ''){
if (diyStore.value[index].noticeType == 'text') {
if (diyStore.value[index].noticeTitle == '') {
res.code = false
res.message = t('noticeTypeTextPlaceholder')
return res
@ -134,9 +138,7 @@ diyStore.editComponent.list.forEach((item: any) => {
if (!item.id) item.id = diyStore.generateRandom()
})
const selectStyle = ref(diyStore.editComponent.style)
const changeStyle = (value :any) => {
const changeStyle = (value: any) => {
diyStore.editComponent.systemUrl = value;
diyStore.editComponent.imgType = 'system';
}
@ -144,11 +146,11 @@ const changeStyle = (value :any) => {
watch(
() => diyStore.editComponent.imageUrl,
(newValue, oldValue) => {
if(newValue){
if (newValue) {
diyStore.editComponent.imgType = 'diy';
}else{
changeStyle('style_1');
}
} else {
changeStyle('style_1');
}
}
)
@ -185,26 +187,26 @@ defineExpose({})
</script>
<style lang="scss">
.notice-content-wrap {
.add-notice-width {
width: calc(100% - 20px);
}
.notice-content-wrap {
.add-notice-width {
width: calc(100% - 20px);
}
.diy-upload-img {
.image-wrap {
width: 50px !important;
height: 50px !important;
margin-right: 0 !important;
background: #fff;
}
.diy-upload-img {
.image-wrap {
width: 50px !important;
height: 50px !important;
margin-right: 0 !important;
background: #fff;
}
.content-wrap {
div {
display: none;
}
}
}
}
.content-wrap {
div {
display: none;
}
}
}
}
</style>
<style lang="scss" scoped></style>

View File

@ -1,35 +1,36 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('pageContent') }}</h3>
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('diyPageTitle')">
<el-input v-model.trim="diyStore.pageTitle" :placeholder="t('diyPageTitlePlaceholder')" clearable maxlength="16" show-word-limit/>
<div class="text-sm text-gray-400">{{ t('pageTitleTips') }}</div>
</el-form-item>
</el-form>
</div>
<!-- 表单布局 页面设置 -->
<slot name="content"></slot>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('statusBarContent') }}</h3>
<h3 class="mb-[10px]">{{ t('pageContent') }}</h3>
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('diyPageTitle')">
<el-input v-model.trim="diyStore.pageTitle" :placeholder="t('diyPageTitlePlaceholder')" clearable
maxlength="16" show-word-limit />
<div class="text-sm text-gray-400">{{ t('pageTitleTips') }}</div>
</el-form-item>
</el-form>
</div>
<!-- 表单布局 页面设置 -->
<slot name="content"></slot>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('statusBarContent') }}</h3>
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('topStatusBarNav')" class="display-block">
<el-switch v-model="diyStore.global.topStatusBar.isShow"/>
<div class="text-sm text-gray-400">{{ t('statusBarSwitchTips') }}</div>
</el-form-item>
<el-switch v-model="diyStore.global.topStatusBar.isShow" />
<div class="text-sm text-gray-400">{{ t('statusBarSwitchTips') }}</div>
</el-form-item>
<template v-if="diyStore.global.topStatusBar.isShow">
<el-form-item :label="t('diyTitle')">
<el-input v-model.trim="diyStore.global.title" :placeholder="t('diyTitlePlaceholder')" clearable maxlength="12" show-word-limit/>
<el-input v-model.trim="diyStore.global.title" :placeholder="t('diyTitlePlaceholder')" clearable maxlength="12" show-word-limit />
<div class="text-sm text-gray-400">{{ t('titleTips') }}</div>
</el-form-item>
<el-form-item :label="t('selectStyle')" class="display-block">
<div class="flex">
<span class="text-primary flex-1 cursor-pointer" @click="showStyle">{{diyStore.global.topStatusBar.styleName}}</span>
<span class="text-primary flex-1 cursor-pointer" @click="showStyle">{{ diyStore.global.topStatusBar.styleName }}</span>
<el-icon>
<ArrowRight />
</el-icon>
@ -41,7 +42,7 @@
<div class="text-sm text-gray-400 mt-[10px]">{{ t('topStatusBarImgTips') }}</div>
</el-form-item>
<el-form-item :label="t('topStatusBarSearchName')" v-if="'style-3' == diyStore.global.topStatusBar.style">
<el-input v-model.trim="diyStore.global.topStatusBar.inputPlaceholder" :placeholder="t('topStatusBarSearchNamePlaceholder')" clearable maxlength="12" show-word-limit/>
<el-input v-model.trim="diyStore.global.topStatusBar.inputPlaceholder" :placeholder="t('topStatusBarSearchNamePlaceholder')" clearable maxlength="12" show-word-limit />
</el-form-item>
<el-form-item :label="t('textAlign')" v-show="diyStore.global.topStatusBar.style == 'style-1'">
<el-radio-group v-model="diyStore.global.topStatusBar.textAlign">
@ -53,31 +54,35 @@
<diy-link v-model="diyStore.global.topStatusBar.link" />
</el-form-item>
</template>
</el-form>
</div>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('bottomNavContent') }}</h3>
<h3 class="mb-[10px]">{{ t('bottomNavContent') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('tabbar')" class="display-block">
<el-switch v-model="diyStore.global.bottomTabBarSwitch"/>
<div class="text-sm text-gray-400">{{ t('tabbarSwitchTips') }}</div>
</el-form-item>
</el-form>
</div>
<el-form-item :label="t('tabbar')" class="display-block">
<el-switch v-model="diyStore.global.bottomTabBarSwitch" />
<div class="text-sm text-gray-400">{{ t('tabbarSwitchTips') }}</div>
</el-form-item>
</el-form>
</div>
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="800px">
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="800px">
<div class="flex flex-wrap">
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] mb-[15px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-1' }" @click="selectStyle = 'style-1'">
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] mb-[15px] cursor-pointer border bg-gray-50"
:class="{ 'border-primary': selectStyle == 'style-1' }" @click="selectStyle = 'style-1'">
<img class="max-w-[100%] max-h-[100%]" src="@/app/assets/images/diy/head/nav_style1.jpg" />
</div>
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] mb-[15px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-2' }" @click="selectStyle = 'style-2'">
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] mb-[15px] cursor-pointer border bg-gray-50"
:class="{ 'border-primary': selectStyle == 'style-2' }" @click="selectStyle = 'style-2'">
<img class="max-w-[100%] max-h-[100%]" src="@/app/assets/images/diy/head/nav_style2.jpg" />
</div>
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mb-[15px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-3' }" @click="selectStyle = 'style-3'">
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mb-[15px] cursor-pointer border bg-gray-50"
:class="{ 'border-primary': selectStyle == 'style-3' }" @click="selectStyle = 'style-3'">
<img class="max-w-[100%] max-h-[100%]" src="@/app/assets/images/diy/head/nav_style3.jpg" />
</div>
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-4' }" @click="selectStyle = 'style-4'">
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] mr-[2%] cursor-pointer border bg-gray-50"
:class="{ 'border-primary': selectStyle == 'style-4' }" @click="selectStyle = 'style-4'">
<img class="max-w-[100%] max-h-[100%]" src="@/app/assets/images/diy/head/nav_style4.jpg" />
</div>
</div>
@ -90,59 +95,59 @@
</template>
</el-dialog>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('pageStyle') }}</h3>
<el-form label-width="115px" class="px-[10px]">
<el-form-item :label="t('pageBgColor')">
<el-color-picker v-model="diyStore.editComponent.pageStartBgColor" show-alpha :predefine="diyStore.predefineColors" />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
<el-color-picker v-model="diyStore.editComponent.pageEndBgColor" show-alpha :predefine="diyStore.predefineColors" />
</el-form-item>
<el-form-item :label="t('bgGradientAngle')">
<el-radio-group v-model="diyStore.editComponent.pageGradientAngle">
<el-radio label="to bottom">{{ t('topToBottom') }}</el-radio>
<el-radio label="to right">{{ t('leftToRight') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('bgHeightScale')">
<el-slider v-model="diyStore.global.bgHeightScale" show-input size="small" class="ml-[10px] diy-nav-slider"/>
</el-form-item>
<div class="text-sm text-gray-400 ml-[80px] mb-[10px]">{{ t('bgHeightScaleTip') }}</div>
<el-form-item :label="t('bgUrl')">
<upload-image v-model="diyStore.global.bgUrl" :limit="1"/>
</el-form-item>
</el-form>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('statusBarStyle') }}</h3>
<el-form label-width="115px" class="px-[10px]">
<h3 class="mb-[10px]">{{ t('pageStyle') }}</h3>
<el-form label-width="115px" class="px-[10px]">
<el-form-item :label="t('pageBgColor')">
<el-color-picker v-model="diyStore.editComponent.pageStartBgColor" show-alpha :predefine="diyStore.predefineColors" />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
<el-color-picker v-model="diyStore.editComponent.pageEndBgColor" show-alpha :predefine="diyStore.predefineColors" />
</el-form-item>
<el-form-item :label="t('bgGradientAngle')">
<el-radio-group v-model="diyStore.editComponent.pageGradientAngle">
<el-radio label="to bottom">{{ t('topToBottom') }}</el-radio>
<el-radio label="to right">{{ t('leftToRight') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('bgHeightScale')">
<el-slider v-model="diyStore.global.bgHeightScale" show-input size="small" class="ml-[10px] diy-nav-slider" />
</el-form-item>
<div class="text-sm text-gray-400 ml-[80px] mb-[10px]">{{ t('bgHeightScaleTip') }}</div>
<el-form-item :label="t('bgUrl')">
<upload-image v-model="diyStore.global.bgUrl" :limit="1" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('statusBarStyle') }}</h3>
<el-form label-width="115px" class="px-[10px]">
<el-form-item :label="t('topStatusBarBgColor')" class="display-block">
<el-color-picker v-model="diyStore.global.topStatusBar.bgColor" show-alpha />
</el-form-item>
<el-form-item :label="t('rollTopStatusBarBgColor')" class="display-block">
<el-color-picker v-model="diyStore.global.topStatusBar.rollBgColor" show-alpha />
</el-form-item>
<el-form-item :label="t('topStatusBarTextColor')" class="display-block">
<el-color-picker v-model="diyStore.global.topStatusBar.textColor" show-alpha />
</el-form-item>
<el-form-item :label="t('rollTopStatusBarTextColor')" class="display-block">
<el-color-picker v-model="diyStore.global.topStatusBar.rollTextColor" show-alpha />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('marginSet') }}</h3>
<el-form label-width="115px" class="px-[10px]">
<el-form-item :label="t('marginBoth')">
<el-slider v-model="diyStore.global.template.margin.both" show-input size="small" @input="inputBoth" class="ml-[10px] diy-nav-slider"/>
</el-form-item>
</el-form>
</div>
</div>
<el-color-picker v-model="diyStore.global.topStatusBar.bgColor" show-alpha />
</el-form-item>
<el-form-item :label="t('rollTopStatusBarBgColor')" class="display-block">
<el-color-picker v-model="diyStore.global.topStatusBar.rollBgColor" show-alpha />
</el-form-item>
<el-form-item :label="t('topStatusBarTextColor')" class="display-block">
<el-color-picker v-model="diyStore.global.topStatusBar.textColor" show-alpha />
</el-form-item>
<el-form-item :label="t('rollTopStatusBarTextColor')" class="display-block">
<el-color-picker v-model="diyStore.global.topStatusBar.rollTextColor" show-alpha />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('marginSet') }}</h3>
<el-form label-width="115px" class="px-[10px]">
<el-form-item :label="t('marginBoth')">
<el-slider v-model="diyStore.global.template.margin.both" show-input size="small" @input="inputBoth" class="ml-[10px] diy-nav-slider" />
</el-form-item>
</el-form>
</div>
</div>
</template>
<script lang="ts" setup>
@ -159,11 +164,11 @@ watch(
//
const image = new Image()
image.src = img(diyStore.global.bgUrl)
image.onload = async () => {
image.onload = async() => {
diyStore.global.imgWidth = image.width
diyStore.global.imgHeight = image.height
}
if(!diyStore.global.bgUrl){
if (!diyStore.global.bgUrl) {
diyStore.global.imgWidth = ''
diyStore.global.imgHeight = ''
}
@ -171,8 +176,8 @@ watch(
)
//
const inputBoth = (value:any)=>{
diyStore.value.forEach((item,index)=>{
const inputBoth = (value: any) => {
diyStore.value.forEach((item, index) => {
item.margin.both = value;
})
@ -192,7 +197,7 @@ const showStyle = () => {
const selectStyle = ref("style-1")
const changeStyle = () => {
switch (selectStyle.value) {
switch (selectStyle.value) {
case 'style-1':
diyStore.global.topStatusBar.styleName = '风格1'
break

View File

@ -1,127 +1,129 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('pictureShowBlockOne') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('image')">
<upload-image v-model="diyStore.editComponent.moduleOne.head.textImg" :limit="1"/>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('pictureShowBlockOne') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('image')">
<upload-image v-model="diyStore.editComponent.moduleOne.head.textImg" :limit="1" />
</el-form-item>
<el-form-item :label="t('subTitle')">
<el-input v-model.trim="diyStore.editComponent.moduleOne.head.subText" :placeholder="t('subTitlePlaceholder')" clearable maxlength="8" show-word-limit />
<el-input v-model.trim="diyStore.editComponent.moduleOne.head.subText"
:placeholder="t('subTitlePlaceholder')" clearable maxlength="8" show-word-limit />
</el-form-item>
<el-form-item :label="t('subTitleTextColor')">
<el-color-picker v-model="diyStore.editComponent.moduleOne.head.subTextColor" show-alpha />
<el-color-picker v-model="diyStore.editComponent.moduleOne.head.subTextColor" show-alpha />
</el-form-item>
<el-form-item :label="t('pictureShowBgColor')">
<el-color-picker v-model="diyStore.editComponent.moduleOne.listFrame.startColor" show-alpha />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
<el-color-picker v-model="diyStore.editComponent.moduleOne.listFrame.startColor" show-alpha />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
<el-color-picker v-model="diyStore.editComponent.moduleOne.listFrame.endColor" show-alpha />
</el-form-item>
<div v-for="(item,index) in diyStore.editComponent.moduleOne.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
<div v-for="(item,index) in diyStore.editComponent.moduleOne.list" :key="item.id"
class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1"/>
<upload-image v-model="item.imageUrl" :limit="1" />
</el-form-item>
<el-form-item :label="t('pictureShowBtnText')">
<el-input v-model.trim="item.btnTitle.text" :placeholder="t('activeCubeTitlePlaceholder')" clearable maxlength="4" show-word-limit/>
<el-input v-model.trim="item.btnTitle.text" :placeholder="t('activeCubeTitlePlaceholder')" clearable maxlength="4" show-word-limit />
</el-form-item>
<el-form-item :label="t('pictureShowBtnColor')">
<el-color-picker v-model="item.btnTitle.color" show-alpha />
<el-color-picker v-model="item.btnTitle.color" show-alpha />
</el-form-item>
<el-form-item :label="t('pictureShowBtnBgColor')">
<el-color-picker v-model="item.btnTitle.startColor" show-alpha />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
<el-color-picker v-model="item.btnTitle.startColor" show-alpha />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
<el-color-picker v-model="item.btnTitle.endColor" show-alpha />
</el-form-item>
<el-form-item :label="t('link')">
<diy-link v-model="item.link"/>
<diy-link v-model="item.link" />
</el-form-item>
</div>
</el-form>
</div>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('pictureShowBlockTwo') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('pictureShowBlockTwo') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('image')">
<upload-image v-model="diyStore.editComponent.moduleTwo.head.textImg" :limit="1"/>
<upload-image v-model="diyStore.editComponent.moduleTwo.head.textImg" :limit="1" />
</el-form-item>
<el-form-item :label="t('subTitle')">
<el-input v-model.trim="diyStore.editComponent.moduleTwo.head.subText" :placeholder="t('subTitlePlaceholder')" clearable maxlength="8" show-word-limit />
</el-form-item>
<el-form-item :label="t('subTitleTextColor')">
<el-color-picker v-model="diyStore.editComponent.moduleTwo.head.subTextColor" show-alpha />
<el-color-picker v-model="diyStore.editComponent.moduleTwo.head.subTextColor" show-alpha />
</el-form-item>
<el-form-item :label="t('pictureShowBgColor')">
<el-color-picker v-model="diyStore.editComponent.moduleTwo.listFrame.startColor" show-alpha />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
<el-color-picker v-model="diyStore.editComponent.moduleTwo.listFrame.startColor" show-alpha />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
<el-color-picker v-model="diyStore.editComponent.moduleTwo.listFrame.endColor" show-alpha />
</el-form-item>
<div v-for="(item,index) in diyStore.editComponent.moduleTwo.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
<div v-for="(item,index) in diyStore.editComponent.moduleTwo.list" :key="item.id"
class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1"/>
<upload-image v-model="item.imageUrl" :limit="1" />
</el-form-item>
<el-form-item :label="t('pictureShowBtnText')">
<el-input v-model.trim="item.btnTitle.text" :placeholder="t('activeCubeTitlePlaceholder')" clearable maxlength="4" show-word-limit/>
<el-input v-model.trim="item.btnTitle.text" :placeholder="t('activeCubeTitlePlaceholder')" clearable maxlength="4" show-word-limit />
</el-form-item>
<el-form-item :label="t('pictureShowBtnColor')">
<el-color-picker v-model="item.btnTitle.color" show-alpha />
<el-color-picker v-model="item.btnTitle.color" show-alpha />
</el-form-item>
<el-form-item :label="t('pictureShowBtnBgColor')">
<el-color-picker v-model="item.btnTitle.startColor" show-alpha />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]"/>
<el-color-picker v-model="item.btnTitle.startColor" show-alpha />
<icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
<el-color-picker v-model="item.btnTitle.endColor" show-alpha />
</el-form-item>
<el-form-item :label="t('link')">
<diy-link v-model="item.link"/>
<diy-link v-model="item.link" />
</el-form-item>
</div>
</el-form>
</div>
</el-form>
</div>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('pictureShowBlockStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('topRounded')">
<el-slider v-model="diyStore.editComponent.moduleRounded.topRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100"/>
<h3 class="mb-[10px]">{{ t('pictureShowBlockStyle') }}</h3>
<el-form label-width="90px" class="px-[10px]">
<el-form-item :label="t('topRounded')">
<el-slider v-model="diyStore.editComponent.moduleRounded.topRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100" />
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider v-model="diyStore.editComponent.moduleRounded.bottomRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100"/>
<el-slider v-model="diyStore.editComponent.moduleRounded.bottomRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100" />
</el-form-item>
</el-form>
</div>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>
<script lang="ts" setup>
import { t } from '@/lang'
import useDiyStore from '@/stores/modules/diy'
import { img } from '@/utils/common'
import { ref, reactive } from 'vue'
const diyStore = useDiyStore()

View File

@ -1,18 +1,18 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('richTextContentSet') }}</h3>
<editor v-model="diyStore.editComponent.html" :height="600" class="editor-width" />
</div>
</div>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('richTextContentSet') }}</h3>
<editor v-model="diyStore.editComponent.html" :height="600" class="editor-width" />
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>
@ -27,7 +27,7 @@ diyStore.editComponent.ignore = [] // 忽略公共属性
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
if(diyStore.value[index].html == '<p><br></p>'){
if (diyStore.value[index].html == '<p><br></p>') {
res.code = false
res.message = t('richTextPlaceholder')
return res

View File

@ -1,73 +1,75 @@
<template>
<!-- 内容 -->
<div class="content-wrap rubik-cube" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap rubik-cube" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('template')">
<span>{{ selectTemplate.name }}</span>
</el-form-item>
<ul class="selected-template-list">
<li v-for="(item,i) in templateList" :key="i" :class="[(item.className == diyStore.editComponent.mode) ? 'selected' : '' ]" @click="changeTemplateList(i)">
<icon :name="'iconfont ' + item.src" size="16px"/>
</li>
</ul>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('rubikCubeLayout') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('selectStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('template')">
<span>{{ selectTemplate.name }}</span>
</el-form-item>
<ul class="selected-template-list">
<li v-for="(item,i) in templateList" :key="i"
:class="[(item.className == diyStore.editComponent.mode) ? 'selected' : '' ]"
@click="changeTemplateList(i)">
<icon :name="'iconfont ' + item.src" size="16px" />
</li>
</ul>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('rubikCubeLayout') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<ul class="layout">
<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 || diyStore.editComponent.list[i].imageUrl == 'static/resource/images/diy/figure.png'">
<p>{{li.name}}</p>
<p>{{li.desc}}</p>
</div>
</li>
</ul>
<ul class="layout">
<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 || diyStore.editComponent.list[i].imageUrl == 'static/resource/images/diy/figure.png'">
<p>{{ li.name }}</p>
<p>{{ li.desc }}</p>
</div>
</li>
</ul>
<div v-for="(item) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1" @change="selectImg"/>
</el-form-item>
<div v-for="(item) in diyStore.editComponent.list" :key="item.id" class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]">
<el-form-item :label="t('image')">
<upload-image v-model="item.imageUrl" :limit="1" @change="selectImg" />
</el-form-item>
<el-form-item :label="t('link')">
<diy-link v-model="item.link"/>
</el-form-item>
</div>
<el-form-item :label="t('link')">
<diy-link v-model="item.link" />
</el-form-item>
</div>
</el-form>
</el-form>
</div>
</div>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('rubikCubeStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('imageGap')">
<el-slider v-model="diyStore.editComponent.imageGap" show-input size="small" class="ml-[10px] diy-nav-slider" :max="30"/>
</el-form-item>
<el-form-item :label="t('topRounded')">
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50"/>
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50"/>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('rubikCubeStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('imageGap')">
<el-slider v-model="diyStore.editComponent.imageGap" show-input size="small" class="ml-[10px] diy-nav-slider" :max="30" />
</el-form-item>
<el-form-item :label="t('topRounded')">
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</template>
@ -312,16 +314,16 @@ const changeTemplateList = (v: number) => {
}
}
const selectImg = (url:string) => {
const selectImg = (url: string) => {
handleHeight(true)
}
//
const handleHeight = (isCalcHeight:boolean = false) => {
const handleHeight = (isCalcHeight: boolean = false) => {
diyStore.editComponent.list.forEach((item: any, index: number) => {
const image = new Image()
image.src = img(item.imageUrl)
image.onload = async () => {
image.onload = async() => {
item.imgWidth = image.width
item.imgHeight = image.height
}
@ -332,307 +334,307 @@ defineExpose({})
</script>
<style lang="scss" scoped>
.rubik-cube .selected-template-list {
/*padding-left: 15px;*/
margin-bottom: 20px;
overflow: hidden;
display: flex;
flex-wrap: wrap;
.rubik-cube .selected-template-list {
/*padding-left: 15px;*/
margin-bottom: 20px;
overflow: hidden;
display: flex;
flex-wrap: wrap;
li {
color: #909399;
width: 46px;
height: 32px;
text-align: center;
line-height: 29px;
border: 1px solid #e5e5e5;
cursor: pointer;
background: #ffffff;
box-sizing: border-box;
border-right: 1px transparent solid;
li {
color: #909399;
width: 46px;
height: 32px;
text-align: center;
line-height: 29px;
border: 1px solid #e5e5e5;
cursor: pointer;
background: #ffffff;
box-sizing: border-box;
border-right: 1px transparent solid;
&:last-child {
border-right: 1px solid #e5e5e5;
}
&:last-child {
border-right: 1px solid #e5e5e5;
}
&.selected {
color: var(--el-color-primary);
border-color: var(--el-color-primary);
}
&.selected {
color: var(--el-color-primary);
border-color: var(--el-color-primary);
}
img {
display: inline-block;
}
img {
display: inline-block;
}
div {
font-size: 12px;
}
}
}
div {
font-size: 12px;
}
}
}
.layout {
overflow: hidden;
position: relative;
margin-bottom: 15px;
.layout {
overflow: hidden;
position: relative;
margin-bottom: 15px;
li {
float: left;
color: #909399;
border: 1px solid #e5e5e5;
cursor: pointer;
font-size: 12px;
position: relative;
li {
float: left;
color: #909399;
border: 1px solid #e5e5e5;
cursor: pointer;
font-size: 12px;
position: relative;
div.empty {
left: 0;
text-align: center;
width: 100%;
position: absolute;
top: 50%;
margin-top: -26px;
div.empty {
left: 0;
text-align: center;
width: 100%;
position: absolute;
top: 50%;
margin-top: -26px;
p {
margin: 0;
line-height: 26px;
}
}
p {
margin: 0;
line-height: 26px;
}
}
div.have-preview-image {
box-sizing: border-box;
div.have-preview-image {
box-sizing: border-box;
img {
display: inline-block;
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
}
}
img {
display: inline-block;
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
}
}
// 12
&.row1-of2 {
width: 49.2%;
height: 160px;
border-right: 1px transparent solid;
// 12
&.row1-of2 {
width: 49.2%;
height: 160px;
border-right: 1px transparent solid;
&:last-child {
border-right: 1px solid #e5e5e5;
}
&:last-child {
border-right: 1px solid #e5e5e5;
}
div.empty {
}
div.empty {
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
}
// 13
&.row1-of3 {
width: 32.5%;
height: 100px;
border-right: 1px transparent solid;
// 13
&.row1-of3 {
width: 32.5%;
height: 100px;
border-right: 1px transparent solid;
&:last-child {
border-right: 1px solid #bdf;
}
&:last-child {
border-right: 1px solid #bdf;
}
div.empty {
}
div.empty {
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 100px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 100px;
background: #ffffff;
}
}
// 14
&.row1-of4 {
width: 24.2%;
height: 80px;
border-right: 1px transparent solid;
// 14
&.row1-of4 {
width: 24.2%;
height: 80px;
border-right: 1px transparent solid;
&:last-child {
border-right: 1px solid #bdf;
}
&:last-child {
border-right: 1px solid #bdf;
}
div.empty {
}
div.empty {
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 80px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 80px;
background: #ffffff;
}
}
// 22
&.row2-lt-of2-rt {
width: 49.2%;
height: 160px;
// 22
&.row2-lt-of2-rt {
width: 49.2%;
height: 160px;
&:nth-child(1) {
border-right: 1px transparent solid;
border-bottom: 1px transparent solid;
}
&:nth-child(1) {
border-right: 1px transparent solid;
border-bottom: 1px transparent solid;
}
&:nth-child(2) {
border-bottom: 1px transparent solid;
}
&:nth-child(2) {
border-bottom: 1px transparent solid;
}
&:nth-child(3) {
border-right: 1px transparent solid;
clear: both;
}
&:nth-child(3) {
border-right: 1px transparent solid;
clear: both;
}
div.empty {
}
div.empty {
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
// 12
&.row1-lt-of2-rt {
width: 49.2%;
font-size: 12px;
// 12
&.row1-lt-of2-rt {
width: 49.2%;
font-size: 12px;
&:nth-child(1) {
height: 322px;
border-right: 1px transparent solid;
&:nth-child(1) {
height: 322px;
border-right: 1px transparent solid;
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 322px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 322px;
background: #ffffff;
}
}
&:nth-child(2) {
height: 160px;
border-bottom: 1px transparent solid;
&:nth-child(2) {
height: 160px;
border-bottom: 1px transparent solid;
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
&:nth-child(3) {
height: 160px;
&:nth-child(3) {
height: 160px;
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
div.empty {
}
}
div.empty {
}
}
// 12
&.row1-tp-of2-bm {
height: 160px;
// 12
&.row1-tp-of2-bm {
height: 160px;
&:nth-child(1) {
width: 99.4%;
border-bottom: 1px transparent solid;
}
&:nth-child(1) {
width: 99.4%;
border-bottom: 1px transparent solid;
}
&:nth-child(2) {
width: 49.2%;
border-right: 1px transparent solid;
}
&:nth-child(2) {
width: 49.2%;
border-right: 1px transparent solid;
}
&:nth-child(3) {
width: 49.2%;
}
&:nth-child(3) {
width: 49.2%;
}
div.empty {
}
div.empty {
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
// 13
&.row1-lt-of1-tp-of2-bm {
&:nth-child(1) {
height: 320px;
width: 49.2%;
border-right: 1px transparent solid;
// 13
&.row1-lt-of1-tp-of2-bm {
&:nth-child(1) {
height: 320px;
width: 49.2%;
border-right: 1px transparent solid;
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 320px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 320px;
background: #ffffff;
}
}
&:nth-child(2) {
height: 160px;
width: 49.2%;
border-bottom: 1px transparent solid;
&:nth-child(2) {
height: 160px;
width: 49.2%;
border-bottom: 1px transparent solid;
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
&:nth-child(3) {
height: 160px;
width: 24.2%;
border-right: 1px transparent solid;
&:nth-child(3) {
height: 160px;
width: 24.2%;
border-right: 1px transparent solid;
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
&:nth-child(4) {
height: 160px;
width: 24.2%;
&:nth-child(4) {
height: 160px;
width: 24.2%;
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
div.have-preview-image {
text-align: center;
height: 100%;
line-height: 160px;
background: #ffffff;
}
}
div.empty {
}
}
div.empty {
}
}
}
}
</style>
}
}
</style>

View File

@ -1,114 +1,119 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('styleSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer" @click="showStyle">{{ diyStore.editComponent.styleName }}</span>
<el-icon>
<ArrowRight />
</el-icon>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('titleContent') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('title')">
<el-input v-model.trim="diyStore.editComponent.text" :placeholder="t('titlePlaceholder')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('link')">
<diy-link v-model="diyStore.editComponent.link" />
</el-form-item>
<el-form-item :label="t('textAlign')" v-show="diyStore.editComponent.style == 'style-1'">
<el-radio-group v-model="diyStore.editComponent.textAlign">
<el-radio :label="'left'">{{ t('textAlignLeft') }}</el-radio>
<el-radio :label="'center'">{{ t('textAlignCenter') }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</div>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('styleSet') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('selectStyle')" class="flex">
<span class="text-primary flex-1 cursor-pointer"
@click="showStyle">{{ diyStore.editComponent.styleName }}</span>
<el-icon>
<ArrowRight />
</el-icon>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('titleContent') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('title')">
<el-input v-model.trim="diyStore.editComponent.text" :placeholder="t('titlePlaceholder')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('link')">
<diy-link v-model="diyStore.editComponent.link" />
</el-form-item>
<el-form-item :label="t('textAlign')" v-show="diyStore.editComponent.style == 'style-1'">
<el-radio-group v-model="diyStore.editComponent.textAlign">
<el-radio :label="'left'">{{ t('textAlignLeft') }}</el-radio>
<el-radio :label="'center'">{{ t('textAlignCenter') }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.subTitle.control">
<h3 class="mb-[10px]">{{ t('subTitleContent') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('subTitle')">
<el-input v-model.trim="diyStore.editComponent.subTitle.text" :placeholder="t('subTitlePlaceholder')" clearable maxlength="30" show-word-limit />
</el-form-item>
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.subTitle.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="16" />
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.subTitle.color" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.subTitle.control">
<h3 class="mb-[10px]">{{ t('subTitleContent') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('subTitle')">
<el-input v-model.trim="diyStore.editComponent.subTitle.text" :placeholder="t('subTitlePlaceholder')" clearable maxlength="30" show-word-limit />
</el-form-item>
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.subTitle.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="16" />
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.subTitle.color" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.more.control">
<h3 class="mb-[10px]">{{ t('moreContent') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('more')">
<el-input v-model.trim="diyStore.editComponent.more.text" :placeholder="t('morePlaceholder')" clearable maxlength="8" show-word-limit />
</el-form-item>
<el-form-item :label="t('link')">
<diy-link v-model="diyStore.editComponent.more.link" />
</el-form-item>
<el-form-item :label="t('moreIsShow')">
<el-switch v-model="diyStore.editComponent.more.isShow" />
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.more.color" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap" v-show="diyStore.editComponent.more.control">
<h3 class="mb-[10px]">{{ t('moreContent') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('more')">
<el-input v-model.trim="diyStore.editComponent.more.text" :placeholder="t('morePlaceholder')" clearable maxlength="8" show-word-limit />
</el-form-item>
<el-form-item :label="t('link')">
<diy-link v-model="diyStore.editComponent.more.link" />
</el-form-item>
<el-form-item :label="t('moreIsShow')">
<el-switch v-model="diyStore.editComponent.more.isShow" />
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.more.color" />
</el-form-item>
</el-form>
</div>
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="620px">
<el-dialog v-model="showDialog" :title="t('selectStyle')" width="620px">
<div class="flex flex-wrap">
<div class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-1' }" @click="selectStyle = 'style-1'">
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style1.png" />
</div>
<div class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-2' }" @click="selectStyle = 'style-2'">
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style2.png" />
</div>
</div>
<div class="flex flex-wrap">
<div
class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] mr-[12px] cursor-pointer border bg-gray-50"
:class="{ 'border-primary': selectStyle == 'style-1' }" @click="selectStyle = 'style-1'">
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style1.png" />
</div>
<div
class="flex items-center justify-center overflow-hidden w-[280px] h-[100px] cursor-pointer border bg-gray-50"
:class="{ 'border-primary': selectStyle == 'style-2' }" @click="selectStyle = 'style-2'">
<img class="max-w-[280px] max-h-[220px]" src="@/app/assets/images/diy/text/style2.png" />
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" @click="changeStyle">{{ t('confirm') }}</el-button>
</span>
</template>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" @click="changeStyle">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</div>
</el-dialog>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('titleStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="30" />
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.fontWeight">
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('titleStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="30" />
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.fontWeight">
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor" />
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>

View File

@ -1,24 +1,26 @@
<template>
<el-dialog v-model="dialogThemeVisible" title="编辑色调" width="850px" align-center destroy-on-close="true">
<el-dialog v-model="dialogThemeVisible" title="编辑色调" width="850px" align-center destroy-on-close="true">
<el-form :model="openData" label-width="150px" :rules="formRules">
<el-form-item label="色调名称" prop="title" >
<el-input v-model="openData.title" placeholder="请输入色调名称" maxlength="15" class="!w-[250px]" :disabled="openData.mark != 'diy'" />
<el-form-item label="色调名称" prop="title">
<el-input v-model="openData.title" placeholder="请输入色调名称" maxlength="15" class="!w-[250px]" :disabled="openData.id != ''" />
</el-form-item>
</el-form>
<el-form :model="formData" label-width="150px" class="h-[640px] overflow-auto" ref="formRef" @submit.prevent>
<el-form-item :label="item.title" v-for="(item,index) in formData" :key="index" :prop="`${index}.value`" :rules="[{ required: true, message: `请选择${item.title}色调`, trigger: 'blur' }]">
<el-color-picker v-model="item.value" show-alpha :predefine="diyStore.predefineColors"/>
<div class="form-tip">{{item.tip}}</div>
<el-form :model="formData" label-width="150px" class="h-[640px] overflow-auto" ref="formRef" @submit.prevent>
<el-form-item :label="item.title" v-for="(item, index) in formData" :key="index" :prop="`${index}.value`"
:rules="[{ required: true, message: `请选择${item.title}色调`, trigger: 'blur' }]">
<el-color-picker v-model="item.value" show-alpha :predefine="diyStore.predefineColors" @change="colorPickerChange($event, item)" />
<div class="form-tip">{{ item.tip }}</div>
</el-form-item>
<el-form-item :label="item.title" v-for="(item,index) in openData.diy_value" :key="index">
<el-form-item :label="item.title" v-for="(item, index) in openData.new_theme" :key="index">
<div class="flex items-center">
<el-color-picker v-model="item.value" show-alpha :predefine="diyStore.predefineColors"/>
<span class="text-primary cursor-pointer text-[14px] ml-[20px]" @click="editThemeFn(item)">编辑</span>
<span class="text-primary cursor-pointer text-[14px] ml-[8px]" @click="deleteThemeFn(item)">删除</span>
<el-color-picker v-model="item.value" show-alpha :predefine="diyStore.predefineColors" />
<span class="text-primary cursor-pointer text-[14px] ml-[20px]" @click="editThemeFn(item)">编辑</span>
<span class="text-primary cursor-pointer text-[14px] ml-[8px]" @click="deleteThemeFn(item)">删除</span>
</div>
<div class="form-tip">{{item.tip}}</div>
<div class="form-tip">{{ item.tip }}</div>
</el-form-item>
<el-form-item>
@ -29,7 +31,7 @@
<div class="form-tip">新增颜色key值不能与当前的存在的key值重复</div>
</el-form-item>
</el-form>
<add-theme ref="addThemeRef" @confirm="addThemeConfirm" />
<add-theme-component ref="addThemeRef" @confirm="addThemeConfirm" />
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogThemeVisible = false">取消</el-button>
@ -43,22 +45,25 @@
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import { filterNumber } from '@/utils/common'
import { ElMessage } from 'element-plus'
import { cloneDeep } from 'lodash-es'
import addTheme from './add-theme.vue'
import addThemeComponent from './add-theme.vue'
import useDiyStore from '@/stores/modules/diy'
import { addTheme, editTheme } from '@/app/api/diy'
import type { FormInstance } from 'element-plus'
const diyStore = useDiyStore()
const dialogThemeVisible = ref(false)
const addThemeRef = ref(null)
const addThemeRef = ref()
const openData: Record<string, any> = reactive({ //
title: '',
mark: '',
diy_value: [],
default: {},
data: {}
id: '',
theme: {},
default_theme: {},
new_theme: [],
key: '',
theme_field: [] //
})
const emit = defineEmits(['confirm'])
@ -74,101 +79,45 @@ const formRules = computed(() => {
}
})
/**
* 表单数据
*/
const initialFormData = [
{
title: '主色调',
label: '--primary-color',
value: '#333333',
tip: '主色调在uiapp中使用var(--primary-color)'
},
{
title: '辅色调',
label: '--primary-help-color',
value: '#333333',
tip: '辅色调在uiapp中使用var(--primary-help-color)'
},
{
title: '页面背景色',
label: '--page-bg-color',
value: '#ffffff',
tip: '页面背景色在uiapp中使用var(--page-bg-color)'
},
{
title: '主色调浅色(淡)',
label: '--primary-color-light',
value: '',
tip: '主色调浅色在uiapp中使用var(--primary-color-light)'
},
{
title: '主色调浅色(深)',
label: '--primary-color-light2',
value: '',
tip: '主色调浅色在uiapp中使用var(--primary-color-light2)'
},
{
title: '灰色调',
label: '--primary-color-dark',
value: '#cccccc',
tip: '灰色调在uiapp中使用var(--primary-color-dark)'
},
{
title: '禁用色',
label: '--primary-color-disabled',
value: '#dddddd',
tip: '禁用色在uiapp中使用var(--primary-color-disabled)'
},
{
title: '价格颜色',
label: '--price-text-color',
value: '#333333',
tip: '价格颜色在uiapp中使用var(--price-text-color)'
}
]
const formData = ref([...cloneDeep(initialFormData)])
const formData = ref()
const open = (res:any) => { // name=>key=>default=>data=>
const open = (res: any) => { // title=>key=>default_theme=>theme=>
Object.keys(openData).forEach((key: string) => {
openData[key] = res[key] != undefined ? cloneDeep(res[key]) : ''
})
//
formData.value.forEach((item, index) => {
initialFormData.forEach((subItem, subIndex) => {
if (item.label == subItem.label) {
item.value = subItem.value
}
})
})
formData.value = [...cloneDeep(openData.theme_field)]
//
formData.value.forEach((item, index) => {
item.value = res.data[item.label] ? res.data[item.label] : item.value
item.value = res.theme[item.label] ? res.theme[item.label] : item.value
})
console.log(formData.value, openData)
dialogThemeVisible.value = true
}
//
const addThemeFn = () => {
const keyArr = []
// keyArr, key
const keyArr: string[] = []
formData.value.forEach((item, index) => {
keyArr.push(item.label)
})
const obj = {
key: keyArr
}
addThemeRef.value.open(obj)
}
//
const editThemeFn = (res:any) => {
const keyArr = []
const editThemeFn = (res: any) => {
// keyArr, key
const keyArr: string[] = []
formData.value.forEach((item, index) => {
keyArr.push(item.label)
})
const obj = {
key: keyArr,
data: res
@ -176,44 +125,44 @@ const editThemeFn = (res:any) => {
addThemeRef.value.open(obj)
}
//
const deleteThemeFn = (res:any) => {
const deleteThemeFn = (res: any) => {
let indent = -1
for (let i = 0; i < openData.diy_value.length; i++) {
if (openData.diy_value[i].label == res.label) {
for (let i = 0; i < openData.new_theme.length; i++) {
if (openData.new_theme[i].label == res.label) {
indent = i
}
}
if (indent > -1) {
openData.diy_value.splice(indent, 1)
openData.new_theme.splice(indent, 1)
}
}
//
const addThemeConfirm = (res:any) =>{
for (let i = 0; i < openData.diy_value.length; i++) {
if (openData.diy_value[i].label == res.label) {
openData.diy_value[i] = res
const addThemeConfirm = (res: any) => {
for (let i = 0; i < openData.new_theme.length; i++) {
if (openData.new_theme[i].label == res.label) {
openData.new_theme[i] = res
return
}
}
openData.diy_value.push(res)
openData.new_theme.push(res)
}
//
const resetConfirmFn = () => {
if (openData.default && Object.keys(openData.default).length) {
if (openData.default_theme && Object.keys(openData.default_theme).length) {
formData.value.forEach((item, index) => {
item.value = cloneDeep(openData.default[item.label])
item.value = openData.default_theme[item.label]
})
} else {
formData.value = cloneDeep(initialFormData)
formData.value = cloneDeep(openData.theme_field)
// title
if (!openData.id) {
openData.title = ''
}
}
openData.diy_value = []
if (openData.mark == 'diy') {
openData.title = ''
}
openData.new_theme = []
ElMessage({
message: '重置成功',
@ -221,38 +170,98 @@ const resetConfirmFn = () => {
})
}
let confirmRepeat = false
const confirmFn = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(async (valid) => {
if (valid) {
const params = {
title: '',
id: '',
theme: {},
diy_value: [],
title: ''
default_theme: {},
new_theme: [],
addon: ''
}
params.title = openData.title
formData.value.forEach((item, index) => {
params.theme[item.label] = item.value
})
openData.diy_value.forEach((item, index) => {
openData.new_theme.forEach((item, index) => {
params.theme[item.label] = item.value
})
params.diy_value = openData.diy_value || []
params.new_theme = openData.new_theme || []
let api = null
if (openData.id) {
api = editTheme
params.id = openData.id
} else {
api = addTheme
}
params.addon = openData.key
emit('confirm', params)
//
if (openData.id == '') {
const defaultTheme = {}
openData.theme_field.forEach((item, index) => {
defaultTheme[item.label] = item.value
})
params.default_theme = cloneDeep(defaultTheme)
} else {
params.default_theme = cloneDeep(openData.default_theme)
}
if (confirmRepeat) return false
confirmRepeat = true
dialogThemeVisible.value = false
api(params).then((res: any) => {
confirmRepeat = false
dialogThemeVisible.value = false
emit('confirm', params)
}).catch(() => {
confirmRepeat = false
})
}
})
}
const applyOpacity = (color, opacity) => {
// RGBA
const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/
const rgbaRegex = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(,\s*\d*\.?\d+)?\)$/
if (hexRegex.test(color)) {
// #ffffff
const hex = color.replace('#', '')
const r = parseInt(hex.substring(0, 2), 16)
const g = parseInt(hex.substring(2, 4), 16)
const b = parseInt(hex.substring(4, 6), 16)
return `rgba(${r},${g},${b},${opacity})`
} else if (rgbaRegex.test(color)) {
// RGBA rgba(255,255,255,0.5)
return color.replace(/[\d\.]+\)$/, `${opacity})`)
}
return color
}
const colorPickerChange = (e: any, data: any) => {
if (data.label == '--primary-color') {
formData.value.forEach((item, index) => {
if (item.label == '--primary-color-light') {
item.value = applyOpacity(data.value, 0.1)
}
if (item.label == '--primary-color-light2') {
item.value = applyOpacity(data.value, 0.8)
}
})
}
}
defineExpose({
dialogThemeVisible,
open
})
</script>
<style lang="scss" scoped>
</style>
<style lang="scss" scoped></style>

View File

@ -1,26 +1,42 @@
<template>
<el-dialog v-model="dialogThemeVisible" :title="data.addon_title" width="550px" align-center>
<el-form class="page-form mt-[15px]" :model="formData" label-width="90px" v-loading="loading">
<el-form-item label="选择配色">
<div class="flex items-center flex-wrap">
<template v-for="(tempItem,tempIndex) in theme_temp">
<div :key="tempIndex" v-if="tempItem.name != 'diy'" class="flex items-center border-[1px] border-solid border-[#dcdee2] rounded-[5px] h-[40px] px-[15px] mr-[10px] cursor-pointer my-[5px]" :class="{'!border-[var(--el-color-primary)]': curr_theme_mark == tempItem.name}" @click="themeTempChange(tempItem)">
<span v-if="data.theme" class="w-[20px] h-[20px] mr-[5px] rounded-[3px]" :style="{backgroundColor: data.theme['--primary-color']}"></span>
<span class="text-[14px]" :class="{'!text-[var(--el-color-primary)]': curr_theme_mark == tempItem.name}">{{tempItem.title}}</span>
<el-dialog v-model="dialogThemeVisible" :title="dialogTitle" width="535px" align-center class="custom-theme-dialog" @close="cancelFn">
<div class="flex flex-col items-baseline">
<div class="flex items-center flex-wrap max-h-[365px] overflow-auto [&>:nth-child(3n)]:mr-0">
<div :key="tempIndex" v-for="(tempItem, tempIndex) in themeTemp"
class="flex flex-col border-[1px] border-solid border-[#dcdee2] rounded-[4px] px-[10px] pt-[10px] pb-[15px] mr-[10px] cursor-pointer my-[5px]"
:class="{ '!border-[var(--el-color-primary)]': currTheme.id == tempItem.id }"
@click="themeTempChange(tempItem)">
<div class="flex justify-between pb-[5px]">
<div class="text-[14px] text-[#666] max-w-[85px] whitespace-nowrap overflow-hidden text-ellipsis" :class="{ '!text-[#333]': currTheme.id == tempItem.id }">{{ tempItem.title }}</div>
<div>
<span class="iconfont iconshanchu-fanggaiV6xx !text-[14px] text-[#999]" v-if="currTheme.id != tempItem.id && tempItem.theme_type != 'default' && currTableTheme != tempItem.id" @click.stop="deleteThemeFn(tempItem)"></span>
<span class="nc-iconfont nc-icon-bianjiV6xx1 !text-[14px] text-[#999] ml-[5px]" @click.stop="editThemeFn('edit', tempItem)"></span>
</div>
</div>
<div class="flex">
<div class="w-[70px] h-[54px] pl-[7px] pt-[9px] flex flex-col mr-[4px] rounded-[4px] text-[10px] leading-[1] text-[#fff]"
:style="{ backgroundColor: tempItem.theme['--primary-color'] }">
<span>主色调</span>
</div>
<div class="flex flex-col">
<div class="secod-color-item mb-[4px]" :style="{ backgroundColor: tempItem.theme['--primary-help-color2'] }">
<span>辅色</span>
</div>
<div class="secod-color-item" :style="{ backgroundColor: tempItem.theme['--primary-color-dark'] }">
<span>配色</span>
</div>
</div>
</template>
<div class="flex items-center border-[1px] border-solid border-[#dcdee2] rounded-[5px] h-[40px] px-[15px] cursor-pointer" :class="{'!border-[var(--el-color-primary)]': curr_theme_mark == 'diy'}" @click="themeTempChange('diy')">
<span class="nc-iconfont nc-icon-tianjiaV6xx mr-[5px]" :class="{'!text-[var(--el-color-primary)]': curr_theme_mark == 'diy'}"></span>
<span class="text-[14px]" :class="{'!text-[var(--el-color-primary)]': curr_theme_mark == 'diy'}">自定义</span>
</div>
</div>
</el-form-item>
</el-form>
<edit-theme ref="editThemeRef" @confirm="editThemeConfirm"/>
</div>
<div class="flex items-center border-[1px] border-solid border-[var(--el-color-primary)] rounded-[2px] h-[32px] px-[15px] cursor-pointer mt-[15px]" @click="editThemeFn()">
<span class="text-[14px] text-[var(--el-color-primary)]">新增配色</span>
</div>
</div>
<edit-theme ref="editThemeRef" @confirm="editThemeConfirm" />
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogThemeVisible = false">取消</el-button>
<el-button type="primary" plain @click="editThemeFn()">编辑</el-button>
<el-button @click="cancelFn()">取消</el-button>
<el-button type="primary" @click="confirmFn()">确定</el-button>
</div>
</template>
@ -28,139 +44,141 @@
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import { setDiyTheme, getDefaultTheme } from '@/app/api/diy'
import { setDiyTheme, getDefaultTheme, deleteTheme } from '@/app/api/diy'
import { cloneDeep } from 'lodash-es'
import editTheme from './edit-theme.vue'
import useDiyStore from '@/stores/modules/diy'
import { time } from 'echarts'
const diyStore = useDiyStore()
const editThemeRef = ref(null)
const editThemeRef = ref()
const dialogThemeVisible = ref(false)
let confirmRepeat = false
const curr_theme_title = ref('') //title
const curr_theme_mark = ref('') //
const curr_theme_value = ref('') //theme
const theme_temp = ref([]);
const mode = ref('default'); //
const currTheme = reactive({
title: '',
id: '',
theme: {},
default_theme: {},
new_theme: [],
addon_title: '',
key: ''
})
const themeTemp = ref([])
const emit = defineEmits(['confirm'])
const data = ref({})
const open = (res:any) => {
confirmRepeat = false;
data.value = cloneDeep(res);
curr_theme_value.value = res.value;
curr_theme_mark.value = res.color_mark;
curr_theme_title.value = res.color_name;
//
theme_temp.value.forEach((item,index)=>{
if(item.name == data.value.color_mark){
item.diy_value = data.value.diy_value;
item.title = res.color_name;
const initData = (params: any, callback: any = '') => {
getDefaultTheme({ addon: params.key }).then((res) => {
themeTemp.value = res.data || []
if (callback) {
callback(res.data[res.data.length - 1])
}
})
}
mode.value = res.mode;
const currTableTheme = ref('')
const open = (res: any) => {
currTableTheme.value = res.id
initData(res)
confirmRepeat = false
currTheme.title = res.title
currTheme.id = res.id
currTheme.theme = res.theme
currTheme.addon_title = res.addon_title
currTheme.key = res.key
dialogThemeVisible.value = true
}
const emit = defineEmits(['confirm'])
const initData = () => {
getDefaultTheme().then((res) => {
theme_temp.value = res.data || [];
//
let diy_theme_temp = {
name: 'diy',
theme: '',
title: ''
}
theme_temp.value.push(diy_theme_temp);
})
}
initData()
const dialogTitle = computed(() => {
const name = `选择${ currTheme.addon_title }配色`
return name
})
//
const themeTempChange = (item)=>{
if(item.name == data.value.color_mark){ //
curr_theme_title.value = data.value.color_name;
curr_theme_mark.value = data.value.color_mark;
curr_theme_value.value = data.value.value;
}else if(typeof item == 'object'){ //
curr_theme_title.value = item.title;
curr_theme_mark.value = item.name;
curr_theme_value.value = item.theme;
}else{ //
curr_theme_title.value = '自定义';
curr_theme_mark.value = item;
curr_theme_value.value = '';
}
const themeTempChange = (item: any = {}) => {
currTheme.title = item.title
currTheme.id = item.id
currTheme.theme = item.theme
currTheme.default_theme = item.default_theme
currTheme.new_theme = item.new_theme
}
//
const editThemeFn = ()=>{
let theme = {
default: {}, //
data: {}, //
title:'',
mark: '', // ,
diy_value: [] //
const editThemeFn = (type = 'add', item = {}) => {
const theme = {
default_theme: {}, //
theme: {}, //
title: '',
id: '', // ,
new_theme: [], //
key: '', //
theme_field: ''
}
theme.data = cloneDeep(curr_theme_value.value) || {};
theme.mark = curr_theme_mark.value;
theme_temp.value.forEach((item,index)=>{
if(item.name == curr_theme_mark.value){
theme.default = item.theme ? cloneDeep(item.theme) : '';
theme.diy_value= item.diy_value || [];
theme.title = item.title;
if (type == 'edit') {
theme.title = item.title
theme.theme = cloneDeep(item.theme) || {}
theme.id = item.id
theme.default_theme = cloneDeep(item.default_theme) || ''
theme.new_theme = cloneDeep(item.new_theme) || []
theme.new_theme = cloneDeep(item.new_theme) || []
}
theme.key = currTheme.key
//
themeTemp.value.forEach((item, index) => {
if (item.id == currTheme.id) {
theme.theme_field = item.theme_field
}
})
editThemeRef.value.open(theme)
}
//
const editThemeConfirm = (res)=>{
if(curr_theme_mark.value == data.value.color_mark){
data.value.value = res.theme;
}
theme_temp.value.forEach((item,index)=>{
if(item.name == curr_theme_mark.value){
item.diy_value= res.diy_value || [];
}
const editThemeConfirm = (res: any) => {
initData(currTheme, (params: any) => {
currTheme.new_theme = res.new_theme
currTheme.theme = res.theme
currTheme.title = res.title
currTheme.id = res.id || params.id // id, id
})
}
//
let deleteRepeat = false
const deleteThemeFn = (res: any) => {
if (deleteRepeat) return false
deleteRepeat = true
const id = res.id
deleteTheme(id).then((res) => {
initData(currTheme)
deleteRepeat = false
}).catch(() => {
deleteRepeat = false
})
data.value.title = res.title;
curr_theme_value.value = res.theme;
}
//
const confirmFn = () => {
if (confirmRepeat) return
confirmRepeat = true
let params = {}
params.id = data.value.id;
params.mode = mode.value;
params.color_mark = curr_theme_mark.value;
params.value = curr_theme_value.value;
params.key = data.value.key;
params.color_name = curr_theme_mark.value == 'diy' ? (data.value.title || '自定义') : curr_theme_title.value;
theme_temp.value.forEach((item,index)=>{
if(item.name == curr_theme_mark.value){
params.diy_value = cloneDeep(item.diy_value);
}
})
const params = {}
params.addon = currTheme.key
params.id = currTheme.id
params.title = currTheme.title
params.theme = currTheme.theme
params.new_theme = currTheme.new_theme
setDiyTheme(params).then((res) => {
emit('confirm', data);
confirmRepeat = false;
dialogThemeVisible.value = false;
}).catch(()=>{
confirmRepeat = false;
confirmRepeat = false
dialogThemeVisible.value = false
emit('confirm')
}).catch(() => {
confirmRepeat = false
})
}
//
const cancelFn = () => {
dialogThemeVisible.value = false
emit('confirm')
}
defineExpose({
@ -170,5 +188,7 @@ defineExpose({
</script>
<style lang="scss" scoped>
.secod-color-item {
@apply w-[60px] h-[25px] flex flex-col rounded-[4px] text-[10px] text-[#fff] leading-[1] items-end pt-[8px] pr-[7px];
}
</style>

View File

@ -138,7 +138,7 @@
<div class="edit-component-wrap">
<component v-if="diyStore.currentComponent" :is="modules[diyStore.currentComponent]" :value="diyStore.value[diyStore.currentIndex]">
<component v-if="diyStore.currentComponent" :is="modules[diyStore.currentComponent]" :key="diyStore.currentIndex" :value="diyStore.value[diyStore.currentIndex]">
<template #style>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('componentStyleTitle') }}</h3>

View File

@ -31,7 +31,7 @@
<div class="w-[700px]">
<div class="flex flex-wrap">
<diy-link v-model="link" :ignore="['DIY_LINK','DIY_JUMP_OTHER_APPLET','DIY_MAKE_PHONE_CALL']" @success="changePage">
<diy-link v-model="link" :ignore="['OTHER_LINK']" @success="changePage">
<el-button type="primary">{{ t('changePage') }}</el-button>
</diy-link>
<el-button type="primary" @click="toDecorate()" v-show="page.use_template.action == 'decorate'" class="ml-[12px]">{{ t('decorate') }}</el-button>

View File

@ -13,7 +13,7 @@
<el-table-column label="应用" min-width="120" >
<template #default="{ row }">
<div class="flex items-center">
<el-image class="w-[40px] h-[40px] rounded-md overflow-hidden" :src="img(row.icon)" fit="contain">
<el-image class="w-[40px] h-[40px] rounded-md overflow-hidden" :src="row.icon" fit="contain">
<template #error>
<div class="flex items-center w-full h-full">
<img class="w-full h-full" src="@/app/assets/images/icon-addon.png" alt="">
@ -27,16 +27,16 @@
<el-table-column label="配色名称" min-width="120" >
<template #default="{ row }">
<div>{{ row.color_name }}</div>
<div>{{ row.title }}</div>
</template>
</el-table-column>
<el-table-column label="配色方案" min-width="120" >
<template #default="{ row }">
<div class="rounded-[3px] inline-flex items-center justify-center border-[1px] border-solid border-[#f2f2f2] overflow-hidden" v-if="row.value">
<span class="w-[18px] h-[18px]" :style="{backgroundColor: row.value['--primary-color']}"></span>
<span class="w-[18px] h-[18px]" :style="{backgroundColor: row.value['--primary-help-color']}"></span>
<span class="w-[18px] h-[18px]" :style="{backgroundColor: '#fff'}"></span>
<div class="rounded-[3px] inline-flex items-center justify-center border-[1px] border-solid border-[#f2f2f2] overflow-hidden" v-if="row.theme">
<span class="w-[18px] h-[18px]" :style="{backgroundColor: row.theme['--primary-color']}"></span>
<span class="w-[18px] h-[18px]" :style="{backgroundColor: row.theme['--primary-help-color2']}"></span>
<span class="w-[18px] h-[18px]" :style="{backgroundColor: row.theme['--primary-color-dark']}"></span>
</div>
</template>
</el-table-column>
@ -54,17 +54,12 @@
</template>
<script lang="ts" setup>
import { reactive, ref, watch, computed } from 'vue'
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { img } from '@/utils/common'
import { setDiyTheme, getDiyTheme, getDefaultTheme } from '@/app/api/diy'
import { useClipboard } from '@vueuse/core'
import { ElMessage, FormInstance } from 'element-plus'
import { ArrowLeft } from '@element-plus/icons-vue'
import { getDiyTheme } from '@/app/api/diy'
import { useRoute } from 'vue-router'
import themeList from './components/theme-list.vue'
import { cloneDeep } from 'lodash-es'
import { tr } from 'element-plus/es/locale'
const route = useRoute()
const pageName = route.meta.title
@ -74,7 +69,7 @@ const data = ref([])
const initData = () => {
loading.value = true;
getDiyTheme().then((res) => {
getDiyTheme({}).then((res) => {
let obj = cloneDeep(res.data);
for(let key in obj){
obj[key].key = key;
@ -85,11 +80,17 @@ const initData = () => {
}
initData()
//
const editEvent = (data)=>{
themeListRef.value.open(data);
const editEvent = (data)=> {
themeListRef.value.open(data)
}
</script>
<style lang="scss" scoped></style>
<!-- 设置弹窗标题 -->
<style scoped>
/* 使用深度选择器 */
::v-deep .custom-theme-dialog .el-dialog__title {
font-size: 16px;
}
</style>

View File

@ -1,56 +1,56 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('地址格式')">
<el-radio-group v-model="diyStore.editComponent.addressFormat" class="!block">
<el-radio class="!block" label="province/city/district/address">{{ t('省/市/区/街道/详细地址') }}</el-radio>
<el-radio class="!block" label="province/city/district/street">{{ t('省/市/区/街道(镇)') }}</el-radio>
<el-radio class="!block" label="province/city/district">{{ t('省/市/区(县)') }}</el-radio>
<el-radio class="!block" label="province/city">{{ t('省/市') }}</el-radio>
<el-radio class="!block" label="province">{{ t('省') }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('地址格式')">
<el-radio-group v-model="diyStore.editComponent.addressFormat" class="!block">
<el-radio class="!block" label="province/city/district/address">{{ t('省/市/区/街道/详细地址') }}</el-radio>
<el-radio class="!block" label="province/city/district/street">{{ t('省/市/区/街道(镇)') }}</el-radio>
<el-radio class="!block" label="province/city/district">{{ t('省/市/区(县)') }}</el-radio>
<el-radio class="!block" label="province/city">{{ t('省/市') }}</el-radio>
<el-radio class="!block" label="province">{{ t('省') }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('隐私保护') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>会自动将提交的个人信息做加密展示</p>
<p>适用于公开展示收集的数据且不暴露用户隐私</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
<div class="text-sm text-gray-400">{{ t('提交后自动隐藏地址,仅管理员可查看') }}</div>
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('隐私保护') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>会自动将提交的个人信息做加密展示</p>
<p>适用于公开展示收集的数据且不暴露用户隐私</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
<div class="text-sm text-gray-400">{{ t('提交后自动隐藏地址,仅管理员可查看') }}</div>
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -63,8 +63,8 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
return res
const res = { code: true, message: '' }
return res
}
defineExpose({})

View File

@ -1,81 +1,81 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('style')">
<el-radio-group v-model="diyStore.editComponent.style">
<el-radio label="style-1">{{ t('defaultSources') }}</el-radio>
<el-radio label="style-2">{{ t('listStyle') }}</el-radio>
<el-radio label="style-3">{{ t('dropDownStyle') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('option')">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('style')">
<el-radio-group v-model="diyStore.editComponent.style">
<el-radio label="style-1">{{ t('defaultSources') }}</el-radio>
<el-radio label="style-2">{{ t('listStyle') }}</el-radio>
<el-radio label="style-3">{{ t('dropDownStyle') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('option')">
<div ref="formCheckboxRef">
<div v-for="(option, index) in diyStore.editComponent.options" :key="option.id" class="option-item flex items-center mb-[15px]">
<el-input v-model="diyStore.editComponent.options[index].text" class="!w-[215px]" :placeholder="t('optionPlaceholder')" maxlength="30" clearable />
<span v-if="diyStore.editComponent.options.length > 1" @click="removeOption(index)" class="cursor-pointer ml-[5px] nc-iconfont nc-icon-shanchu-yuangaizhiV6xx"></span>
</div>
</div>
<span class="text-primary cursor-pointer mr-[10px]" @click="addOption">{{ t('addSingleOption') }}</span>
<el-popover :visible="visible" placement="bottom" :width="300">
<p class="mb-[5px]">{{ t('addMultipleOption') }}</p>
<p class="text-[#888] text-[12px] mb-[5px]">{{ t('addOptionTips') }}</p>
<el-input v-model.trim="optionsValue" type="textarea" clearable maxlength="200" show-word-limit />
<div class="mt-[10px] text-right">
<el-button size="small" text @click="visible = false">{{ t('cancel') }}</el-button>
<el-button size="small" type="primary" @click="batchAddOptions">{{ t('confirm') }}</el-button>
</div>
<template #reference>
<span class="text-primary cursor-pointer" @click="visible = true">{{ t('addMultipleOption') }}</span>
</template>
</el-popover>
</el-form-item>
</el-form>
<span class="text-primary cursor-pointer mr-[10px]" @click="addOption">{{ t('addSingleOption') }}</span>
<el-popover :visible="visible" placement="bottom" :width="300">
<p class="mb-[5px]">{{ t('addMultipleOption') }}</p>
<p class="text-[#888] text-[12px] mb-[5px]">{{ t('addOptionTips') }}</p>
<el-input v-model.trim="optionsValue" type="textarea" clearable maxlength="200" show-word-limit />
<div class="mt-[10px] text-right">
<el-button size="small" text @click="visible = false">{{ t('cancel') }}</el-button>
<el-button size="small" type="primary" @click="batchAddOptions">{{ t('confirm') }}</el-button>
</div>
<template #reference>
<span class="text-primary cursor-pointer" @click="visible = true">{{ t('addMultipleOption') }}</span>
</template>
</el-popover>
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- <el-form label-width="100px" class="px-[10px]">-->
<!-- <el-form-item class="display-block">-->
<!-- <template #label>-->
<!-- <div class="flex items-center">-->
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
<!-- <el-tooltip effect="light" placement="top">-->
<!-- <template #content>-->
<!-- <p>会自动将提交的个人信息做加密展示</p>-->
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私</p>-->
<!-- </template>-->
<!-- <el-icon>-->
<!-- <QuestionFilled color="#999999" />-->
<!-- </el-icon>-->
<!-- </el-tooltip>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏内容,仅管理员可查看') }}</div>-->
<!-- </el-form-item>-->
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- <el-form label-width="100px" class="px-[10px]">-->
<!-- <el-form-item class="display-block">-->
<!-- <template #label>-->
<!-- <div class="flex items-center">-->
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
<!-- <el-tooltip effect="light" placement="top">-->
<!-- <template #content>-->
<!-- <p>会自动将提交的个人信息做加密展示</p>-->
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私</p>-->
<!-- </template>-->
<!-- <el-icon>-->
<!-- <QuestionFilled color="#999999" />-->
<!-- </el-icon>-->
<!-- </el-tooltip>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏内容,仅管理员可查看') }}</div>-->
<!-- </el-form-item>-->
<!-- </el-form>-->
<!-- </el-form>-->
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
import { t } from '@/lang'
import { ref, onMounted, nextTick} from 'vue'
import { ref, onMounted, nextTick } from 'vue'
import useDiyStore from '@/stores/modules/diy'
import Sortable from 'sortablejs'
import { range } from 'lodash-es'
@ -86,84 +86,84 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
let pass = true;
for (let i = 0; i < diyStore.value[index].options.length; i++) {
if (!diyStore.value[index].options[i].text) {
res.code = false;
res.message = t('optionPlaceholder');
pass = false;
break;
}
}
const res = { code: true, message: '' }
let pass = true;
for (let i = 0; i < diyStore.value[index].options.length; i++) {
if (!diyStore.value[index].options[i].text) {
res.code = false;
res.message = t('optionPlaceholder');
pass = false;
break;
}
}
if (!pass) return res;
if (!pass) return res;
let uniqueOptions = uniqueByKey(diyStore.value[index].options, 'text')
if (uniqueOptions.length != diyStore.value[index].options.length) {
res.code = false;
res.message = t('errorTipsOne')
}
return res
let uniqueOptions = uniqueByKey(diyStore.value[index].options, 'text')
if (uniqueOptions.length != diyStore.value[index].options.length) {
res.code = false;
res.message = t('errorTipsOne')
}
return res
}
diyStore.editComponent.options.forEach((item: any) => {
if (!item.id) item.id = diyStore.generateRandom()
if (!item.id) item.id = diyStore.generateRandom()
})
const visible = ref(false)
const optionsValue = ref()
const addOption = () => {
diyStore.editComponent.options.push({
id: diyStore.generateRandom(),
text: '选项' + (diyStore.editComponent.options.length + 1)
});
diyStore.editComponent.options.push({
id: diyStore.generateRandom(),
text: '选项' + (diyStore.editComponent.options.length + 1)
});
};
const removeOption = (index:any) => {
const removeOption = (index: any) => {
diyStore.editComponent.options.splice(index, 1);
}
//
const batchAddOptions = () => {
if (optionsValue.value.trim()) {
const newOptions = optionsValue.value.split(',').map((option: any) => {
return {
id: diyStore.generateRandom(),
text: option.trim()
};
}).filter((option: any) => option.text !== '');
if (optionsValue.value.trim()) {
const newOptions = optionsValue.value.split(',').map((option: any) => {
return {
id: diyStore.generateRandom(),
text: option.trim()
};
}).filter((option: any) => option.text !== '');
//
const uniqueNewOptions = uniqueByKey(newOptions, 'text');
//
const uniqueNewOptions = uniqueByKey(newOptions, 'text');
//
const filteredNewOptions = uniqueNewOptions.filter((newOption: any) =>
!diyStore.editComponent.options.some((existingOption: any) => existingOption.text === newOption.text)
);
//
const filteredNewOptions = uniqueNewOptions.filter((newOption: any) =>
!diyStore.editComponent.options.some((existingOption: any) => existingOption.text === newOption.text)
);
//
if (filteredNewOptions.length > 0) {
diyStore.editComponent.options.push(...filteredNewOptions);
} else {
ElMessage({
message: t('errorTipsTwo'),
type: "error",
});
}
//
if (filteredNewOptions.length > 0) {
diyStore.editComponent.options.push(...filteredNewOptions);
} else {
ElMessage({
message: t('errorTipsTwo'),
type: "error",
});
}
optionsValue.value = '';
visible.value = false;
}
optionsValue.value = '';
visible.value = false;
}
};
//
const uniqueByKey = (arr: any, key: any) => {
const seen = new Set();
return arr.filter((item: any) => {
const serializedKey = JSON.stringify(item[key]);
return seen.has(serializedKey) ? false : seen.add(serializedKey);
});
const seen = new Set();
return arr.filter((item: any) => {
const serializedKey = JSON.stringify(item[key]);
return seen.has(serializedKey) ? false : seen.add(serializedKey);
});
}
const formCheckboxRef = ref()

View File

@ -1,93 +1,98 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('dataFormat')">
<el-radio-group v-model="diyStore.editComponent.dateFormat">
<div class="flex flex-col">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('dataFormat')">
<el-radio-group v-model="diyStore.editComponent.dateFormat">
<div class="flex flex-col">
<el-radio label="YYYY年M月D日">{{ dateFormat.format1 }}</el-radio>
<el-radio label="YYYY-MM-DD">{{ dateFormat.format2 }}</el-radio>
<el-radio label="YYYY/MM/DD">{{ dateFormat.format3 }}</el-radio>
</div>
</el-radio-group>
</el-form-item>
</el-form>
</el-radio-group>
</el-form-item>
</el-form>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('startDate') }}</h3>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.start.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.start.defaultControl" />
</el-form-item>
<el-form-item v-if="diyStore.editComponent.start.defaultControl">
<el-radio-group v-model="diyStore.editComponent.start.dateWay">
<el-radio label="current">{{ t('currentDate') }}</el-radio>
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="diyStore.editComponent.start.defaultControl && diyStore.editComponent.start.dateWay == 'diy'">
<el-date-picker v-model="diyStore.editComponent.field.default.start.date" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" :placeholder="t('startDataPlaceholder')" @change="startDateChange" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('startDate') }}</h3>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.start.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.start.defaultControl" />
</el-form-item>
<el-form-item v-if="diyStore.editComponent.start.defaultControl">
<el-radio-group v-model="diyStore.editComponent.start.dateWay">
<el-radio label="current">{{ t('currentDate') }}</el-radio>
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="diyStore.editComponent.start.defaultControl && diyStore.editComponent.start.dateWay == 'diy'">
<el-date-picker v-model="diyStore.editComponent.field.default.start.date" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" :placeholder="t('startDataPlaceholder')" @change="startDateChange" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('endDate') }}</h3>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.end.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.end.defaultControl" />
</el-form-item>
<el-form-item v-if="diyStore.editComponent.end.defaultControl">
<el-radio-group v-model="diyStore.editComponent.end.dateWay">
<el-radio label="current">{{ t('currentDate') }}</el-radio>
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="diyStore.editComponent.end.defaultControl && diyStore.editComponent.end.dateWay == 'diy'">
<el-date-picker :disabled-date="disabledEndDate" v-model="diyStore.editComponent.field.default.end.date" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" :placeholder="t('endDataPlaceholder')" @change="endDateChange" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('endDate') }}</h3>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.end.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.end.defaultControl" />
</el-form-item>
<el-form-item v-if="diyStore.editComponent.end.defaultControl">
<el-radio-group v-model="diyStore.editComponent.end.dateWay">
<el-radio label="current">{{ t('currentDate') }}</el-radio>
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="diyStore.editComponent.end.defaultControl && diyStore.editComponent.end.dateWay == 'diy'">
<el-date-picker :disabled-date="disabledEndDate"
v-model="diyStore.editComponent.field.default.end.date" format="YYYY/MM/DD"
value-format="YYYY-MM-DD" type="date" :placeholder="t('endDataPlaceholder')"
@change="endDateChange" />
</el-form-item>
</el-form>
</div>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('textStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="18" />
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.fontWeight">
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('textStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="18" />
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.fontWeight">
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor" />
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -105,8 +110,6 @@ diyStore.editComponent.verify = (index: number) => {
let starTime = diyStore.value[index].field.default.start.date
let endTime = diyStore.value[index].field.default.end.date
console.log(diyStore.value[index].field.default)
let today = new Date()
const hours = String(today.getHours()).padStart(2, '0')
const minutes = String(today.getMinutes()).padStart(2, '0')
@ -117,6 +120,7 @@ diyStore.editComponent.verify = (index: number) => {
if (diyStore.editComponent.end.dateWay == 'current') {
endTime = today.toISOString().split('T')[0]
}
if (diyStore.editComponent.start.defaultControl && starTime == '' && diyStore.editComponent.end.dateWay == 'diy') {
res.code = false
res.message = t('startDataTips')
@ -143,13 +147,13 @@ const dateFormat: any = reactive({
})
// -
const disabledEndDate = (time:Date)=>{
const disabledEndDate = (time: Date) => {
let cutoffDate = null
let bool = false
if(diyStore.editComponent.start && diyStore.editComponent.start.defaultControl){
if(diyStore.editComponent.start.dateWay == 'diy'){
if (diyStore.editComponent.start && diyStore.editComponent.start.defaultControl) {
if (diyStore.editComponent.start.dateWay == 'diy') {
cutoffDate = new Date(diyStore.editComponent.field.default.start.date)
}else{
} else {
cutoffDate = new Date()
}
bool = time.getTime() < cutoffDate.getTime()
@ -178,14 +182,14 @@ onMounted(() => {
const hours = String(today.getHours()).padStart(2, '0')
const minutes = String(today.getMinutes()).padStart(2, '0')
dateFormat.format1 = `${year}${month}${day}`
dateFormat.format2 = `${year}-${month}-${day}`
dateFormat.format3 = `${year}/${month}/${day}`
dateFormat.format4 = `${year}-${month}-${day} ${hours}:${minutes}`
dateFormat.format1 = `${ year }${ month }${ day }`
dateFormat.format2 = `${ year }-${ month }-${ day }`
dateFormat.format3 = `${ year }/${ month }/${ day }`
dateFormat.format4 = `${ year }-${ month }-${ day } ${ hours }:${ minutes }`
})
//
const startDateChange = (date)=>{
const startDateChange = (date) => {
diyStore.editComponent.field.default.start.date = date
diyStore.editComponent.field.default.start.timestamp = timeTurnTimeStamp(date)
@ -195,7 +199,7 @@ const startDateChange = (date)=>{
diyStore.editComponent.field.default.end.timestamp = parseInt(endDate.getTime() / 1000)
}
//
const endDateChange = (date)=>{
const endDateChange = (date) => {
diyStore.editComponent.field.default.end.date = date
diyStore.editComponent.field.default.end.timestamp = timeTurnTimeStamp(date)
}

View File

@ -1,56 +1,56 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('dataFormat')">
<el-radio-group v-model="diyStore.editComponent.dateFormat" class="!block">
<el-radio class="!block" label="YYYY年M月D日">{{ dateFormat.format1 }}</el-radio>
<el-radio class="!block" label="YYYY-MM-DD">{{ dateFormat.format2 }}</el-radio>
<el-radio class="!block" label="YYYY/MM/DD">{{ dateFormat.format3 }}</el-radio>
<el-radio class="!block" label="YYYY-MM-DD HH:mm">{{ dateFormat.format4 }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.defaultControl"/>
</el-form-item>
<el-form-item v-if="diyStore.editComponent.defaultControl">
<el-radio-group v-model="diyStore.editComponent.dateWay">
<el-radio label="current">{{ t('currentDate') }}</el-radio>
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="diyStore.editComponent.defaultControl && diyStore.editComponent.dateWay == 'diy'">
<el-date-picker v-if="diyStore.editComponent.dateFormat != 'YYYY-MM-DD HH:mm'" v-model="diyStore.editComponent.field.default.date" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" :placeholder="t('dataPlaceholder')" @change="dateChange"/>
<el-date-picker v-else v-model="diyStore.editComponent.field.default.date" format="YYYY/MM/DD HH:mm" value-format="YYYY-MM-DD HH:mm" type="datetime" :placeholder="t('dataPlaceholder')" @change="dateChange"/>
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('dataFormat')">
<el-radio-group v-model="diyStore.editComponent.dateFormat" class="!block">
<el-radio class="!block" label="YYYY年M月D日">{{ dateFormat.format1 }}</el-radio>
<el-radio class="!block" label="YYYY-MM-DD">{{ dateFormat.format2 }}</el-radio>
<el-radio class="!block" label="YYYY/MM/DD">{{ dateFormat.format3 }}</el-radio>
<el-radio class="!block" label="YYYY-MM-DD HH:mm">{{ dateFormat.format4 }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.defaultControl" />
</el-form-item>
<el-form-item v-if="diyStore.editComponent.defaultControl">
<el-radio-group v-model="diyStore.editComponent.dateWay">
<el-radio label="current">{{ t('currentDate') }}</el-radio>
<el-radio label="diy">{{ t('diyDate') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="diyStore.editComponent.defaultControl && diyStore.editComponent.dateWay == 'diy'">
<el-date-picker v-if="diyStore.editComponent.dateFormat != 'YYYY-MM-DD HH:mm'" v-model="diyStore.editComponent.field.default.date" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" :placeholder="t('dataPlaceholder')" @change="dateChange" />
<el-date-picker v-else v-model="diyStore.editComponent.field.default.date" format="YYYY/MM/DD HH:mm" value-format="YYYY-MM-DD HH:mm" type="datetime" :placeholder="t('dataPlaceholder')" @change="dateChange" />
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
import { t } from '@/lang'
import { ref,reactive,watch,onMounted } from 'vue'
import { ref, reactive, onMounted } from 'vue'
import { timeTurnTimeStamp } from '@/utils/common'
import useDiyStore from '@/stores/modules/diy'
@ -64,16 +64,16 @@ diyStore.editComponent.verify = (index: number) => {
}
const dateFormat: any = reactive({
format1: '',
format2: '',
format3: '',
format4: ''
format1: '',
format2: '',
format3: '',
format4: ''
});
onMounted(() => {
//
const today = new Date();
if (!diyStore.editComponent.field.default.date) {
if (!diyStore.editComponent.field.default.date) {
diyStore.editComponent.field.default.date = today.toISOString().split('T')[0];
diyStore.editComponent.field.default.timestamp = today.getTime() / 1000;
}
@ -83,13 +83,13 @@ onMounted(() => {
const hours = String(today.getHours()).padStart(2, '0');
const minutes = String(today.getMinutes()).padStart(2, '0');
dateFormat.format1 = `${year}${month}${day}`;
dateFormat.format2 = `${year}-${month}-${day}`;
dateFormat.format3 = `${year}/${month}/${day}`;
dateFormat.format4 = `${year}-${month}-${day} ${hours}:${minutes}`;
dateFormat.format1 = `${ year }${ month }${ day }`;
dateFormat.format2 = `${ year }-${ month }-${ day }`;
dateFormat.format3 = `${ year }/${ month }/${ day }`;
dateFormat.format4 = `${ year }-${ month }-${ day } ${ hours }:${ minutes }`;
});
const dateChange = (date: any)=>{
const dateChange = (date: any) => {
diyStore.editComponent.field.default.date = date;
diyStore.editComponent.field.default.timestamp = timeTurnTimeStamp(date);
}

View File

@ -1,30 +1,30 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -38,7 +38,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
// todo
// todo
return res
}
defineExpose({})

View File

@ -1,31 +1,31 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('限制上传大小')">
<el-input v-model.trim="diyStore.editComponent.limitUploadSize" clearable maxlength="15" />
/MBBit*1024
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('限制上传大小')">
<el-input v-model.trim="diyStore.editComponent.limitUploadSize" clearable maxlength="15" />
/MBBit*1024
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>

View File

@ -1,67 +1,67 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('preventDuplicationTipsOne') }}</p>
<p>{{ t('preventDuplicationTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.unique" />
</el-form-item>
<el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('privacyProtectionTipsOne') }}</p>
<p>{{ t('privacyProtectionTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsThree') }}</div>
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('preventDuplicationTipsOne') }}</p>
<p>{{ t('preventDuplicationTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.unique" />
</el-form-item>
<el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('privacyProtectionTipsOne') }}</p>
<p>{{ t('privacyProtectionTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsThree') }}</div>
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -75,7 +75,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
// todo
// todo
return res
}
defineExpose({})

View File

@ -1,13 +1,13 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('imageLimit')">
<el-input v-model.trim="diyStore.editComponent.limit" :placeholder="t('imageLimitPlaceholder')" clearable maxlength="2" />
</el-form-item>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('imageLimit')">
<el-input v-model.trim="diyStore.editComponent.limit" :placeholder="t('imageLimitPlaceholder')" clearable maxlength="2" />
</el-form-item>
<el-form-item :label="t('上传方式')">
<el-checkbox-group v-model="diyStore.editComponent.uploadMode" :min="1">
@ -15,23 +15,23 @@
<el-checkbox label="从相册选择" value="select_from_album" />
</el-checkbox-group>
</el-form-item>
</el-form>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -44,41 +44,41 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
if (diyStore.value[index].limit == '') {
res.code = false;
res.message = t('imageLimitPlaceholder')
return res;
}
if (isNaN(diyStore.value[index].limit) || !regExp.number.test(diyStore.value[index].limit)) {
res.code = false;
res.message = t('imageLimitErrorTips');
return res;
}
if (diyStore.value[index].limit < 0) {
res.code = false;
res.message = t('imageLimitErrorTipsTwo')
return res;
}
if (diyStore.value[index].limit == 0) {
res.code = false;
res.message = t('imageLimitErrorTipsThree')
return res;
}
if (diyStore.value[index].limit > 20) {
res.code = false;
res.message = t('imafeLimitErrorTipsFour')
return res;
}
return res
const res = { code: true, message: '' }
if (diyStore.value[index].limit == '') {
res.code = false
res.message = t('imageLimitPlaceholder')
return res
}
if (isNaN(diyStore.value[index].limit) || !regExp.number.test(diyStore.value[index].limit)) {
res.code = false
res.message = t('imageLimitErrorTips')
return res
}
if (diyStore.value[index].limit < 0) {
res.code = false
res.message = t('imageLimitErrorTipsTwo')
return res
}
if (diyStore.value[index].limit == 0) {
res.code = false
res.message = t('imageLimitErrorTipsThree')
return res
}
if (diyStore.value[index].limit > 9) {
res.code = false
res.message = t('imafeLimitErrorTipsFour')
return res
}
return res
}
//
const regExp: any = {
required: /[\S]+/,
number: /^\d{0,10}$/,
digit: /^\d{0,10}(.?\d{0,2})$/,
special: /^\d{0,10}(.?\d{0,3})$/
required: /[\S]+/,
number: /^\d{0,10}$/,
digit: /^\d{0,10}(.?\d{0,2})$/,
special: /^\d{0,10}(.?\d{0,3})$/
}
defineExpose({})

View File

@ -1,80 +1,80 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-input v-model.trim="diyStore.editComponent.field.default" :placeholder="t('defaultValuePlaceholder')" clearable maxlength="18" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-input v-model.trim="diyStore.editComponent.field.default" :placeholder="t('defaultValuePlaceholder')" clearable maxlength="18" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('preventDuplicationTipsOne') }}</p>
<p>{{ t('preventDuplicationTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.unique" />
</el-form-item>
<!-- <el-form-item class="display-block">-->
<!-- <template #label>-->
<!-- <div class="flex items-center">-->
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
<!-- <el-tooltip effect="light" placement="top">-->
<!-- <template #content>-->
<!-- <p>会自动将提交的个人信息做加密展示</p>-->
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私</p>-->
<!-- </template>-->
<!-- <el-icon>-->
<!-- <QuestionFilled color="#999999" />-->
<!-- </el-icon>-->
<!-- </el-tooltip>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏文本,仅管理员可查看') }}</div>-->
<!-- </el-form-item>-->
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('preventDuplicationTipsOne') }}</p>
<p>{{ t('preventDuplicationTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.unique" />
</el-form-item>
<!-- <el-form-item class="display-block">-->
<!-- <template #label>-->
<!-- <div class="flex items-center">-->
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
<!-- <el-tooltip effect="light" placement="top">-->
<!-- <template #content>-->
<!-- <p>会自动将提交的个人信息做加密展示</p>-->
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私</p>-->
<!-- </template>-->
<!-- <el-icon>-->
<!-- <QuestionFilled color="#999999" />-->
<!-- </el-icon>-->
<!-- </el-tooltip>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏文本,仅管理员可查看') }}</div>-->
<!-- </el-form-item>-->
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -87,9 +87,9 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
// todo
return res
const res = { code: true, message: '' }
// todo
return res
}
defineExpose({})

View File

@ -1,53 +1,53 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('access')">
<el-radio-group v-model="diyStore.editComponent.mode">
<el-radio class="!mr-[20px]" label="authorized_wechat_location">{{ t('authorizeWeChatLocation') }}</el-radio>
<el-radio label="open_choose_location">{{ t('manuallySelectPositioning') }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('access')">
<el-radio-group v-model="diyStore.editComponent.mode">
<el-radio class="!mr-[20px]" label="authorized_wechat_location">{{ t('authorizeWeChatLocation') }}</el-radio>
<el-radio label="open_choose_location">{{ t('manuallySelectPositioning') }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('privacyProtectionTipsOne') }}</p>
<p>{{ t('privacyProtectionTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsFour') }}</div>
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('privacyProtectionTipsOne') }}</p>
<p>{{ t('privacyProtectionTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsFour') }}</div>
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -61,7 +61,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
// todo
// todo
return res
}
defineExpose({})

View File

@ -1,67 +1,67 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('preventDuplicationTipsOne') }}</p>
<p>{{ t('preventDuplicationTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.unique" />
</el-form-item>
<el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('privacyProtectionTipsOne') }}</p>
<p>{{ t('privacyProtectionTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsFive') }}</div>
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('preventDuplication') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('preventDuplicationTipsOne') }}</p>
<p>{{ t('preventDuplicationTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.unique" />
</el-form-item>
<el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('privacyProtection') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>{{ t('privacyProtectionTipsOne') }}</p>
<p>{{ t('privacyProtectionTipsTwo') }}</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
<div class="text-sm text-gray-400">{{ t('privacyProtectionTipsFive') }}</div>
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -75,7 +75,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
// todo
// todo
return res
}
defineExpose({})

View File

@ -1,83 +1,83 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('unit')">
<el-input v-model.trim="diyStore.editComponent.unit" :placeholder="t('unitPlaceholder')" clearable maxlength="5" show-word-limit />
</el-form-item>
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-input v-model.trim="diyStore.editComponent.field.default" :placeholder="t('defaultValuePlaceholder')" @keyup="filterDigit($event)" clearable maxlength="18" show-word-limit />
</el-form-item>
</el-form>
<el-input v-model.trim="diyStore.editComponent.unit" :placeholder="t('unitPlaceholder')" clearable maxlength="5" show-word-limit />
</el-form-item>
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-input v-model.trim="diyStore.editComponent.field.default" :placeholder="t('defaultValuePlaceholder')" @keyup="filterDigit($event)" clearable maxlength="18" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<!-- <el-form-item>-->
<!-- <template #label>-->
<!-- <div class="flex items-center">-->
<!-- <span class="mr-[3px]">{{ t('内容防重复') }}</span>-->
<!-- <el-tooltip effect="light" placement="top">-->
<!-- <template #content>-->
<!-- <p>该组件填写的内容不能与已提交的数据重复</p>-->
<!-- <p>极端情况下可能存在延时导致限制失效</p>-->
<!-- </template>-->
<!-- <el-icon>-->
<!-- <QuestionFilled color="#999999" />-->
<!-- </el-icon>-->
<!-- </el-tooltip>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-switch v-model="diyStore.editComponent.field.unique" />-->
<!-- </el-form-item>-->
<!-- <el-form-item class="display-block">-->
<!-- <template #label>-->
<!-- <div class="flex items-center">-->
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
<!-- <el-tooltip effect="light" placement="top">-->
<!-- <template #content>-->
<!-- <p>会自动将提交的个人信息做加密展示</p>-->
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私</p>-->
<!-- </template>-->
<!-- <el-icon>-->
<!-- <QuestionFilled color="#999999" />-->
<!-- </el-icon>-->
<!-- </el-tooltip>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏数字,仅管理员可查看') }}</div>-->
<!-- </el-form-item>-->
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<el-form label-width="100px" class="px-[10px]">
<!-- <el-form-item>-->
<!-- <template #label>-->
<!-- <div class="flex items-center">-->
<!-- <span class="mr-[3px]">{{ t('内容防重复') }}</span>-->
<!-- <el-tooltip effect="light" placement="top">-->
<!-- <template #content>-->
<!-- <p>该组件填写的内容不能与已提交的数据重复</p>-->
<!-- <p>极端情况下可能存在延时导致限制失效</p>-->
<!-- </template>-->
<!-- <el-icon>-->
<!-- <QuestionFilled color="#999999" />-->
<!-- </el-icon>-->
<!-- </el-tooltip>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-switch v-model="diyStore.editComponent.field.unique" />-->
<!-- </el-form-item>-->
<!-- <el-form-item class="display-block">-->
<!-- <template #label>-->
<!-- <div class="flex items-center">-->
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
<!-- <el-tooltip effect="light" placement="top">-->
<!-- <template #content>-->
<!-- <p>会自动将提交的个人信息做加密展示</p>-->
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私</p>-->
<!-- </template>-->
<!-- <el-icon>-->
<!-- <QuestionFilled color="#999999" />-->
<!-- </el-icon>-->
<!-- </el-tooltip>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏数字,仅管理员可查看') }}</div>-->
<!-- </el-form-item>-->
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -92,24 +92,24 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
if(diyStore.value[index].field.default){
if (isNaN(diyStore.value[index].field.default) || !regExp.digit.test(diyStore.value[index].field.default)) {
res.code = false;
res.message = t('defaultErrorTips');
} else if (diyStore.value[index].field.default < 0) {
res.code = false;
res.message = t('defaultMustZeroTips')
}
}
return res
if (diyStore.value[index].field.default) {
if (isNaN(diyStore.value[index].field.default) || !regExp.digit.test(diyStore.value[index].field.default)) {
res.code = false;
res.message = t('defaultErrorTips');
} else if (diyStore.value[index].field.default < 0) {
res.code = false;
res.message = t('defaultMustZeroTips')
}
}
return res
}
//
const regExp: any = {
required: /[\S]+/,
number: /^\d{0,10}$/,
digit: /^\d{0,10}(.?\d{0,2})$/,
special: /^\d{0,10}(.?\d{0,3})$/
required: /[\S]+/,
number: /^\d{0,10}$/,
digit: /^\d{0,10}(.?\d{0,2})$/,
special: /^\d{0,10}(.?\d{0,3})$/
}
defineExpose({})

View File

@ -1,189 +1,189 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('style')">
<el-radio-group v-model="diyStore.editComponent.style">
<el-radio label="style-1">{{ t('defaultSources') }}</el-radio>
<el-radio label="style-2">{{ t('listStyle') }}</el-radio>
<el-radio label="style-3">{{ t('dropDownStyle') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('option')">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('style')">
<el-radio-group v-model="diyStore.editComponent.style">
<el-radio label="style-1">{{ t('defaultSources') }}</el-radio>
<el-radio label="style-2">{{ t('listStyle') }}</el-radio>
<el-radio label="style-3">{{ t('dropDownStyle') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('option')">
<div ref="formRadioRef">
<div v-for="(option, index) in diyStore.editComponent.options" :key="option.id" class="option-item flex items-center mb-[15px]">
<el-input v-model="diyStore.editComponent.options[index].text" class="!w-[215px]" :placeholder="t('optionPlaceholder')" clearable maxlength="30" />
<span v-if="diyStore.editComponent.options.length > 1" @click="removeOption(index)" class="cursor-pointer ml-[5px] nc-iconfont nc-icon-shanchu-yuangaizhiV6xx"></span>
</div>
</div>
<span class="text-primary cursor-pointer mr-[10px]" @click="addOption">{{ t('addSingleOption') }}</span>
<el-popover :visible="visible" placement="bottom" :width="300">
<p class="mb-[5px]">{{ t('addMultipleOption') }}</p>
<p class="text-[#888] text-[12px] mb-[5px]">{{ t('addOptionTips') }}</p>
<el-input v-model.trim="optionsValue" type="textarea" clearable maxlength="200" show-word-limit />
<div class="mt-[10px] text-right">
<el-button size="small" text @click="visible = false">{{ t('cancel') }}</el-button>
<el-button size="small" type="primary" @click="batchAddOptions">{{ t('confirm') }}</el-button>
</div>
<template #reference>
<span class="text-primary cursor-pointer" @click="visible = true">{{ t('addMultipleOption') }}</span>
</template>
</el-popover>
</el-form-item>
<!-- <el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('逻辑规则') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>支持选择某个选项后显示特定的组件</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<div>
<el-button plain>{{ t('添加字段显示规则') }}</el-button>
<span class="mr-[3px]">1条字段显示规则</span>
<span class="text-primary cursor-pointer" @click="">设置</span>
</div>
</el-form-item> -->
</el-form>
<span class="text-primary cursor-pointer mr-[10px]" @click="addOption">{{ t('addSingleOption') }}</span>
<el-popover :visible="visible" placement="bottom" :width="300">
<p class="mb-[5px]">{{ t('addMultipleOption') }}</p>
<p class="text-[#888] text-[12px] mb-[5px]">{{ t('addOptionTips') }}</p>
<el-input v-model.trim="optionsValue" type="textarea" clearable maxlength="200" show-word-limit />
<div class="mt-[10px] text-right">
<el-button size="small" text @click="visible = false">{{ t('cancel') }}</el-button>
<el-button size="small" type="primary" @click="batchAddOptions">{{ t('confirm') }}</el-button>
</div>
<template #reference>
<span class="text-primary cursor-pointer" @click="visible = true">{{ t('addMultipleOption') }}</span>
</template>
</el-popover>
</el-form-item>
<!-- <el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('逻辑规则') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>支持选择某个选项后显示特定的组件</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<div>
<el-button plain>{{ t('添加字段显示规则') }}</el-button>
<span class="mr-[3px]">1条字段显示规则</span>
<span class="text-primary cursor-pointer" @click="">设置</span>
</div>
</el-form-item> -->
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- <el-form label-width="100px" class="px-[10px]">-->
<!-- <el-form-item class="display-block">-->
<!-- <template #label>-->
<!-- <div class="flex items-center">-->
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
<!-- <el-tooltip effect="light" placement="top">-->
<!-- <template #content>-->
<!-- <p>会自动将提交的个人信息做加密展示</p>-->
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私</p>-->
<!-- </template>-->
<!-- <el-icon>-->
<!-- <QuestionFilled color="#999999" />-->
<!-- </el-icon>-->
<!-- </el-tooltip>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏内容,仅管理员可查看') }}</div>-->
<!-- </el-form-item>-->
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- <el-form label-width="100px" class="px-[10px]">-->
<!-- <el-form-item class="display-block">-->
<!-- <template #label>-->
<!-- <div class="flex items-center">-->
<!-- <span class="mr-[3px]">{{ t('隐私保护') }}</span>-->
<!-- <el-tooltip effect="light" placement="top">-->
<!-- <template #content>-->
<!-- <p>会自动将提交的个人信息做加密展示</p>-->
<!-- <p>适用于公开展示收集的数据且不暴露用户隐私</p>-->
<!-- </template>-->
<!-- <el-icon>-->
<!-- <QuestionFilled color="#999999" />-->
<!-- </el-icon>-->
<!-- </el-tooltip>-->
<!-- </div>-->
<!-- </template>-->
<!-- <el-switch v-model="diyStore.editComponent.field.privacyProtection" />-->
<!-- <div class="text-sm text-gray-400">{{ t('提交后自动隐藏内容,仅管理员可查看') }}</div>-->
<!-- </el-form-item>-->
<!-- </el-form>-->
<!-- </el-form>-->
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
import { t } from '@/lang'
import { ref, onMounted, nextTick} from 'vue'
import { ref, onMounted, nextTick } from 'vue'
import useDiyStore from '@/stores/modules/diy'
import Sortable from 'sortablejs'
import { range } from 'lodash-es'
import { FormInstance, ElMessage } from "element-plus";
import { ElMessage } from "element-plus";
const diyStore = useDiyStore()
diyStore.editComponent.ignore = ['componentBgUrl'] //
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
let pass = true;
for (let i = 0; i < diyStore.value[index].options.length; i++) {
if (!diyStore.value[index].options[i].text) {
res.code = false;
res.message = t('optionPlaceholder');
pass = false;
break;
}
}
const res = { code: true, message: '' }
let pass = true;
for (let i = 0; i < diyStore.value[index].options.length; i++) {
if (!diyStore.value[index].options[i].text) {
res.code = false;
res.message = t('optionPlaceholder');
pass = false;
break;
}
}
if (!pass) return res;
if (!pass) return res;
let uniqueOptions = uniqueByKey(diyStore.value[index].options, 'text')
let uniqueOptions = uniqueByKey(diyStore.value[index].options, 'text')
if (uniqueOptions.length != diyStore.value[index].options.length) {
res.code = false;
res.message = t('errorTipsOne')
}
return res
if (uniqueOptions.length != diyStore.value[index].options.length) {
res.code = false;
res.message = t('errorTipsOne')
}
return res
}
diyStore.editComponent.options.forEach((item: any) => {
if (!item.id) item.id = diyStore.generateRandom()
if (!item.id) item.id = diyStore.generateRandom()
})
const visible = ref(false)
const optionsValue = ref()
const addOption = () => {
diyStore.editComponent.options.push({
id: diyStore.generateRandom(),
text: '选项' + (diyStore.editComponent.options.length + 1)
});
diyStore.editComponent.options.push({
id: diyStore.generateRandom(),
text: '选项' + (diyStore.editComponent.options.length + 1)
});
};
const removeOption = (index:any) => {
const removeOption = (index: any) => {
diyStore.editComponent.options.splice(index, 1);
}
const batchAddOptions = () => {
if (optionsValue.value.trim()) {
const newOptions = optionsValue.value.split(',').map((option: any) => {
return {
id: diyStore.generateRandom(),
text: option.trim()
};
}).filter((option: any) => option.text !== '');
if (optionsValue.value.trim()) {
const newOptions = optionsValue.value.split(',').map((option: any) => {
return {
id: diyStore.generateRandom(),
text: option.trim()
};
}).filter((option: any) => option.text !== '');
//
const uniqueNewOptions = uniqueByKey(newOptions, 'text');
//
const uniqueNewOptions = uniqueByKey(newOptions, 'text');
//
const filteredNewOptions = uniqueNewOptions.filter(newOption =>
!diyStore.editComponent.options.some(existingOption => existingOption.text === newOption.text)
);
//
const filteredNewOptions = uniqueNewOptions.filter(newOption =>
!diyStore.editComponent.options.some(existingOption => existingOption.text === newOption.text)
);
//
if (filteredNewOptions.length > 0) {
diyStore.editComponent.options.push(...filteredNewOptions);
} else {
ElMessage({
message: t('errorTipsTwo'),
type: "warning",
});
}
//
if (filteredNewOptions.length > 0) {
diyStore.editComponent.options.push(...filteredNewOptions);
} else {
ElMessage({
message: t('errorTipsTwo'),
type: "warning",
});
}
optionsValue.value = '';
visible.value = false;
}
optionsValue.value = '';
visible.value = false;
}
};
//
const uniqueByKey = (arr: any, key: any) => {
const seen = new Set();
return arr.filter((item: any) => {
const serializedKey = JSON.stringify(item[key]);
return seen.has(serializedKey) ? false : seen.add(serializedKey);
});
const seen = new Set();
return arr.filter((item: any) => {
const serializedKey = JSON.stringify(item[key]);
return seen.has(serializedKey) ? false : seen.add(serializedKey);
});
}
const formRadioRef = ref()

View File

@ -1,75 +1,79 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<div class="edit-attr-item-wrap">
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('floatBtnBtton')" class="display-block">
<el-radio-group v-model="diyStore.editComponent.btnPosition" @change="btnPositionChangeFn">
<el-radio label="follow_content">{{ t('followContent') }}</el-radio>
<el-radio label="hover_screen_bottom">{{ t('hoverScreenBottom') }}</el-radio>
</el-radio-group>
<div class="text-sm text-gray-400 mb-[5px] leading-[1.4]" v-show="diyStore.editComponent.btnPosition == 'follow_content'">{{ t('btnTips') }}</div>
<div class="text-sm text-gray-400 mb-[5px]" v-show="diyStore.editComponent.btnPosition == 'hover_screen_bottom'">{{ t('btnTipsTwo') }}</div>
<el-form-item :label="t('floatBtnButton')" class="display-block">
<el-radio-group v-model="diyStore.editComponent.btnPosition" @change="btnPositionChangeFn">
<el-radio label="follow_content">{{ t('followContent') }}</el-radio>
<el-radio label="hover_screen_bottom">{{ t('hoverScreenBottom') }}</el-radio>
</el-radio-group>
<div class="text-sm text-gray-400 mb-[5px] leading-[1.4]"
v-show="diyStore.editComponent.btnPosition == 'follow_content'">{{ t('btnTips') }}
</div>
<div class="text-sm text-gray-400 mb-[5px]"
v-show="diyStore.editComponent.btnPosition == 'hover_screen_bottom'">{{ t('btnTipsTwo') }}
</div>
<div class="text-sm text-gray-400 mb-[10px] leading-[1.4]">{{ t('btnTipsThree') }}</div>
</el-form-item>
</el-form>
</el-form-item>
</el-form>
</div>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('submitBtn') }}</h3>
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('submitBtnName')">
<el-input v-model.trim="diyStore.editComponent.submitBtn.text" :placeholder="t('btnNamePlaceholder')" clearable maxlength="10" show-word-limit />
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.submitBtn.color" />
</el-form-item>
<el-form-item :label="t('subTextBgColor')">
<el-color-picker v-model="diyStore.editComponent.submitBtn.bgColor" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('submitBtn') }}</h3>
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('submitBtnName')">
<el-input v-model.trim="diyStore.editComponent.submitBtn.text" :placeholder="t('btnNamePlaceholder')" clearable maxlength="10" show-word-limit />
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.submitBtn.color" />
</el-form-item>
<el-form-item :label="t('subTextBgColor')">
<el-color-picker v-model="diyStore.editComponent.submitBtn.bgColor" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('resetBtn') }}</h3>
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('carouselSearchTabControl')">
<el-switch v-model="diyStore.editComponent.resetBtn.control" />
</el-form-item>
<el-form-item :label="t('submitBtnName')">
<el-input v-model.trim="diyStore.editComponent.resetBtn.text" :placeholder="t('btnNamePlaceholder')" clearable maxlength="10" show-word-limit />
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.resetBtn.color" />
</el-form-item>
<el-form-item :label="t('subTextBgColor')">
<el-color-picker v-model="diyStore.editComponent.resetBtn.bgColor" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('resetBtn') }}</h3>
<el-form label-width="80px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('carouselSearchTabControl')">
<el-switch v-model="diyStore.editComponent.resetBtn.control" />
</el-form-item>
<el-form-item :label="t('submitBtnName')">
<el-input v-model.trim="diyStore.editComponent.resetBtn.text" :placeholder="t('btnNamePlaceholder')" clearable maxlength="10" show-word-limit />
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.resetBtn.color" />
</el-form-item>
<el-form-item :label="t('subTextBgColor')">
<el-color-picker v-model="diyStore.editComponent.resetBtn.bgColor" />
</el-form-item>
</el-form>
</div>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('btnStyle') }}</h3>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('topRounded')">
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('btnStyle') }}</h3>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('topRounded')">
<el-slider v-model="diyStore.editComponent.topElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item>
<el-form-item :label="t('bottomRounded')">
<el-slider v-model="diyStore.editComponent.bottomElementRounded" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -81,8 +85,8 @@ const diyStore = useDiyStore()
diyStore.editComponent.ignore = ['componentBgUrl'] //
//
const btnPositionChangeFn = (e)=>{
if(e == 'hover_screen_bottom'){
const btnPositionChangeFn = (e) => {
if (e == 'hover_screen_bottom') {
diyStore.editComponent.margin.bottom = 0;
diyStore.editComponent.margin.both = 0;
diyStore.editComponent.margin.top = 0;
@ -91,19 +95,19 @@ const btnPositionChangeFn = (e)=>{
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
if (diyStore.value[index].submitBtn.text == '') {
res.code = false;
res.message = t('submitBtnNamePlaceholder');
return res;
}
if (diyStore.value[index].resetBtn.text == '') {
res.code = false;
res.message = t('resetBtnNamePlaceholder');
return res;
}
const res = { code: true, message: '' }
if (diyStore.value[index].submitBtn.text == '') {
res.code = false;
res.message = t('submitBtnNamePlaceholder');
return res;
}
if (diyStore.value[index].resetBtn.text == '') {
res.code = false;
res.message = t('resetBtnNamePlaceholder');
return res;
}
return res
return res
}
defineExpose({})

View File

@ -1,26 +1,26 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
todo 此处编写表格组件的属性
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
todo 此处编写表格组件的属性
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -34,7 +34,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
// todo
// todo
return res
}
defineExpose({})

View File

@ -1,66 +1,67 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-input v-model.trim="diyStore.editComponent.field.default" :placeholder="t('defaultValuePlaceholder')" clearable maxlength="18" show-word-limit />
</el-form-item>
<el-form-item :label="t('rowCount')">
<el-input v-model.trim="diyStore.editComponent.rowCount" :placeholder="t('rowCountPlaceholder')" clearable maxlength="2" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item>
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('defaultValue') }}</span>
<el-tooltip effect="light" :content="t('defaultValueTips')" placement="top">
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-input v-model.trim="diyStore.editComponent.field.default"
:placeholder="t('defaultValuePlaceholder')" clearable maxlength="18" show-word-limit />
</el-form-item>
<el-form-item :label="t('rowCount')">
<el-input v-model.trim="diyStore.editComponent.rowCount" :placeholder="t('rowCountPlaceholder')" clearable maxlength="2" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!--<el-form label-width="100px" class="px-[10px]">
<el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('隐私保护') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>会自动将提交的个人信息做加密展示</p>
<p>适用于公开展示收集的数据且不暴露用户隐私</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
<div class="text-sm text-gray-400">{{ t('提交后自动隐藏文本,仅管理员可查看') }}</div>
</el-form-item>
</el-form>-->
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!--<el-form label-width="100px" class="px-[10px]">
<el-form-item class="display-block">
<template #label>
<div class="flex items-center">
<span class="mr-[3px]">{{ t('隐私保护') }}</span>
<el-tooltip effect="light" placement="top">
<template #content>
<p>会自动将提交的个人信息做加密展示</p>
<p>适用于公开展示收集的数据且不暴露用户隐私</p>
</template>
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</div>
</template>
<el-switch v-model="diyStore.editComponent.field.privacyProtection" />
<div class="text-sm text-gray-400">{{ t('提交后自动隐藏文本,仅管理员可查看') }}</div>
</el-form-item>
</el-form>-->
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -74,7 +75,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
// todo
// todo
return res
}
defineExpose({})

View File

@ -1,86 +1,88 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('startTime') }}</h3>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.start.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.start.defaultControl"/>
</el-form-item>
<el-form-item v-if="diyStore.editComponent.start.defaultControl">
<el-radio-group v-model="diyStore.editComponent.start.timeWay">
<el-radio label="current">{{ t('currentTime') }}</el-radio>
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="diyStore.editComponent.start.defaultControl && diyStore.editComponent.start.timeWay == 'diy'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('startTime') }}</h3>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.start.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.start.defaultControl" />
</el-form-item>
<el-form-item v-if="diyStore.editComponent.start.defaultControl">
<el-radio-group v-model="diyStore.editComponent.start.timeWay">
<el-radio label="current">{{ t('currentTime') }}</el-radio>
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="diyStore.editComponent.start.defaultControl && diyStore.editComponent.start.timeWay == 'diy'">
<el-time-picker v-model="diyStore.editComponent.field.default.start.date" :placeholder="t('startTimePlaceholder')" format="HH:mm" value-format="HH:mm" @change="startTimePickerChange" />
</el-form-item>
</el-form>
</div>
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('endTime') }}</h3>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.end.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.end.defaultControl" />
</el-form-item>
<el-form-item v-if="diyStore.editComponent.end.defaultControl">
<el-radio-group v-model="diyStore.editComponent.end.timeWay">
<el-radio label="current">{{ t('currentTime') }}</el-radio>
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="diyStore.editComponent.end.defaultControl && diyStore.editComponent.end.timeWay == 'diy'">
<el-time-picker :disabled-hours="disabledHours" :disabled-minutes="disabledMinutes" v-model="diyStore.editComponent.field.default.end.date" :placeholder="t('endTimePlaceholder')" format="HH:mm" value-format="HH:mm" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('endTime') }}</h3>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.end.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.end.defaultControl" />
</el-form-item>
<el-form-item v-if="diyStore.editComponent.end.defaultControl">
<el-radio-group v-model="diyStore.editComponent.end.timeWay">
<el-radio label="current">{{ t('currentTime') }}</el-radio>
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="diyStore.editComponent.end.defaultControl && diyStore.editComponent.end.timeWay == 'diy'">
<el-time-picker :disabled-hours="disabledHours" :disabled-minutes="disabledMinutes" v-model="diyStore.editComponent.field.default.end.date" :placeholder="t('endTimePlaceholder')" format="HH:mm" value-format="HH:mm" />
</el-form-item>
</el-form>
</div>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
</div>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('textStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="18" />
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.fontWeight">
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor" />
</el-form-item>
</el-form>
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('textStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="diyStore.editComponent.fontSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="12" :max="18" />
</el-form-item>
<el-form-item :label="t('textFontWeight')">
<el-radio-group v-model="diyStore.editComponent.fontWeight">
<el-radio :label="'normal'">{{ t('fontWeightNormal') }}</el-radio>
<el-radio :label="'bold'">{{ t('fontWeightBold') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="diyStore.editComponent.textColor" />
</el-form-item>
</el-form>
</div>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
import { t } from '@/lang'
import { ref,onMounted } from 'vue'
import { ref, onMounted } from 'vue'
import useDiyStore from '@/stores/modules/diy'
const diyStore = useDiyStore()
@ -96,25 +98,25 @@ diyStore.editComponent.verify = (index: number) => {
const hours = String(today.getHours()).padStart(2, '0');
const minutes = String(today.getMinutes()).padStart(2, '0');
if(diyStore.editComponent.start.timeWay == 'current'){
starTime = `${hours}:${minutes}`;
if (diyStore.editComponent.start.timeWay == 'current') {
starTime = `${ hours }:${ minutes }`;
}
if(diyStore.editComponent.end.timeWay == 'current'){
endTime = `${hours}:${minutes}`;
if (diyStore.editComponent.end.timeWay == 'current') {
endTime = `${ hours }:${ minutes }`;
}
if(diyStore.editComponent.start.defaultControl && starTime == ''){
if (diyStore.editComponent.start.defaultControl && starTime == '') {
res.code = false
res.message = t('startTimeTips')
return res
}
if(diyStore.editComponent.end.defaultControl && endTime == ''){
if (diyStore.editComponent.end.defaultControl && endTime == '') {
res.code = false
res.message = t('endTimeTips')
return res
}
if(diyStore.editComponent.start.defaultControl && diyStore.editComponent.end.defaultControl && timeInvertSecond(starTime) > timeInvertSecond(endTime)){
if (diyStore.editComponent.start.defaultControl && diyStore.editComponent.end.defaultControl && timeInvertSecond(starTime) > timeInvertSecond(endTime)) {
res.code = false
res.message = t('startEndTimeTips')
return res
@ -122,28 +124,26 @@ diyStore.editComponent.verify = (index: number) => {
return res
}
onMounted(() => {
const today = new Date();
const hours = String(today.getHours()).padStart(2, '0');
const minutes = String(today.getMinutes()).padStart(2, '0');
if(!diyStore.editComponent.field.default.start.date){
diyStore.editComponent.field.default.start.date = `${hours}:${minutes}`;
diyStore.editComponent.field.default.start.timestamp = timeInvertSecond(`${hours}:${minutes}`);
if (!diyStore.editComponent.field.default.start.date) {
diyStore.editComponent.field.default.start.date = `${ hours }:${ minutes }`;
diyStore.editComponent.field.default.start.timestamp = timeInvertSecond(`${ hours }:${ minutes }`);
}
if(!diyStore.editComponent.field.default.end.date){
if (!diyStore.editComponent.field.default.end.date) {
let endDate = new Date();
endDate.setHours(today.getHours(), today.getMinutes() + 10, 0, 0); // 10
const endHours = String(endDate.getHours()).padStart(2, '0');
const endMinutes = String(endDate.getMinutes()).padStart(2, '0');
diyStore.editComponent.field.default.end.date = `${endHours}:${endMinutes}`;
diyStore.editComponent.field.default.end.timestamp = timeInvertSecond(`${endHours}:${endMinutes}`);
diyStore.editComponent.field.default.end.date = `${ endHours }:${ endMinutes }`;
diyStore.editComponent.field.default.end.timestamp = timeInvertSecond(`${ endHours }:${ endMinutes }`);
}
});
//
const startTimePickerChange = (e) => {
diyStore.editComponent.field.default.start.timestamp = timeInvertSecond(e);
@ -152,24 +152,24 @@ const startTimePickerChange = (e) => {
const date = new Date();
date.setHours(parseInt(startTimeArr[0]), parseInt(startTimeArr[1]), 0, 0);
date.setMinutes(date.getMinutes() + 10);
const updatedEndTime = `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
const updatedEndTime = `${ String(date.getHours()).padStart(2, '0') }:${ String(date.getMinutes()).padStart(2, '0') }`;
diyStore.editComponent.field.default.end.date = updatedEndTime;
diyStore.editComponent.field.default.end.timestamp = timeInvertSecond(updatedEndTime);
}
//
const endTimePickerChange = (e)=>{
const endTimePickerChange = (e) => {
diyStore.editComponent.field.default.end.timestamp = timeInvertSecond(e);
}
const disabledHours = () => {
let timeArr = diyStore.editComponent.field.default.start.date.split(":")
return makeRange(0,timeArr[0]);
return makeRange(0, timeArr[0]);
}
const disabledMinutes = (hour: number) => {
let timeArr = diyStore.editComponent.field.default.start.date.split(":")
return makeRange(0,timeArr[1]);
return makeRange(0, timeArr[1]);
}
const makeRange = (start: number, end: number) => {
@ -180,16 +180,16 @@ const makeRange = (start: number, end: number) => {
return result
}
const timeInvertSecond = (time:any)=>{
const timeInvertSecond = (time: any) => {
let arr = time.split(":");
let num = 0;
if(arr[0]){
if (arr[0]) {
num += arr[0] * 60 * 60;
}
if(arr[1]){
if (arr[1]) {
num += arr[1] * 60;
}
if(arr[2]){
if (arr[2]) {
num += arr[2];
}
return num;

View File

@ -1,47 +1,47 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.defaultControl" @change="changeDateDefaultControl" />
</el-form-item>
<el-form-item v-if="diyStore.editComponent.defaultControl">
<el-radio-group v-model="diyStore.editComponent.timeWay">
<el-radio label="current">{{ t('currentTime') }}</el-radio>
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="diyStore.editComponent.defaultControl && diyStore.editComponent.timeWay == 'diy'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
<el-form-item :label="t('defaultValue')">
<el-switch v-model="diyStore.editComponent.defaultControl" @change="changeDateDefaultControl" />
</el-form-item>
<el-form-item v-if="diyStore.editComponent.defaultControl">
<el-radio-group v-model="diyStore.editComponent.timeWay">
<el-radio label="current">{{ t('currentTime') }}</el-radio>
<el-radio label="diy">{{ t('diyTime') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="diyStore.editComponent.defaultControl && diyStore.editComponent.timeWay == 'diy'">
<el-time-picker v-model="diyStore.editComponent.field.default" :placeholder="t('timePlaceholder')" format="HH:mm" value-format="HH:mm" />
</el-form-item>
</el-form>
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
import { t } from '@/lang'
import { ref,watch,onMounted } from 'vue'
import { ref, watch, onMounted } from 'vue'
import useDiyStore from '@/stores/modules/diy'
const diyStore = useDiyStore()
@ -54,32 +54,32 @@ diyStore.editComponent.verify = (index: number) => {
}
onMounted(() => {
//
if (!diyStore.editComponent.field.default) {
const today = new Date();
const hours = String(today.getHours()).padStart(2, '0');
const minutes = String(today.getMinutes()).padStart(2, '0');
diyStore.editComponent.field.default = `${hours}:${minutes}`;
}
});
const changeDateDefaultControl = (val: any) => {
if (val) {
const today = new Date();
const hours = String(today.getHours()).padStart(2, '0');
const minutes = String(today.getMinutes()).padStart(2, '0');
diyStore.editComponent.field.default = `${hours}:${minutes}`;
}
}
watch(
() => diyStore.editComponent.timeWay,
(newVal) => {
//
if (!diyStore.editComponent.field.default) {
const today = new Date();
const hours = String(today.getHours()).padStart(2, '0');
const minutes = String(today.getMinutes()).padStart(2, '0');
diyStore.editComponent.field.default = `${hours}:${minutes}`;
}
diyStore.editComponent.field.default = `${ hours }:${ minutes }`;
}
});
const changeDateDefaultControl = (val: any) => {
if (val) {
const today = new Date();
const hours = String(today.getHours()).padStart(2, '0');
const minutes = String(today.getMinutes()).padStart(2, '0');
diyStore.editComponent.field.default = `${ hours }:${ minutes }`;
}
}
watch(
() => diyStore.editComponent.timeWay,
(newVal) => {
const today = new Date();
const hours = String(today.getHours()).padStart(2, '0');
const minutes = String(today.getMinutes()).padStart(2, '0');
diyStore.editComponent.field.default = `${ hours }:${ minutes }`;
}
);
defineExpose({})

View File

@ -1,30 +1,30 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('上传方式')">
<el-radio-group v-model="diyStore.editComponent.uploadMode">
<el-radio label="shoot_and_album">{{ t('拍摄和相册') }}</el-radio>
<el-radio label="shoot_only">{{ t('只允许拍摄') }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]">
<el-form-item :label="t('上传方式')">
<el-radio-group v-model="diyStore.editComponent.uploadMode">
<el-radio label="shoot_and_album">{{ t('拍摄和相册') }}</el-radio>
<el-radio label="shoot_only">{{ t('只允许拍摄') }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>

View File

@ -1,30 +1,30 @@
<template>
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 内容 -->
<div class="content-wrap" v-show="diyStore.editTab == 'content'">
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 字段内容设置 -->
<slot name="field"></slot>
<el-form label-width="100px" class="px-[10px]" @submit.prevent>
<el-form-item :label="t('formPlaceholder')">
<el-input v-model.trim="diyStore.editComponent.placeholder" :placeholder="t('formPlaceholderTips')" clearable maxlength="15" show-word-limit />
</el-form-item>
</el-form>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
<!-- 表单组件 其他设置 -->
<slot name="other"></slot>
</div>
</div>
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 样式 -->
<div class="style-wrap" v-show="diyStore.editTab == 'style'">
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 表单组件 字段样式 -->
<slot name="style-field"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
<!-- 组件样式 -->
<slot name="style"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
@ -38,7 +38,7 @@ diyStore.editComponent.ignore = ['componentBgUrl'] // 忽略公共属性
//
diyStore.editComponent.verify = (index: number) => {
const res = { code: true, message: '' }
// todo
// todo
return res
}
defineExpose({})

View File

@ -0,0 +1,177 @@
<template>
<div>
<el-form :inline="true" :model="tableData.searchParam" ref="searchFormRef">
<el-form-item :label="t('formSelectContentTitle')" prop="title" class="form-item-wrap">
<el-input v-model.trim="tableData.searchParam.title" :placeholder="t('formSelectContentTitlePlaceholder')" />
</el-form-item>
<el-form-item :label="t('formSelectContentTypeName')" prop="type" class="form-item-wrap">
<el-select v-model="tableData.searchParam.type" :placeholder="t('formSelectContentTypeNamePlaceholder')">
<el-option :label="t('formSelectContentTypeAll')" value="" />
<el-option v-for="(item, key) in formType" :label="item.title" :value="key" :key="key" />
</el-select>
</el-form-item>
<el-form-item class="form-item-wrap">
<el-button type="primary" @click="loadList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
<el-table :data="tableData.data" size="large" ref="tableRef" v-loading="tableData.loading">
<template #empty>
<span>{{ !tableData.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column min-width="7%">
<template #default="{ row }">
<el-checkbox v-model="row.checked" @change="handleCheckChange($event,row)" />
</template>
</el-table-column>
<el-table-column prop="page_title" :label="t('formSelectContentTitle')" min-width="65%" />
<el-table-column prop="type_name" :label="t('formSelectContentTypeName')" min-width="25%" />
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.limit"
layout="total, sizes, prev, pager, next, jumper" :total="tableData.total"
@size-change="loadList()" @current-change="loadList" />
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, nextTick } from 'vue'
import { t } from '@/lang'
import { getFormType, getDiyFormSelectPageList } from '@/app/api/diy_form'
import { FormInstance, ElMessage } from "element-plus";
const prop = defineProps({
formId: {
type: [Number, String],
default: 0
}
})
const formType: any = reactive({}) //
const searchFormRef = ref<FormInstance>()
const tableRef = ref();
const tableData: any = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
title: '',
type: '',
verify_form_ids: []
}
})
//
const selectData: any = reactive({
form_id: prop.formId
})
//
const loadList = (page: number = 1) => {
tableData.loading = true
tableData.page = page
if (selectData.form_id) {
tableData.searchParam.verify_form_ids = [selectData.form_id]
}
getDiyFormSelectPageList({
page: tableData.page,
limit: tableData.limit,
...tableData.searchParam
}).then(res => {
tableData.loading = false
tableData.data = res.data.data
tableData.data.forEach((item: any) => {
item.checked = item.form_id == selectData.form_id
})
tableData.total = res.data.total
setGoodsSelected()
}).catch(() => {
tableData.loading = false
})
}
//
const loadFormType = (addon = '') => {
getFormType({}).then(res => {
for (let key in formType) {
delete formType[key];
}
for (const key in res.data) {
formType[key] = res.data[key]
}
})
}
loadFormType();
loadList()
const handleCheckChange = (isSelect: any, row: any) => {
if (isSelect) {
selectData.form_id = row.form_id
} else {
selectData.form_id = 0 //
}
setGoodsSelected()
}
//
const setGoodsSelected = () => {
nextTick(() => {
for (let i = 0; i < tableData.data.length; i++) {
tableData.data[i].checked = false
if (selectData.form_id == tableData.data[i].form_id) {
tableData.data[i].checked = true
Object.assign(selectData, tableData.data[i])
}
}
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadList()
}
const getData = () => {
if (selectData.form_id == 0) {
ElMessage({
type: 'warning',
message: `${ t('formSelectContentTips') }`
})
return;
}
return {
name: 'DIY_FORM',
title: selectData.page_title,
url: `/app/pages/index/diy_form?form_id=${ selectData.form_id }`,
action: '',
formId: selectData.form_id
}
}
defineExpose({
getData
})
</script>
<style lang="scss" scoped>
.form-item-wrap {
margin-right: 10px !important;
margin-bottom: 10px !important;
&.last-child {
margin-right: 0 !important;
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div>
<el-dialog v-model="showDialog" :title="t('submirSuccess')" width="850px" :close-on-press-escape="true" :destroy-on-close="true" :close-on-click-modal="false">
<el-dialog v-model="showDialog" :title="t('submitSuccess')" width="850px" :close-on-press-escape="true" :destroy-on-close="true" :close-on-click-modal="false">
<div class="flex flex-1 mt-[24px] mx-[24px] mb-0">
<div class="preview-wrap">
@ -119,7 +119,7 @@
<el-icon>
<QuestionFilled color="#999999" />
</el-icon>
</el-tooltip>
</el-tooltip>
</el-radio>
<el-radio label="submission_time" class="!block">
<span class="mr-[3px]">{{ t('submissionTime') }}</span>

View File

@ -63,7 +63,7 @@
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-if="row.type=='DIY_FORM'">
<el-button type="primary" class="w-full" link @click="submitConfigEvent(row)">{{ t('submirSuccess') }}</el-button>
<el-button type="primary" class="w-full" link @click="submitConfigEvent(row)">{{ t('submitSuccess') }}</el-button>
</el-dropdown-item>
<el-dropdown-item>
<el-button type="primary" class="w-full" link @click="writeConfigEvent(row)">{{ t('writeSet') }}</el-button>

View File

@ -87,7 +87,7 @@
<el-table-column :label="t('applicationForWithdrawalAmount')" align="center" min-width="120" />
<el-table-column :label="t('actualTransferAmount')" align="center" min-width="120" />
<el-table-column :label="t('cashOutCommission')" align="center" min-width="110" />
<el-table-column :label="t('cashOutStatus')" align="center" min-width="100" />
<el-table-column :label="t('cashOutStatus')" align="center" min-width="150" />
<el-table-column :label="t('applyTime')" align="center" min-width="160" />
<el-table-column :label="t('auditTime')" align="center" min-width="160" />
<el-table-column :label="t('transferTime')" align="center" min-width="160" />
@ -103,7 +103,7 @@
<div class="flex items-center cursor-pointer " @click="toMember(row.member.member_id)">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<div class="flex flex flex-col items-baseline" style="width: calc(100% - 60px);">
<div class="flex flex-col items-baseline" style="width: calc(100% - 60px);">
<span class="w-[100%] truncate text-left">{{ row.member.nickname || row.member.username || '' }}</span>
<span class="w-[100%] truncate">{{ row.member.mobile || '' }}</span>
</div>
@ -136,6 +136,14 @@
<span>{{ t('bankAccount') }}{{ row.transfer_account }}</span>
<span>{{ t('bankName') }}{{ row.transfer_bank }}</span>
</div>
<div class="flex items-center" v-else-if="row.transfer_type=='wechatpay'">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<div class="flex flex-col items-baseline" style="width: calc(100% - 60px);">
<span class="w-[100%] truncate text-left">{{ row.member.nickname || row.member.username || '' }}</span>
<span class="w-[100%] truncate">{{ row.member.mobile || '' }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="apply_money" min-width="120" align="center" />
@ -144,7 +152,12 @@
<el-table-column prop="service_money" align="center" min-width="110" />
<el-table-column prop="status_name" align="center" min-width="100" />
<el-table-column prop="status_name" align="center" min-width="150">
<template #default="{ row }">
<div>{{ row.status_name }}</div>
<div v-if="row.status == 2 && row.transfer_type == 'wechatpay'" class="text-[12px] text-[var(--el-color-success)]">(等待用户收款)</div>
</template>
</el-table-column>
<el-table-column min-width="160" align="center">
<template #default="{ row }">
@ -166,9 +179,11 @@
<el-table-column align="right" fixed="right" width="120">
<template #default="{ row }">
<el-button v-for="(item, index) in operationBtn[row.status.toString()].value" :key="index + 'a'"
@click="fnProcessing(operationBtn[row.status.toString()].clickArr[index], row)"
type="primary" link>{{ item }}</el-button>
<el-button type="primary" link @click="successfulAuditFn(row)" v-if="row.status == 1"> {{ t('successfulAudit') }}</el-button>
<el-button type="primary" link @click="auditFailureFn(row)" v-if="row.status == 1"> {{ t('auditFailure') }}</el-button>
<el-button type="primary" link @click="memberCancelFn(row)" v-if="row.status == 1 || row.status == 2 || row.status == 4"> {{ t('cancelWithdrawal') }}</el-button>
<el-button type="primary" link @click="transferFn(row)" v-if="row.status == 2 && row.transfer_type !== 'wechatpay'"> {{ t('transfer') }}</el-button>
<el-button type="primary" link @click="detailFn(row.id)"> {{ t('detail') }}</el-button>
<el-button type="primary" link @click="handleRemark(row)"> {{ t('remark') }}</el-button>
</template>
</el-table-column>
@ -284,6 +299,11 @@
<div class="input-width"> {{ cashOutInfo.transfer.transfer_remark }} </div>
</el-form-item>
</el-col>
<el-col :span="12" v-if="cashOutInfo.refuse_reason">
<el-form-item :label="t('remark')">
<div class="input-width"> {{ cashOutInfo.refuse_reason }} </div>
</el-form-item>
</el-col>
</el-row>
</el-form>
@ -482,11 +502,10 @@
<script lang="ts" setup>
import { reactive, ref, computed } from 'vue'
import { t } from '@/lang'
import { getCashOutList, getTransfertype, memberTransfer, memberAudit, getCashOutDetail, getCashOutStatusList, getCashOutStat, memberRemark, memberCheck } from '@/app/api/member'
import { getCashOutList, getTransfertype, memberTransfer, memberAudit, getCashOutDetail, getCashOutStatusList, getCashOutStat, memberRemark, memberCheck, memberCancel } from '@/app/api/member'
import { img } from '@/utils/common'
import { ElMessageBox, FormInstance, FormRules } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
import { AnyObject } from '@/types/global'
const cashOutStatusList = ref([])
const checkStatusList = async () => {
@ -496,32 +515,6 @@ checkStatusList()
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const operationBtn = ref<AnyObject>({
1: {
value: [t('successfulAudit'), t('auditFailure'), t('detail')],
clickArr: ['successfulAuditFn', 'auditFailureFn', 'detailFn']
},
2: {
value: [t('transfer'), t('detail')],
clickArr: ['transferFn', 'detailFn']
},
3: {
value: [t('detail')],
clickArr: ['detailFn']
},
4: {
value: [t('detail')],
clickArr: ['detailFn']
},
'-1': {
value: [t('detail')],
clickArr: ['detailFn']
},
'-2': {
value: [t('detail')],
clickArr: ['detailFn']
}
})
//
const formRules = reactive<FormRules>({})
@ -592,48 +585,14 @@ const loadOrderList = (page: number = 1) => {
}
loadOrderList()
//
const auditFailure = ref({ refuse_reason: '', id: 0, action: 0 })
const auditShowDialog = ref(false)
const fnProcessing = (type: string, data: any) => {
const obj = {}
if (['successfulAuditFn', 'auditFailureFn'].includes(type)) {
obj.id = data.id
if (type == 'successfulAuditFn') {
obj.action = 'agree'
curData.value = data
auditPassShowDialog.value = true
} else {
obj.action = 'refuse'
auditFailure.value = Object.assign(auditFailure.value, obj)
auditShowDialog.value = true
}
} else if (type == 'transferFn') {
if (data.transfer_type == 'wechatpay') {
obj.id = data.id
ElMessageBox.confirm(`${t('isTransfer')}`, `${t('transfer')}`).then(() => {
transferFn(obj)
})
} else {
transferData.value = data
formTransfer.id = data.id
transferShowDialog.value = true
}
} else if (type == 'checkFn') {
checkFn(data.id)
} else {
detailFn(data.id)
}
}
/**
* 转账
* @param data
*/
const transferData = ref({})
const transferData = ref<any>({})
const transferShowDialog = ref(false)
const formTransferRef = ref<FormInstance>()
const formTransfer = reactive({
const formTransfer = reactive<any>({
id: 0,
transfer_voucher: '',
transfer_remark: ''
@ -646,23 +605,25 @@ const formTransferRules = computed(() => {
}
})
const transferFn = (data:any) => {
transferData.value = data
formTransfer.id = data.id
transferShowDialog.value = true
}
const handleTransfer = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(async (valid) => {
if (valid) {
transferFn(formTransfer)
memberTransfer({ ...formTransfer }).then(res => {
transferShowDialog.value = false
loadOrderList()
}).catch(() => {
transferShowDialog.value = false
loadOrderList()
})
}
})
}
const transferFn = (data:any) => {
memberTransfer({ ...data }).then(res => {
transferShowDialog.value = false
loadOrderList()
}).catch(() => {
transferShowDialog.value = false
loadOrderList()
})
}
/**
* 详情
@ -696,6 +657,12 @@ const detailFn = (id:any) => {
const auditPassShowDialog = ref(false)
const curData = ref<any>({})
//
const successfulAuditFn = (data: any) => {
curData.value = data
auditPassShowDialog.value = true
}
const handlePass = () => {
const obj = {
id: curData.value.id,
@ -703,24 +670,55 @@ const handlePass = () => {
}
cashOutAuditFn(obj)
}
/**
* 拒绝审核
*/
const auditFailure = ref({ refuse_reason: '', id: 0, action: '' })
const auditShowDialog = ref(false)
const loading = ref(false)
const auditFailureFn = (data: any) => {
auditFailure.value.id = data.id
auditFailure.value.action = 'refuse'
auditShowDialog.value = true
}
const confirm = () => {
auditShowDialog.value = false
cashOutAuditFn(auditFailure.value)
}
const repeat = ref(false)
const cashOutAuditFn = (data:any) => {
if (repeat.value) return
repeat.value = true
memberAudit({
...data
}).then(res => {
repeat.value = false
auditPassShowDialog.value = false
loadOrderList()
}).catch(() => {
repeat.value = false
auditPassShowDialog.value = false
loadOrderList()
})
}
/**
* 拒绝审核
*/
const confirm = () => {
auditShowDialog.value = false
cashOutAuditFn(auditFailure.value)
//
const memberCancelFn = (data: any) => {
ElMessageBox.confirm(t('cancelTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(() => {
memberCancel({ id: data.id }).then((res) => {
loadOrderList()
})
})
}
/**

View File

@ -144,27 +144,27 @@ const formRules = reactive<FormRules>({
{ required: true, message: t('daySignAwardPlaceholder'), trigger: 'change' }
],
sign_period:[{
required: true,
trigger: 'blur',
validator: (rule: any, value: any, callback: any) => {
if (value === null || value === '') {
callback(t('signPeriodTip'))
}else if (isNaN(value) || !regExp.number.test(value)) {
callback(t('signPeriodLimitTips'))
}else if (value < 2 || value > 365) {
callback(t('signPeriodMustZeroTips'))
} else {
callback();
}
required: true,
trigger: 'blur',
validator: (rule: any, value: any, callback: any) => {
if (value === null || value === '') {
callback(t('signPeriodTip'))
}else if (isNaN(value) || !regExp.number.test(value)) {
callback(t('signPeriodLimitTips'))
}else if (value < 2 || value > 365) {
callback(t('signPeriodMustZeroTips'))
} else {
callback()
}
}
}],
}]
})
/**
* 签到奖励文本请求参数
*/
const contentData = reactive<Record<string, any>>({
gifts: [],
gifts: []
})
/**
@ -211,17 +211,16 @@ const setFormData = async () => {
if (formData.continue_award) {
formData.continue_award.forEach((item: any, index: number) => {
continueSignAwardTableData.data.push(cloneDeep(item))
contentData.gifts = [];
contentData.gifts = []
const val = cloneDeep(item)
delete val['continue_sign'];
delete val['continue_tag'];
delete val['receive_limit'];
delete val['receive_num'];
delete val['continue_sign']
delete val['continue_tag']
delete val['receive_limit']
delete val['receive_num']
contentData.gifts = val
@ -239,7 +238,7 @@ setFormData()
const daySignAwardText = ref([])
const setMemberBenefitsContent = async () => {
const data = await (await getMemberGiftsContent(contentData)).data
daySignAwardText.value = [];
daySignAwardText.value = []
Object.values(data).forEach((el: any) => {
daySignAwardText.value.push(el)
})
@ -254,7 +253,7 @@ const setMemberBenefitsContent = async () => {
*/
const setMemberBenefitsContents = async (content: any, item: any, index: number = 0, tag = 0) => {
const data = await (await getMemberGiftsContent(content)).data
continueSignAwardText.value = [];
continueSignAwardText.value = []
Object.values(data).forEach((el: any) => {
continueSignAwardText.value.push(el)
})
@ -276,7 +275,6 @@ const setMemberBenefitsContents = async (content: any, item: any, index: number
isEdit = false
editIndex = 0
}
/**
@ -313,6 +311,9 @@ const setDaySignAward = async () => {
if (!formData.day_award.hasOwnProperty('balance') && !formData.day_award.hasOwnProperty('point') && formData.day_award.shop_coupon.is_use == 0) {
formData.day_award = ''
}
if (formData.day_award.hasOwnProperty('balance') && formData.day_award.balance.is_use == 1) {
formData.day_award.balance.money = Number(formData.day_award.balance.money)
}
contentData.gifts = formData.day_award
setMemberBenefitsContent()
@ -338,8 +339,8 @@ const continueSignAwardSet = () => {
* 修改连签奖励设置页
*/
const continueSignAwardModify = (flag: boolean, index: any) => {
isEdit = flag;
editIndex = index;
isEdit = flag
editIndex = index
continue_award.value = formData.continue_award[index]
continueSignDialog.value = true
@ -356,18 +357,20 @@ const setContinueSignAward = async () => {
if (!continue_award.value.hasOwnProperty('balance') && !continue_award.value.hasOwnProperty('point') && continue_award.value.shop_coupon.is_use == 0) {
continue_award.value = ''
}
if (continue_award.value.hasOwnProperty('balance') && continue_award.value.balance.is_use == 1) {
continue_award.value.balance.money = Number(continue_award.value.balance.money)
}
if (Object.keys(continue_award.value).length > 0) {
const val = cloneDeep(continue_award.value)
delete val['continue_sign'];
delete val['continue_tag'];
delete val['receive_limit'];
delete val['receive_num'];
delete val['continue_sign']
delete val['continue_tag']
delete val['receive_limit']
delete val['receive_num']
contentData.gifts = val
let index = 0;
let index = 0
if (formData.continue_award.length > 0) {
index = formData.continue_award.length - 1
}
@ -394,7 +397,7 @@ const deleteContinueSignAwardEvent = (index: number) => {
* 使用默认说明
*/
const defaultExplainEvent = () => {
formData.rule_explain = t('ruleExplainDefault');
formData.rule_explain = t('ruleExplainDefault')
}
</script>

View File

@ -38,7 +38,7 @@
<div class="flex items-center cursor-pointer" @click="toMember(row.member_id)">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<div class="flex flex flex-col">
<div class="flex flex-col">
<span>{{ row.member.nickname || '' }}</span>
</div>
</div>

View File

@ -19,7 +19,7 @@
<div class="flex items-center cursor-pointer " @click="toMember(row.member.member_id)" v-if="row.member">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<div class="flex flex flex-col">
<div class="flex flex-col">
<span>{{ row.member.nickname || '' }}</span>
<span>{{ row.member.mobile || '' }}</span>
</div>

View File

@ -90,7 +90,7 @@
<div class="flex items-center cursor-pointer" @click="toMember(row.member_id)">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<div class="flex flex flex-col">
<div class="flex flex-col">
<span>{{ row.member.nickname || '' }}</span>
</div>
</div>

View File

@ -93,7 +93,7 @@
<div class="flex items-center cursor-pointer" @click="toMember(row.member_id)">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<div class="flex flex flex-col">
<div class="flex flex-col">
<span>{{ row.member.nickname || '' }}</span>
</div>
</div>

View File

@ -237,7 +237,7 @@
</div>
</div>
</div>
<point-edit ref="pointDialog" @complete="getMemberInfoFn" />
<balance-edit ref="balanceDialog" @complete="getMemberInfoFn" />
<edit-member ref="editMemberDialog" @complete="getMemberInfoFn()" />
@ -245,33 +245,24 @@
</template>
<script lang="ts" setup>
import { reactive, ref, computed } from 'vue'
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { addMember, getMemberList, getMemberNo, getMemberInfo } from '@/app/api/member'
import { getMemberInfo } from '@/app/api/member'
import { FormInstance, ElMessage } from 'element-plus'
import { ArrowLeft } from '@element-plus/icons-vue'
import { useRouter, useRoute } from 'vue-router'
import { img, filterNumber } from '@/utils/common'
import { useRouter } from 'vue-router'
import { img } from '@/utils/common'
import PointEdit from '@/app/views/member/components/member-point-edit.vue'
import BalanceEdit from '@/app/views/member/components/member-balance-edit.vue'
import EditMember from '@/app/views/member/components/edit-member.vue'
import useAppStore from '@/stores/modules/app'
const showDialog = ref(false)
const loading = ref(false)
const repeat = ref(false)
let popTitle: string = '会员详情'
let memberNo: string = ''
let id = '';
const route = useRoute()
const router = useRouter()
const emit = defineEmits(['load'])
const nickname_name_input = ref(true)
const password_input = ref(true)
const password_copy_input = ref(true)
const handleClose = (done: () => void) => {
showDialog.value = false;
}
@ -290,8 +281,6 @@ const initialFormData = {
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
const pointDialog: Record<string, any> | null = ref(null)
const balanceDialog: Record<string, any> | null = ref(null)
const editMemberDialog: Record<string, any> | null = ref(null)

View File

@ -5,7 +5,7 @@
<el-checkbox v-model="formData.is_use" :true-label="1" :false-label="0" label="" size="large" />
<span class="ml-[10px] el-form-item__label"></span>
<div class="w-[70px]">
<el-input v-model.trim="formData.money" :maxlength="5" clearable />
<el-input v-model.trim="formData.money" :maxlength="5" clearable :disabled="formData.is_use == 0" />
</div>
<span class="ml-[15px] el-form-item__label">元红包</span>
</div>

View File

@ -4,7 +4,7 @@
<el-checkbox v-model="formData.is_use" :true-label="1" :false-label="0" label="" size="large" />
<span class="ml-[10px] el-form-item__label"></span>
<div class="w-[70px]">
<el-input v-model.trim="formData.num" clearable />
<el-input v-model.trim="formData.num" clearable :disabled="formData.is_use == 0" />
</div>
<span class="ml-[15px] el-form-item__label">积分</span>
</el-form-item>

View File

@ -14,7 +14,7 @@
</el-form-item>
<el-form-item :label="t('adjustBalance')" prop="adjust">
<el-input-number v-model="formData.adjust" clearable :min="0" :max="999999" :placeholder="t('adjustPlaceholder')"/>
<el-input-number v-model="formData.adjust" clearable :min="0" :max="999999" :placeholder="t('adjustBalancePlaceholder')" @focus="formData.adjust = ''" class="!w-[200px]"/>
</el-form-item>
<el-form-item :label="t('memo')" prop="memo">

View File

@ -44,7 +44,7 @@
<div class="flex items-center cursor-pointer" @click="toMember(row.member_id)">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<div class="flex flex flex-col">
<div class="flex flex-col">
<span>{{ row.member.nickname || '' }}</span>
</div>
</div>

View File

@ -60,7 +60,7 @@
<img class="max-w-[50px] max-h-[50px]" v-if="row.headimg" :src="img(row.headimg)" alt="">
<img class="max-w-[50px] max-h-[50px]" v-else src="@/app/assets/images/member_head.png" alt="">
</div>
<div class="flex flex flex-col">
<div class="flex flex-col">
<span>{{ row.nickname || '' }}</span>
</div>
</div>

View File

@ -72,7 +72,7 @@
<div class="flex items-center cursor-pointer" @click="toMember(row.member_id)">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.member.headimg" :src="img(row.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<div class="flex flex flex-col">
<div class="flex flex-col">
<span>{{ row.member.nickname || '' }}</span>
</div>
</div>

View File

@ -229,9 +229,9 @@ import { t } from '@/lang'
import { img } from '@/utils/common'
import { useRoute, useRouter } from 'vue-router'
import { cloneDeep } from 'lodash-es'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ElMessageBox } from 'element-plus'
import usePosterStore from '@/stores/modules/poster'
import { initPoster,addPoster,editPoster,getPosterTemplate,getPreviewPoster } from '@/app/api/poster'
import { initPoster, addPoster, editPoster, getPosterTemplate, getPreviewPoster } from '@/app/api/poster'
const setLayout = inject('setLayout')
setLayout('decorate')
@ -249,8 +249,8 @@ if(route && route.query){
}
const backPath:any = route.query.back
const template = ref('');
const oldTemplate = ref('');
const template = ref('')
const oldTemplate = ref('')
const component = ref([])
const componentType: string[] = reactive([])
@ -268,39 +268,39 @@ const previewIframeStyle = (data: any)=>{
left: '',
right: '',
bottom: ''
};
style.transform = `rotate(${data.angle}deg)`;
style.zIndex = `${data.zIndex}`;
}
style.transform = `rotate(${data.angle}deg)`
style.zIndex = `${data.zIndex}`
switch(data.y) {
case 'top':
style.top = 0;
style.top = 0
break;
case 'center':
style.top = '50%';
style.transform = style.transform + ' translateY(-50%)';
style.top = '50%'
style.transform = style.transform + ' translateY(-50%)'
break;
case 'bottom':
style.bottom = 0;
style.bottom = 0
break;
default:
style.top = data.y + 'px';
style.top = data.y + 'px'
}
switch(data.x) {
case 'left':
style.left = 0;
style.left = 0
break;
case 'center':
style.left = '50%';
style.transform = style.transform + ' translateX(-50%)';
style.left = '50%'
style.transform = style.transform + ' translateX(-50%)'
break;
case 'right':
style.right = 0;
style.right = 0
break;
default:
style.left = data.x + 'px';
style.left = data.x + 'px'
}
// console.log(data.x,data.y)
return style;
return style
}
//
@ -341,14 +341,14 @@ const yAlignList = ref([
},
])
const alignChangeFn = (type: any,data: any)=>{
posterStore.editComponent[type] = data.className;
posterStore.editComponent[type] = data.className
}
//
const isChange = ref(true) // truefalse
const goBack = () => {
if (isChange.value) {
location.href = `${location.origin}${backPath}`;
location.href = `${location.origin}${backPath}`
router.push(backPath)
} else {
//
@ -362,7 +362,7 @@ const goBack = () => {
autofocus: false
}
).then(() => {
location.href = `${location.origin}${backPath}`;
location.href = `${location.origin}${backPath}`
}).catch(() => {
})
}
@ -390,6 +390,9 @@ const loadPosterTemplate = ()=> {
}).then(res => {
if (res.data) {
templatePoster.splice(0, templatePoster.length, ...res.data)
if (posterStore.id) {
template.value = templatePoster.findIndex((item:any) => item.type == posterStore.type)
}
}
})
}
@ -398,7 +401,7 @@ const loadPosterTemplate = ()=> {
watch(
() => template.value,
(newValue, oldValue) => {
oldTemplate.value = oldValue;
oldTemplate.value = oldValue
}
)
@ -413,51 +416,51 @@ const changeTemplatePoster = (index:any)=> {
}).then(() => {
posterStore.changeCurrentIndex(-99)
if (index !== '') {
let data = templatePoster[index].data;
posterStore.global = data.global;
let data = templatePoster[index].data
posterStore.global = data.global
if (data.value.length) {
posterStore.value = data.value
}
} else {
//
posterStore.init();
posterStore.init()
}
}).catch(() => {
//
template.value = oldTemplate.value;
});
template.value = oldTemplate.value
})
}else{
if (index !== '') {
let data = templatePoster[index].data;
posterStore.global = data.global;
let data = templatePoster[index].data
posterStore.global = data.global
if (data.value.length) {
posterStore.value = data.value
}
} else {
//
posterStore.init();
posterStore.init()
}
}
};
}
//
initPoster({
id: route.query.id,
type: route.query.type,
name: route.query.name
}).then( async (res:any)=>{
}).then(async (res:any) => {
const data = res.data
posterStore.init(); //
posterStore.init() //
posterStore.id = data.id;
posterStore.name = data.name;
posterStore.channel = data.channel;
posterStore.status = data.status;
posterStore.isDefault = data.is_default;
posterStore.addon = data.addon;
posterStore.type = data.type;
posterStore.typeName = data.poster_type.name;
posterStore.id = data.id
posterStore.name = data.name
posterStore.channel = data.channel
posterStore.status = data.status
posterStore.isDefault = data.is_default
posterStore.addon = data.addon
posterStore.type = data.type
posterStore.typeName = data.poster_type.name
if (data.value) {
const sources = data.value
@ -497,18 +500,18 @@ const save = (callback: any) => {
posterStore.value.forEach((item:any,index:any, originalArr:any)=> {
const box: any = document.getElementById(item.id)
if (box) {
item.width = box.offsetWidth;
item.height = box.offsetHeight;
item.width = box.offsetWidth
item.height = box.offsetHeight
if (item.type == 'draw') {
// [x,y]
let leftTop = [item.x * 1, item.y * 1]; //
let rightTop = [(item.x + item.width) * 1, item.y * 1]; //
let rightBottom = [(item.x + item.width) * 1, (item.y + item.height) * 1]; //
let leftBottom = [item.x * 1, (item.y + item.height) * 1]; //
item.points = [leftTop, rightTop, rightBottom, leftBottom];
let leftTop = [item.x * 1, item.y * 1] //
let rightTop = [(item.x + item.width) * 1, item.y * 1] //
let rightBottom = [(item.x + item.width) * 1, (item.y + item.height) * 1] //
let leftBottom = [item.x * 1, (item.y + item.height) * 1] //
item.points = [leftTop, rightTop, rightBottom, leftBottom]
}
}
delete item.verify;
delete item.verify
})
let data = {
@ -532,7 +535,7 @@ const save = (callback: any) => {
if (posterStore.id) {
isRepeat.value = false //
} else {
location.href = `${location.origin}${backPath}`;
location.href = `${location.origin}${backPath}`
}
if (callback) callback(res.data.id)
}
@ -554,8 +557,8 @@ const preview = () => {
type:posterStore.type
}).then(((res:any)=>{
if(res.data) {
previewPosterUrl.value = res.data;
previewDialogVisible.value = true;
previewPosterUrl.value = res.data
previewDialogVisible.value = true
}
isRepeat.value = false
}))

View File

@ -66,7 +66,7 @@
</el-card>
<!--添加海报-->
<el-dialog v-model="dialogVisible" :title="t('addPosterTitle')" width="350px">
<el-dialog v-model="dialogVisible" :title="t('addPosterTitle')" width="350px" destroy-on-close="true">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules">
<el-form-item :label="t('posterName')" prop="name">

View File

@ -33,7 +33,7 @@
</el-radio-group>
</el-form-item>
<el-form-item :label="t('transfer')" v-if="formData.is_open" class="items-baseline">
<!-- <el-form-item :label="t('transfer')" v-if="formData.is_open" class="items-baseline">
<div>
<el-radio-group v-model="formData.is_auto_transfer">
<el-radio label="0" size="large">{{t('manualTransfer')}}</el-radio>
@ -41,7 +41,7 @@
</el-radio-group>
<div class="text-[12px] text-[#999] leading-[24px]">{{ t('transferTips') }}</div>
</div>
</el-form-item>
</el-form-item> -->
<el-form-item :label="t('transferMode')" v-if="formData.is_open" class="items-baseline">
<div>
<el-checkbox-group v-model="formData.transfer_type" size="large">

View File

@ -10,22 +10,24 @@
<div class="mt-[20px]">
<div class="flex items-center bg">
<span class="p-[15px] w-[25%] text-[14px]">规则名称</span>
<span class="p-[15px] w-[50%] text-[14px]">规则详情</span>
<span class="p-[15px] w-[15%] text-[14px]">所属应用</span>
<span class="p-[15px] w-[35%] text-[14px]">规则详情</span>
<span class="p-[15px] w-[15%] text-[14px]">是否启用</span>
<span class="p-[15px] w-[10%] text-[14px]">操作</span>
</div>
<div v-for="(item, key) in rules" :key="key" class="flex items-center">
<span class="p-[15px] w-[25%] text-[14px]">{{ item.name }}</span>
<span class="p-[15px] w-[50%] text-[14px] text-[#666]">{{ formData[item.key] && formData[item.key].content ? formData[item.key].content : '--' }}</span>
<span class="p-[15px] w-[15%] text-[14px]">{{ item.addon_name }}</span>
<span class="p-[15px] w-[35%] text-[14px] text-[#666]">{{ rulesData[item.key] && rulesData[item.key].content ? rulesData[item.key].content : '--' }}</span>
<span class="p-[15px] w-[15%] text-[14px] text-[#666]">
<el-tag type="success" v-if="formData[item.key] && formData[item.key].is_use">已启用</el-tag>
<el-tag type="success" v-if="rulesData[item.key] && rulesData[item.key].is_use">已启用</el-tag>
<el-tag type="danger" v-else>未启用</el-tag>
</span>
<span class="p-[15px] w-[10%] text-[14px] text-[#666] text-[var(--el-color-primary)] cursor-pointer" @click="examineFn(key)">配置</span>
</div>
</div>
<el-dialog v-model="ruleDialog" :title="'规则配置'" width="600px" :close-on-press-escape="false" :destroy-on-close="true" :close-on-click-modal="false">
<el-dialog v-model="ruleDialog" :title="'规则配置'" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
<div v-for="(item, key) in rules" :key="key" class="pl-[60px]">
<component :is="item.component" v-model="formData[item.key]" ref="ruleRefs" v-if="item.component && currRule == key"/>
</div>
@ -48,11 +50,13 @@ import { useRoute } from 'vue-router'
import { t } from '@/lang'
import { getGrowthRuleConfig, setGrowthRuleConfig, getGrowthRuleDict } from '@/app/api/member'
import Test from '@/utils/test'
import { cloneDeep } from 'lodash-es'
const route = useRoute()
const pageName = route.meta.title
const rules = ref({})
const formData = ref({})
const rulesData = ref<any>({}) //
const formData = ref<any>({})
const ruleRefs = ref(null)
const loading = ref(true)
@ -66,7 +70,7 @@ getGrowthRuleDict().then(({ data }) => {
const ruleConfigFn = () => {
getGrowthRuleConfig().then(({ data }) => {
!Test.empty(data) && (formData.value = data)
!Test.empty(data) && (rulesData.value = data)
loading.value = false
}).catch(() => {
loading.value = false
@ -94,6 +98,7 @@ const ruleDialog = ref(false)
//
const currRule = ref('')
const examineFn = (key:string) => {
formData.value = cloneDeep(rulesData.value)
ruleDialog.value = true
currRule.value = key
}

View File

@ -33,7 +33,7 @@
</div>
</div>
<el-dialog v-model="ruleDialog" :title="'规则配置'" width="600px" :close-on-press-escape="false" :destroy-on-close="true" :close-on-click-modal="false">
<el-dialog v-model="ruleDialog" :title="'规则配置'" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
<div v-for="(item, key) in rules.grant" :key="key" class="pl-[60px]">
<component :is="item.component" v-model="formData.grant[item.key]" ref="ruleRefs" v-if="item.component && currRule == key"/>
</div>

View File

@ -8,7 +8,7 @@
</div>
<div class="mt-[20px]">
<el-alert :description="t('transferTips')" type="warning" show-icon>
<el-alert type="warning" show-icon>
<template #title>
<span class="!text-[14px]">{{ t('operationTip') }}</span>
</template>

View File

@ -0,0 +1,149 @@
<template>
<div class="main-container">
<el-card class="box-card mt-[15px] !border-none" shadow="never" v-for="(item, key) in screne" :key="key">
<div class="flex items-center mb-[20px]">
<h3 class="text-[14px] mr-[20px]">{{ item.name }}</h3>
<div class="flex items-center">
<span class="text-[14px] mr-[10px]">{{ t('transferSceneId') }}</span>
<div class="flex items-center">
<el-input v-model.trim="item.scene_id" maxlength="5" class="!w-[60px]" :disabled="item.disabled" @blur="handleInput($event,key,item)" :ref="(el: any) =>{ if(el) inputRefs[key] = el }" v-show="!item.disabled"/>
<div v-show="item.disabled">{{item.scene_id ? item.scene_id : '--'}}</div>
<div @click="handleDisabled(item, key)" class="w-[40xp] flex items-center ml-[8px]"><el-icon size="20" color="var(--el-color-primary)"><Edit /></el-icon></div>
</div>
</div>
</div>
<div>
<div class="flex items-center justify-between p-[10px] table-item-border bg">
<span class="text-base w-[230px]">{{ t('transferType') }}</span>
<span class="text-base w-[230px]">{{ t('recvPerception') }}</span>
<span class="text-base w-[230px]">{{ t('reportInfos') }}</span>
<span class="text-base w-[80px] text-center">{{ t('operation') }}</span>
</div>
<div v-if="Object.values(item.trade_scene_data).length">
<div class="flex items-center justify-between p-[10px] table-item-border" v-for="(subItem, subKey) in item.trade_scene_data" :key="subKey">
<div class="flex w-[230px] flex-shrink-0 text-base">{{ subItem.name }}</div>
<div class="flex w-[230px] flex-shrink-0 text-base">{{ subItem.perception }}</div>
<div class="w-[230px] flex-shrink-0 text-base">
<div v-for="(childItem,childKey) in subItem.infos" :key="childKey">{{ childKey }}{{ childItem }}</div>
</div>
<div class="flex items-center justify-center w-[80px] select-none">
<button class="text-base text-primary" @click="configFn(item,subItem,subKey)">{{ t('deploy') }}</button>
</div>
</div>
</div>
<div v-else class="min-h-[80px] flex items-center justify-center text-base">
{{ t('noData') }}
</div>
</div>
</el-card>
<el-dialog v-model="showDialog" :title="curData.name" width="550px" :destroy-on-close="true">
<el-form :model="formData" label-width="110px" ref="formRef" class="page-form">
<el-form-item :label="t('recvPerception')" prop="perception" :rules="[{ required: true, message: t('recvPerceptionTips'), trigger: 'blur' }]">
<el-select v-model="formData.perception" :placeholder="t('recvPerceptionTips')" clearable class="!w-[300px]">
<el-option v-for="(item,index) in curData.user_recv_perception" :key="index" :label="item" :value="item" />
</el-select>
</el-form-item>
<template v-for="(item, index) in curData.transfer_scene_report_infos" :key="index">
<el-form-item :label="item" :prop="`infos[${item}]`" :rules="[{ required: true, message: `请输入${item}`, trigger: 'blur' }]">
<el-input v-model.trim="formData.infos[item]" maxlength="40" class="!w-[300px]"/>
</el-form-item>
</template>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="cancel">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { nextTick, ref } from 'vue'
import { t } from '@/lang'
import { getTransferScene, setSceneId, setTradeScene } from '@/app/api/pay'
import { cloneDeep } from 'lodash-es'
import { FormInstance } from 'element-plus'
const screne = ref<any>({})
const loading = ref(false)
const getTransferSceneFn = () => {
getTransferScene().then(res => {
screne.value = res.data
for (const key in screne.value) {
screne.value[key].disabled = true
}
})
}
getTransferSceneFn()
//
const handleInput = (e: any, key: any, data: any) => {
if (e.target.value) {
setSceneId({
scene: key,
scene_id: e.target.value
}).then(() => {
data.disabled = true
getTransferSceneFn()
})
} else {
data.disabled = true
}
}
const inputRefs = ref<any>({})
const handleDisabled = (data: any, key: any) => {
data.disabled = false
nextTick(() => {
inputRefs.value[key].focus()
})
}
const showDialog = ref(false)
const curData = ref<any>({})
const formData = ref({
type: '',
scene: '',
perception: '',
infos: {}
})
const configFn = (data: any, subData: any, type: any) => {
curData.value = cloneDeep(data)
formData.value.type = type
formData.value.scene = subData.scene
formData.value.perception = subData.perception
formData.value.infos = cloneDeep(subData.infos)
showDialog.value = true
}
const formRef = ref<FormInstance>()
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
setTradeScene(formData.value).then(() => {
loading.value = false
showDialog.value = false
getTransferSceneFn()
}).catch(() => {
loading.value = false
})
}
})
}
const cancel = () => {
showDialog.value = false
}
</script>
<style lang="scss" scoped>
.table-item-border {
@apply border-b border-[var(--el-border-color)];
}
</style>

View File

@ -1,14 +1,6 @@
<template>
<div class="main-container h-[500px] w-full p-5 bg-white" v-loading="loading">
<div class="flex flex-wrap px-2 plug-list pb-10">
<div class="flex items-center bg-[#F7F8FA] p-3 w-[295px] relative plug-item mr-4 mb-4 cursor-pointer">
<div class="flex flex-col ml-2">
<span class="text-sm truncate w-[190px]">{{t('refreshMenu')}}</span>
<span class="text-xs text-gray-400 mt-1 truncate w-[190px]" :title="t('refreshMenuDesc')">{{t('refreshMenuDesc')}}</span>
</div>
<span class="plug-item-operate" @click="refreshMenu()">{{t('refresh')}}</span>
</div>
<div class="flex items-center bg-[#F7F8FA] p-3 w-[295px] relative plug-item mr-4 mb-4 cursor-pointer">
<div class="flex flex-col ml-2">
<span class="text-sm truncate w-[190px]">{{t('dataCache')}}</span>
@ -23,26 +15,26 @@
<script lang="ts" setup>
import { ref } from 'vue'
import { t } from '@/lang'
import { clearSchemaCache, menuRefresh } from '@/app/api/sys'
import { clearCache } from '@/app/api/sys'
import { ElMessageBox } from 'element-plus'
const loading = ref<Boolean>(false)
//
const schemaCache = () => {
loading.value = true
clearSchemaCache({}).then(res => {
loading.value = false
}).catch(() => {
loading.value = false
})
}
//
const refreshMenu = () => {
loading.value = true
menuRefresh({}).then(res => {
loading.value = false
}).catch(() => {
loading.value = false
ElMessageBox.confirm(t('clearCacheTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(() => {
loading.value = true
clearCache({}).then(res => {
loading.value = false
}).catch(() => {
loading.value = false
})
})
}
@ -50,10 +42,10 @@ const refreshMenu = () => {
<style lang="scss" scoped>
.demo-tabs > .el-tabs__content {
padding: 32px;
color: #6b778c;
font-size: 32px;
font-weight: 600;
padding: 32px;
color: #6b778c;
font-size: 32px;
font-weight: 600;
}
.plug-item{
.plug-item-operate{

View File

@ -16,28 +16,43 @@
</el-input>
</slot>
</div>
<el-dialog v-model="showDialog" :title="t('selectLinkTips')" width="40%" :close-on-press-escape="false" :destroy-on-close="true" :close-on-click-modal="false" @close="cancel">
<el-dialog v-model="showDialog" :title="t('selectLinkTips')" width="850px" :destroy-on-close="true" :close-on-click-modal="false" @close="cancel">
<div class="flex items-start">
<el-scrollbar class="w-[140px] border-r h-[350px]">
<div v-for="(item, index) in link" :key="index"
class="h-[40px] leading-[40px] cursor-pointer hover:bg-primary-light-9 px-[10px] hover:text-primary"
:class="[item.name == parentLinkName ? 'bg-primary-light-9 text-primary' : '']"
@click="changeParentLink(item)">
{{ item.title }}
</div>
<el-scrollbar class="w-[140px] border-r !h-[550px] link-wrap">
<template v-for="(item, index) in link" :key="index">
<template v-if="item.type == 'folder'">
<div class="flex h-[40px] leading-[40px] cursor-pointer px-[10px] items-center select-none mr-[10px]"
@click="item.foldSwitch = !item.foldSwitch">
<span class="flex-1">{{ item.title }}</span>
<el-icon>
<ArrowDown v-if="item.foldSwitch" />
<ArrowUp v-else />
</el-icon>
</div>
<div class="child-list-wrap" v-show="item.foldSwitch">
<div v-for="(childItem, childIndex) in item.child_list" :key="childIndex" class="h-[40px] leading-[40px] cursor-pointer hover:bg-primary-light-9 hover:text-primary select-none truncate pl-[25px] mr-[20px]" :class="[ childItem.name == parentLinkName ? 'bg-primary-light-9 text-primary' : '' ]" @click="changeParentLink(childItem)">{{ childItem.title }}</div>
</div>
</template>
<div v-else
class="h-[40px] leading-[40px] cursor-pointer px-[10px] items-center select-none hover:bg-primary-light-9 hover:text-primary mr-[20px]"
:class="[ item.name == parentLinkName ? 'bg-primary-light-9 text-primary' : '' ]"
@click="changeParentLink(item)">
<span>{{ item.title }}</span>
</div>
</template>
</el-scrollbar>
<el-scrollbar class="pl-4 h-[350px] flex-1">
<el-scrollbar class="pl-4 !h-[550px] flex-1">
<el-form label-width="100px" class="px-[10px]">
<template v-if="parentLinkName == 'DIY_LINK'">
<component v-if="dynamicComponentName" :is="dynamicComponentName" v-bind="selectLink" ref="dynamicComponentRefs" />
<template v-else-if="parentLinkName == 'DIY_LINK'">
<div class="mb-[16px]">
<el-form-item :label="t('diyLinkName')">
<el-input v-model="selectLink.title" :placeholder="t('diyLinkNamePlaceholder')" />
<el-input v-model="selectLink.title" :placeholder="t('diyLinkNamePlaceholder')" class="!w-[300px]" />
</el-form-item>
</div>
<div class="mb-[16px]">
<el-form-item :label="t('diyLinkUrl')">
<el-input v-model="selectLink.url" :placeholder="t('diyLinkUrlPlaceholder')" />
<el-input v-model="selectLink.url" :placeholder="t('diyLinkUrlPlaceholder')" class="!w-[300px]" />
</el-form-item>
</div>
<el-form-item label=" ">
@ -47,15 +62,15 @@
<div class="text-sm text-gray-400 select-text">跳转外部链接httphttps开头https://baidu.com</div>
</el-form-item>
</template>
<template v-if="parentLinkName == 'DIY_JUMP_OTHER_APPLET'">
<template v-else-if="parentLinkName == 'DIY_JUMP_OTHER_APPLET'">
<div class="mb-[16px]">
<el-form-item :label="t('diyAppletId')">
<el-input v-model="selectLink.appid" :placeholder="t('diyAppletIdPlaceholder')" clearable maxlength="50" />
<el-input v-model="selectLink.appid" :placeholder="t('diyAppletIdPlaceholder')" clearable maxlength="50" class="!w-[300px]" />
</el-form-item>
</div>
<div class="mb-[16px]">
<el-form-item :label="t('diyAppletPage')">
<el-input v-model="selectLink.page" :placeholder="t('diyAppletPagePlaceholder')" clearable maxlength="100" />
<el-input v-model="selectLink.page" :placeholder="t('diyAppletPagePlaceholder')" clearable maxlength="100" class="!w-[300px]" />
</el-form-item>
</div>
<el-form-item label=" ">
@ -65,10 +80,10 @@
<div class="text-sm text-gray-400 select-text">小程序路径格式如app/pages/index/index</div>
</el-form-item>
</template>
<template v-if="parentLinkName == 'DIY_MAKE_PHONE_CALL'">
<template v-else-if="parentLinkName == 'DIY_MAKE_PHONE_CALL'">
<div class="mb-[16px]">
<el-form-item :label="t('diyMakePhone')">
<el-input v-model="selectLink.mobile" :placeholder="t('diyMakePhonePlaceholder')" clearable maxlength="50" />
<el-input v-model="selectLink.mobile" :placeholder="t('diyMakePhonePlaceholder')" clearable maxlength="30" class="!w-[300px]" />
</el-form-item>
</div>
<el-form-item label=" ">
@ -77,9 +92,9 @@
</template>
<div v-else class="flex flex-wrap">
<div v-for="(item, index) in childList" :key="index"
class="border border-br rounded-[3px] mr-[10px] mb-[10px] px-4 h-[32px] leading-[32px] cursor-pointer hover:bg-primary-light-9 px-[10px] hover:text-primary"
class="border border-br rounded-[3px] mr-[10px] mb-[10px] px-4 h-[32px] leading-[32px] cursor-pointer hover:bg-primary-light-9 px-[10px] hover:text-primary"
:class="{ 'border-primary text-primary': (parentLinkName != 'DIY_PAGE' && item.name == selectLink.name) || (parentLinkName == 'DIY_PAGE' && item.url == selectLink.url) }"
@click="changeChildLink(item)">{{ item.title }}
@click="changeChildLink(item)">{{ item.title }}
</div>
</div>
</el-form>
@ -98,7 +113,7 @@
<script lang="ts" setup>
import { t } from '@/lang'
import { ref, computed } from 'vue'
import { ref, computed, defineAsyncComponent } from 'vue'
import { cloneDeep } from 'lodash-es'
import { getLink } from '@/app/api/diy'
import { ElMessage } from 'element-plus'
@ -106,21 +121,22 @@ import { ElMessage } from 'element-plus'
const prop = defineProps({
modelValue: {
type: Object,
default: () => { }
default: () => {
}
},
ignore:{
type:Array,
default:[]
ignore: {
type: Array,
default: []
}
})
const emit = defineEmits(['update:modelValue', 'confirm','success'])
const emit = defineEmits(['update:modelValue', 'confirm', 'success'])
const value: any = computed({
get () {
get() {
return prop.modelValue
},
set (value) {
set(value) {
emit('update:modelValue', value)
}
})
@ -135,17 +151,37 @@ const parentLinkName = ref('')
const childList: any = ref([])
const dynamicComponentName: any = ref('') //
const dynamicComponentRefs: any = ref(null) // ref
const selectLink: any = ref([])
const modules: any = import.meta.glob('@/**/*.vue')
const show = () => {
getLinkFn(() => {
//
if (value.value.name != '') {
selectLink.value = cloneDeep(value.value)
parentLinkName.value = selectLink.value.parent
for (let key in link.value) {
if (link.value[key].name == parentLinkName.value) {
changeParentLink(link.value[key])
for (const key in link.value) {
if (link.value[key].type == 'folder') {
//
if (link.value[key].name == parentLinkName.value) {
changeParentLink(link.value[key].child_list[0])
} else {
for (let i = 0; i < link.value[key].child_list.length; i++) {
if (link.value[key].child_list[i].name == parentLinkName.value) {
changeParentLink(link.value[key].child_list[i])
break
}
}
}
} else {
if (link.value[key].name == parentLinkName.value) {
changeParentLink(link.value[key])
}
}
}
}
@ -155,7 +191,7 @@ const show = () => {
})
}
const getLinkFn = (callback:any=null)=> {
const getLinkFn = (callback: any = null) => {
getLink({}).then((res: any) => {
link.value = res.data
if (prop.ignore && prop.ignore.length) {
@ -169,12 +205,32 @@ const getLinkFn = (callback:any=null)=> {
}
}
childList.value = Object.values(link.value)[0].child_list
//
for (const field in link.value) {
if (link.value[field].type == 'folder') {
link.value[field].foldSwitch = true
}
}
const firstLink: any = Object.values(link.value)[0]
let parentName: any = ''
if (firstLink.type == 'folder') {
childList.value = firstLink.child_list[0].child_list
parentName = firstLink.child_list[0].name
if (!firstLink.child_list[0].component) {
dynamicComponentName.value = ''
}
} else {
childList.value = firstLink.child_list
parentName = firstLink.parent_name
dynamicComponentName.value = ''
}
if (value.value.name != '') {
selectLink.value = cloneDeep(value.value)
} else {
selectLink.value = {
parent: Object.values(link.value)[0].name
parent: parentName
}
}
parentLinkName.value = selectLink.value.parent
@ -185,8 +241,14 @@ const getLinkFn = (callback:any=null)=> {
//
const changeParentLink = (item: any) => {
childList.value = item.child_list
parentLinkName.value = item.name
childList.value = item.child_list
if (item.component) {
dynamicComponentName.value = item.component
dynamicComponentName.value = defineAsyncComponent(modules[dynamicComponentName.value])
} else {
dynamicComponentName.value = ''
}
}
//
@ -205,14 +267,27 @@ const clear = () => {
}
const save = () => {
if (parentLinkName.value === 'DIY_LINK') {
const fields = ['name', 'parent', 'title', 'url', 'appid', 'mobile', 'action', 'page']
if (dynamicComponentName.value && dynamicComponentRefs.value) {
//
const data = dynamicComponentRefs.value.getData()
if (!data) return
//
for (const key in selectLink.value) {
if (fields.indexOf(key) == -1) {
delete selectLink.value[key]
}
}
Object.assign(selectLink.value, data)
} else if (parentLinkName.value === 'DIY_LINK') {
//
if (!selectLink.value.title) {
ElMessage({
message: t('diyLinkNameNotEmpty'),
type: 'warning'
});
})
return
}
@ -220,22 +295,20 @@ const save = () => {
ElMessage({
message: t('diyLinkUrlNotEmpty'),
type: 'warning'
});
})
return
}
selectLink.value.parent = parentLinkName.value
selectLink.value.name = parentLinkName.value
selectLink.value.action = '';
selectLink.value.action = ''
delete selectLink.value.appid;
delete selectLink.value.mobile;
delete selectLink.value.appid
delete selectLink.value.mobile
} else if (parentLinkName.value == 'DIY_PAGE') {
//
selectLink.value.name = parentLinkName.value
selectLink.value.parent = parentLinkName.value
selectLink.value.action = 'decorate';
delete selectLink.value.appid;
@ -261,13 +334,11 @@ const save = () => {
}
selectLink.value.name = parentLinkName.value
selectLink.value.parent = parentLinkName.value
selectLink.value.title = '微信小程序-' + selectLink.value.appid
selectLink.value.action = '';
delete selectLink.value.url;
delete selectLink.value.mobile;
selectLink.value.action = ''
delete selectLink.value.url
delete selectLink.value.mobile
} else if (parentLinkName.value == 'DIY_MAKE_PHONE_CALL') {
//
@ -275,17 +346,27 @@ const save = () => {
ElMessage({
message: t('diyMakePhoneNotEmpty'),
type: 'warning'
});
})
return
}
selectLink.value.name = parentLinkName.value
selectLink.value.parent = parentLinkName.value
selectLink.value.title = '拨打电话:' + selectLink.value.mobile
selectLink.value.action = '';
selectLink.value.action = ''
delete selectLink.value.url;
delete selectLink.value.appid;
delete selectLink.value.url
delete selectLink.value.appid
}
selectLink.value.parent = parentLinkName.value
//
if (dynamicComponentName.value == '') {
for (const key in selectLink.value) {
if (fields.indexOf(key) == -1) {
delete selectLink.value[key]
}
}
}
value.value = cloneDeep(selectLink.value)
@ -306,7 +387,10 @@ defineExpose({
</script>
<style lang="scss">
.link-input .el-input__inner{
cursor: pointer;
}
.link-wrap{
}
.link-input .el-input__inner {
cursor: pointer;
}
</style>

View File

@ -1,11 +1,13 @@
<template>
<upload-attachment type="image" ref="imageRef" limit="" @confirm="imageSelect" />
<upload-attachment type="video" ref="videoRef" @confirm="videoSelect" />
<vue-ueditor-wrap v-model="content" :config="editorConfig" :editorDependencies="['ueditor.config.js','ueditor.all.js']" ref="editorRef"></vue-ueditor-wrap>
<vue-ueditor-wrap v-model="content" :config="editorConfig"
:editorDependencies="['ueditor.config.js', 'ueditor.all.js']" ref="editorRef"
@ready="handleEditorReady"></vue-ueditor-wrap>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
import { computed, nextTick, onMounted, ref } from 'vue'
import { getToken, img } from '@/utils/common'
import { VueUeditorWrap } from 'vue-ueditor-wrap'
import storage from '@/utils/storage'
@ -33,10 +35,10 @@ const imageRef: Record<string, any> | null = ref(null)
const videoRef: Record<string, any> | null = ref(null)
const content = computed({
get () {
get() {
return prop.modelValue
},
set (value) {
set(value) {
emit('update:modelValue', value)
}
})
@ -50,6 +52,7 @@ const baseUrl = import.meta.env.VITE_APP_BASE_URL.substr(-1) == '/' ? import.met
const editorConfig = ref({
debug: false,
UEDITOR_HOME_URL: import.meta.env.MODE == 'development' ? '/public/ueditor/' : '/admin/ueditor/',
UEDITOR_CORS_URL: import.meta.env.MODE == 'development' ? location.origin + '/ueditor/' : location.origin + '/admin/ueditor/',
serverUrl: `${baseUrl}sys/ueditor`,
serverHeaders,
//
@ -58,7 +61,8 @@ const editorConfig = ref({
initialFrameHeight: prop.height,
//
initialFrameWidth: '100%',
toolbarCallback: function(cmd, editor) {
wordCount: true,
toolbarCallback: function (cmd, editor) {
editorEl = editor
switch (cmd) {
case 'insertimage':
@ -70,6 +74,27 @@ const editorConfig = ref({
}
}
})
//
const handleEditorReady = (editor) => {
//
// editorInstance.addListener('contentChange', () => {
// const rawContent = editorInstance.getContent()
// //
// charCount.value = rawContent.replace(/\s/g, '').length
// // DOM
// updateStatsDisplay(charCount.value)
// })
console.log('扩展原型链', editor)
//
const originalCount = editor.getContentLength; //
//
editor.getContentLength = function () {
const rawContent = editor.getContent();
return rawContent.replace(/[\s\u3000]+/g, '').length;
};
}
const imageSelect = (data: Record<string, any>) => {
data.forEach((item: any) => {

View File

@ -6,7 +6,7 @@
<div v-else class="cursor-pointer">{{ t('addHotArea') }}</div>
</slot>
</div>
<el-dialog v-model="showDialog" :title="t('hotAreaSet')" width="810px" :close-on-press-escape="false" :destroy-on-close="true" :close-on-click-modal="false">
<el-dialog v-model="showDialog" :title="t('hotAreaSet')" width="810px" :destroy-on-close="true" :close-on-click-modal="false">
<div class="flex">

View File

@ -16,6 +16,9 @@
"cancel": "取消",
"search": "搜索",
"reset": "重置",
"refresh": "刷新",
"refreshSuccess": "刷新成功",
"select": "选择",
"export": "导出列表",
"exportPlaceholder": "确定要导出数据吗?",
"exportTip": "批量导出数据",
@ -177,5 +180,12 @@
"write": "可写",
"cloudbuildSuccess": "编译完成",
"showDialogCloseTips": "编译任务尚未完成,关闭将取消编译,是否要继续关闭?"
}
},
"formSelectContentTitle": "表单名称",
"formSelectContentTitlePlaceholder": "请输入表单名称",
"formSelectContentTypeName": "表单类型",
"formSelectContentTypeNamePlaceholder": "请选择表单类型",
"formSelectContentTypeAll": "全部",
"formSelectContentTips": "请选择表单"
}

View File

@ -4,8 +4,6 @@
<script lang="ts" setup>
import { ref, markRaw, defineAsyncComponent, provide } from 'vue'
import { getAppType } from '@/utils/common'
import useUserStore from '@/stores/modules/user'
import Storage from '@/utils/storage'
const sysLayout = import.meta.glob('./*/index.vue')

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "nc-iconfont"; /* Project id 4567203 */
src: url('//at.alicdn.com/t/c/font_4567203_1gdtkv2t1dd.woff2?t=1740126778258') format('woff2'),
url('//at.alicdn.com/t/c/font_4567203_1gdtkv2t1dd.woff?t=1740126778258') format('woff'),
url('//at.alicdn.com/t/c/font_4567203_1gdtkv2t1dd.ttf?t=1740126778258') format('truetype');
src: url('//at.alicdn.com/t/c/font_4567203_9qmfc2elgrt.woff2?t=1741345195504') format('woff2'),
url('//at.alicdn.com/t/c/font_4567203_9qmfc2elgrt.woff?t=1741345195504') format('woff'),
url('//at.alicdn.com/t/c/font_4567203_9qmfc2elgrt.ttf?t=1741345195504') format('truetype');
}
.nc-iconfont {
@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale;
}
.nc-icon-qingliV6xx:before {
content: "\e865";
}
.nc-icon-liebiao-xiV6xx1:before {
content: "\e863";
}
.nc-icon-shequfenleiV6xx1:before {
content: "\e862";
}