update admin

This commit is contained in:
全栈小学生 2024-07-26 10:18:53 +08:00
parent e4872ef902
commit 71defadfff
156 changed files with 3556 additions and 2457 deletions

View File

@ -60,7 +60,7 @@ export function editDiyPage(params: Record<string, any>) {
* @param params
*/
export function setUseDiyPage(params: Record<string, any>) {
return request.put(`diy/use`, params, {showSuccessMessage: true})
return request.put(`diy/use/${params.id}`, params, {showSuccessMessage: true})
}
/**

View File

@ -433,15 +433,6 @@ export function getMemberLevelPageList(params: Record<string, any>) {
return request.get(`member/level`, { params })
}
/**
*
* @param params
* @returns
*/
export function getMemberLevelList(params: Record<string, any>) {
return request.get(`member/level/list`, { params })
}
/**
*
* @param level_id level_id
@ -521,4 +512,4 @@ export function setSignConfig(params: Record<string, any>) {
*/
export function getMemberSignList(params: Record<string, any>) {
return request.get(`member/sign`, { params });
}
}

View File

@ -3,26 +3,24 @@ import request from '@/utils/request'
/**
*
*/
export function getAuthinfo() {
export function getAuthInfo() {
return request.get('niucloud/authinfo', { showErrorMessage: false })
}
/**
*
*/
export function setAuthinfo(params: Record<string, any>) {
export function setAuthInfo(params: Record<string, any>) {
return request.post('niucloud/authinfo', params, {showSuccessMessage: true})
}
/**
*
*/
export function getAdminAuthinfo() {
export function getAdminAuthInfo() {
return request.get('niucloud/admin/authinfo')
}
/**
*
* @returns

View File

@ -28,7 +28,6 @@ export function getNoticeLog(params: any) {
return request.get(`notice/log`, {params})
}
/**
*
* @param params

View File

@ -0,0 +1,184 @@
import request from '@/utils/request'
/**
*
* @param params
* @returns
*/
export function getPrinterPageList(params: Record<string, any>) {
return request.get(`sys/printer`, { params })
}
/**
*
* @param params
* @returns
*/
export function getPrinterList(params: Record<string, any>) {
return request.get(`sys/printer/list`, { params })
}
/**
*
* @param printer_id printer_id
* @returns
*/
export function getPrinterInfo(printer_id: number) {
return request.get(`sys/printer/${ printer_id }`);
}
/**
*
* @param params
* @returns
*/
export function addPrinter(params: Record<string, any>) {
return request.post('sys/printer', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function editPrinter(params: Record<string, any>) {
return request.put(`sys/printer/${ params.printer_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function modifyPrinterStatus(params: Record<string, any>) {
return request.put(`sys/printer/status`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param printer_id
* @returns
*/
export function deletePrinter(printer_id: number) {
return request.delete(`sys/printer/${ printer_id }`, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function getPrinterTemplatePageList(params: Record<string, any>) {
return request.get(`sys/printer/template`, { params })
}
/**
*
* @param params
* @returns
*/
export function getPrinterTemplateList(params: Record<string, any>) {
return request.get(`sys/printer/template/list`, { params })
}
/**
*
* @param template_id template_id
* @returns
*/
export function getPrinterTemplateInfo(template_id: number) {
return request.get(`sys/printer/template/${ template_id }`);
}
/**
*
* @param params
* @returns
*/
export function addPrinterTemplate(params: Record<string, any>) {
return request.post('sys/printer/template', params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function editPrinterTemplate(params: Record<string, any>) {
return request.put(`sys/printer/template/${ params.template_id }`, params, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param template_id
* @returns
*/
export function deletePrinterTemplate(template_id: number) {
return request.delete(`sys/printer/template/${ template_id }`, {
showErrorMessage: true,
showSuccessMessage: true
})
}
/**
*
* @param params
* @returns
*/
export function getPrinterType(params: Record<string, any>) {
return request.get(`sys/printer/type`, { params })
}
/**
*
* @param params
* @returns
*/
export function getPrinterBrand(params: Record<string, any>) {
return request.get(`sys/printer/brand`, { params })
}
/**
* token
* @param printer_id printer_id
* @returns
*/
export function refreshPrinterToken(printer_id: number) {
return request.put(`sys/printer/refreshtoken/${ printer_id }`,{},{
showErrorMessage: true,
showSuccessMessage: true
});
}
/**
*
* @param printer_id printer_id
* @returns
*/
export function testPrint(printer_id: number) {
return request.put(`sys/printer/testprint/${ printer_id }`, {},{ showErrorMessage: true, showSuccessMessage: true });
}
/**
*
* @param params
* @returns
*/
export function printTicket(params: Record<string, any>) {
return request.post('sys/printer/printticket', params, { showErrorMessage: true, showSuccessMessage: true })
}

View File

@ -1,6 +1,6 @@
import request from '@/utils/request'
//包含站点管理,站点用户管理,站点操作日志
// 包含站点管理,站点用户管理,站点操作日志
/***************************************************** 站点管理 ****************************************************/
@ -69,7 +69,6 @@ export function getStatusList() {
return request.get(`site/statuslist`)
}
/***************************************************** 站点分组管理 ****************************************************/
/**
@ -167,7 +166,6 @@ export function editUser(params: Record<string, any>) {
return request.put(`site/user/${params.uid}`, params, { showSuccessMessage: true })
}
/**
*
* @param uid
@ -177,7 +175,6 @@ export function lockUser(uid: number) {
return request.put(`site/user/lock/${uid}`)
}
/**
*
* @param uid
@ -187,7 +184,6 @@ export function unlockUser(uid: number) {
return request.put(`site/user/unlock/${uid}`)
}
/***************************************************** 操作日志 **************************************************/
/**

View File

@ -13,5 +13,4 @@ export function getStatInfo() {
*/
export function getSiteStatInfo() {
return request.get(`stat/siteindex`)
}
}

View File

@ -138,7 +138,6 @@ export function getMenuByTypeDir(key: any = 'system') {
return request.get(`sys/menu/dir/${key}`)
}
/***************************************************** 站点菜单 ****************************************************/
/**
@ -149,7 +148,6 @@ export function getSiteMenus() {
return request.get(`site/site/menu`)
}
/***************************************************** 设置 ****************************************************/
/**
@ -279,20 +277,6 @@ export function getAuthMenu() {
return request.get(`auth/site/showmenu`)
}
/**
*
*/
export function getShortcutMenu() {
return request.get(`sys/config/shortcut_menu`)
}
/**
*
*/
export function setShortcutMenu(params: Record<string, any>) {
return request.put(`sys/config/shortcut_menu`, params, { showSuccessMessage: true })
}
/**
*
* @param params
@ -336,7 +320,6 @@ export function getAreatree(level: number = 1) {
return request.get(`sys/area/tree/${level}`)
}
/**
*
*/
@ -528,7 +511,6 @@ export function getChannelType() {
return request.get(`sys/channel`);
}
/**
*
* @returns
@ -569,13 +551,12 @@ export function setPatConfig(params: Record<string, any>) {
return request.post(`pay/channel/set/all`, params, { showSuccessMessage: true })
}
/***************************************************** 刷新菜单 ****************************************************/
/**
*
*/
export function menuRefresh(params: Record<string, any>) {
return request.post(`sys/menu/refresh`, {}, { showSuccessMessage: true })
return request.post(`sys/menu/refresh`, {})
}
/**
@ -585,7 +566,6 @@ export function clearSchemaCache(params: Record<string, any>) {
return request.post(`sys/schema/clear`, {}, { showSuccessMessage: true })
}
/***************************************************** 获取应用 ****************************************************/
/**
*
@ -610,21 +590,6 @@ export function getMap() {
return request.get(`sys/config/map`)
}
/***************************************************** 首页 ****************************************************/
/**
*
*/
export function getIndexList() {
return request.get(`sys/config/site_index`)
}
/**
*
*/
export function setIndexList(params: Record<string, any>) {
return request.put(`sys/config/site_index`, params, { showSuccessMessage: true })
}
/**
*
*/
@ -662,13 +627,6 @@ export function getAddonList() {
return request.get(`app/getAddonList`)
}
/**
*
*/
export function getWapIndexList(params: Record<string, any>) {
return request.get('sys/config/wap_index', { params })
}
/**
* key
* @returns
@ -686,7 +644,6 @@ export function setDeveloperToken(params: Record<string, any>) {
return request.put(`sys/config/developer_token`, params, { showSuccessMessage: true })
}
/**
*
* @returns
@ -729,7 +686,6 @@ export function setThemecolor(params: Record<string, any>) {
return request.put(`sys/config/themecolor`, params)
}
/***************************************************** 报表导出 ****************************************************/
/**

View File

@ -40,6 +40,15 @@ export function getAllUserList(params: Record<string, any>) {
return request.get(`user/user_all`, { params })
}
/**
*
* @param params
* @returns
*/
export function getUserListSelect(params: Record<string, any>) {
return request.get(`user/user_select`, { params })
}
/**
*
* @param username
@ -51,7 +60,7 @@ export function checkUsernameIsExist(username: string) {
/**
*
* @param params
* @param uid
*/
export function getUserCreateSiteLimit(uid: number) {
return request.get(`user/user/create_site_limit/${uid}`)
@ -83,7 +92,7 @@ export function editUserCreateSiteLimit(params: Record<string, any>) {
/**
*
* @param params
* @param id
*/
export function delUserCreateSiteLimit(id: number) {
return request.delete(`user/user/create_site_limit/${id}`, { showSuccessMessage: true })

View File

@ -34,7 +34,6 @@ export function getVerifierList(params: Record<string, any>) {
/**
*
* @param params
* @returns
*/
export function getVerifierSelect() {

View File

@ -49,7 +49,6 @@ export function getTemplateList() {
return request.get('wechat/template')
}
/**
*
* @param params
@ -131,7 +130,6 @@ export function getMediaList(params: Record<string, any>) {
return request.get('wechat/media', { params })
}
/**
*
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,6 +1,5 @@
<template>
<el-dialog v-model="showDialog" :title="t('upgrade.title')" width="850px" :close-on-click-modal="false"
:close-on-press-escape="false" :before-close="dialogClose">
<el-dialog v-model="showDialog" :title="t('upgrade.title')" width="850px" :close-on-click-modal="false" :close-on-press-escape="false" :before-close="dialogClose">
<div v-show="active == 'content'">
@ -117,6 +116,8 @@
<script lang="ts" setup>
import { ref, h, watch } from 'vue'
import { t } from '@/lang'
import { getVersions } from '@/app/api/auth'
import { getFrameworkVersionList } from '@/app/api/module'
import { getUpgradeContent, getUpgradeTask, upgradeAddon, executeUpgrade, preUpgradeCheck, clearUpgradeTask } from '@/app/api/upgrade'
import { Terminal, TerminalFlash } from 'vue-web-terminal'
import 'vue-web-terminal/lib/theme/dark.css'
@ -209,6 +210,14 @@ const elNotificationClick = () => {
notificationEl && notificationEl.close()
}
const versions = ref('')
const getVersionsInfo = () => {
getVersions().then(res => {
versions.value = res.data.version.version
})
}
getVersionsInfo()
/**
* 执行升级
*/
@ -218,19 +227,17 @@ const handleUpgrade = async () => {
const appKey = upgradeContent.value?.app.app_key != 'niucloud-admin' ? upgradeContent.value?.app.app_key : ''
await preUpgradeCheck(appKey)
.then(async ({ data }) => {
if (data.is_pass) {
await upgradeAddon(appKey).then(() => {
getUpgradeTaskFn()
}).catch(() => {
uploading.value = false
})
} else {
upgradeCheck.value = data
}
})
.catch()
await preUpgradeCheck(appKey).then(async({ data }) => {
if (data.is_pass) {
await upgradeAddon(appKey).then(() => {
getUpgradeTaskFn()
}).catch(() => {
uploading.value = false
})
} else {
upgradeCheck.value = data
}
}).catch()
if (uploading.value) active.value = 'upgrade'
}
@ -240,18 +247,26 @@ const open = (addonKey: string = '') => {
ElMessage({ message: '已有正在执行中的升级任务', type: 'error' })
showDialog.value = true
} else {
getUpgradeContent(addonKey).then(({ data }) => {
upgradeContent.value = data
if (!data.version_list.length) {
ElMessage({ message: '已经是最新版本了', type: 'error' })
getFrameworkVersionList().then(({ data }) => {
const newVersion = data.length ? data[0] : null
if (addonKey && newVersion && newVersion.version_no !== versions.value) {
ElMessage({ message: '存在新版本框架,请先升级框架', type: 'error' })
return
}
if (Storage.get('upgradeTipsLock')) {
showDialog.value = true
} else {
upgradeTipsShowDialog.value = true
getUpgradeContent(addonKey).then(({ data }) => {
upgradeContent.value = data
if (!data.version_list.length) {
ElMessage({ message: '已经是最新版本了', type: 'error' })
return
}
if (Storage.get('upgradeTipsLock')) {
showDialog.value = true
} else {
upgradeTipsShowDialog.value = true
}
}).catch()
}
}).catch()
})
}
}

View File

@ -2,7 +2,7 @@
<el-dialog v-model="dialogVisible" :title="t('accountSettings')" width="500">
<el-form :model="saveInfo" label-width="90px" ref="formRef" class="page-form">
<el-form-item :label="t('headImg')">
<upload-image v-model="saveInfo.head_img" :limit="1" :type="'avatar'" />
<upload-image v-model="saveInfo.head_img" :limit="1" :type="'avatar'" imageFit="cover" />
</el-form-item>
<el-form-item :label="t('userName')">
<span>{{saveInfo.username}}</span>
@ -77,5 +77,4 @@ defineExpose({
})
</script>
<style lang="scss" scoped>
</style>

View File

@ -14,5 +14,6 @@
"updateCode": "重新绑定",
"notHaveAuth": "还没有授权?去购买",
"authInfoTips": "授权码和授权秘钥可在Niucloud官网我的授权 授权详情中查看",
"cloudBuildTips": "是否要进行云编译该操作可能会影响到正在访问的客户是否要继续操作?"
"cloudBuildTips": "是否要进行云编译该操作可能会影响到正在访问的客户是否要继续操作?",
"versionTips":"已经升级到最新版本"
}

View File

@ -12,6 +12,7 @@
"pageContent": "页面内容",
"statusBarContent": "导航栏内容",
"statusBarStyle": "导航栏样式",
"statusBarSwitchTips": "此处控制当前页面导航栏是否显示",
"bottomNavContent": "底部导航内容",
"diyPageTitle": "页面名称",
"diyPageTitlePlaceholder": "请输入页面名称",
@ -104,8 +105,7 @@
"titleStyle": "标题样式",
"selectStyle": "风格选择",
"styleLabel": "风格",
"styleShowTips": "风格 1 2 3 5 6仅在小程序中展示",
"topStatusBarBgColorTips": "当导航栏样式为风格5且页面滚动时背景颜色会跟随顶部颜色的设置而改变",
"styleShowTips": "风格 1 2 3仅在小程序中展示",
"titleContent": "标题内容",
"title": "标题名称",
"titlePlaceholder": "请输入标题",
@ -206,6 +206,7 @@
"carouselSearchHotWordTextPlaceholder": "请输入热词",
"carouselSearchAddHotWordItem": "添加一个热词",
"carouselSearchLogoTips": "建议尺寸70px * 30px",
"carouselSearchTextTips": "搜索内容是默认展示数据,当添加搜索热词时,搜索内容隐藏; 当没有搜索热词时,搜索内容展示",
"carouselSearchPlaceholder": "请输入搜索内容",
"carouselSearchTabSet": "选项卡设置",
"carouselSearchTabControl": "展示开关",
@ -249,9 +250,10 @@
"topStatusBarNav": "导航栏",
"topStatusBarNavTips": "此处控制当前页面导航栏是否显示",
"topStatusBarImgTips": "宽度自适应最大150px高度28px",
"topStatusBarIsTransparent": "顶部透明",
"topStatusBarTextColor": "标题颜色",
"topStatusBarBgColor": "顶部颜色",
"topStatusBarBgColor": "头部颜色",
"rollTopStatusBarBgColor": "滚动后头部颜色",
"rollTopStatusBarTextColor": "滚动后标题颜色",
"topStatusBarSearchName": "搜索内容",
"topStatusBarSearchNamePlaceholder": "请输入搜索关键词",
"settingTips": "点击查看如何配置"

View File

@ -2,6 +2,7 @@
"title": "页面名称",
"typeName": "页面类型",
"forAddon": "所属应用",
"forAddonPlaceholder": "请选择所属应用",
"addPageTips": "创建新页面",
"pageTypePlaceholder": "请选择页面类型",
"nameMax": "名称不能超过12个字符",

View File

@ -1,6 +1,7 @@
{
"title": "页面名称",
"forAddon": "所属插件",
"forAddon": "所属应用",
"forAddonPlaceholder": "请选择所属应用",
"all": "全部",
"wapUrl": "wap链接",
"weappUrl": "小程序链接",

View File

@ -1,67 +0,0 @@
{
"todayData": "实时概况",
"memberNumb": "新增会员数(人)",
"orderMoney": "订单金额(元)",
"numberOfSites": "站点数量",
"numberOfVisitors": "今日访客数(人)",
"commonlyUsedFunction": "常用功能",
"articleList": "文章列表",
"memberManagement": "会员管理",
"balanceAccount": "余额账户",
"administrator": "管理员",
"WebDecoration": "网站装修",
"accessMessage": "访问消息",
"memberDistribution": "会员分布",
"systemInfo": "系统环境",
"os": "操作系统",
"phpVersions": "PHP版本号",
"productionEnvironment": "生产环境",
"versionsInfo": "版本信息",
"versions": "当前版本",
"frame": "基于框架",
"channel": "获取渠道",
"serviceSupport": "服务支持",
"officialWbsite": "官网",
"pageView": "访客数(人)",
"siteInfo":"站点信息",
"siteName":"站点名称",
"groupName":"站点套餐",
"expireTime":"过期时间",
"permanent":"永久",
"statusName":"站点状态",
"orderNumber": "订单数(笔)",
"wechatCode": "公众号二维码",
"wechatCodeDesc": "微信扫码关注",
"enterpriseWechatCode": "客服二维码",
"enterpriseWechatCodeDesc": "扫码联系客服",
"tel": "服务热线:",
"message": "请联系客服",
"messageTitle": "提示",
"accumulative":"累计",
"officialAccount": "Niucloud官方公众号",
"officialAccountDesc": "微信扫码关注",
"WeCom": "添加企业微信群",
"path": "地址",
"menuName": "名称",
"menuNamePlaceholder": "模版名称",
"menuBgColor": "背景颜色",
"menuImg": "选择图标",
"menuDesc": "描述",
"addShortcutMenu": "添加快捷模版",
"appTemplate": "应用模块",
"siteType": "站点类型",
"periodTime": "有效期",
"renew": "续费",
"selectModel": "选择模块",
"addMenu": "添加模块",
"shortcutLink": "模版",
"emptyMenu": "暂无快捷模块",
"select": "选择",
"custom": "自定义",
"accessSite": "访问站点",
"pathSelect": "选择模块",
"bgColorPlaceholder": "请选择背景色",
"iconPlaceholder": "请选择图标",
"pathPlaceholder": "请选择链接",
"descPlaceholder": "输入描述语…"
}

View File

@ -72,5 +72,5 @@
"newVersion": "最新版本",
"cloudBuild": "云编译",
"cloudBuildTips": "是否要进行云编译该操作可能会影响到正在访问的客户是否要继续操作?",
"deleteAddonTips": "确定要删除该插件吗?"
"deleteAddonTips": "删除插件会把插件目录连同文件全部删除,确定要删除吗?"
}

View File

@ -42,8 +42,8 @@
"doubleCipherHint": "输入的两次密码不一致",
"memberNoHint":"会员编号只能输入字母和数字",
"mobileHint": "请输入正确的手机号!",
"lable": "标签",
"setLable": "标签",
"memberLabelTag": "标签",
"setLabel": "标签",
"notAvailable": "暂无",
"memberLabelPlaceholder": "请选择会员标签",
"memberInfo":"会员信息",

View File

@ -47,5 +47,15 @@
"polygon": "多边形",
"angle": "旋转角度",
"nickName": "昵称",
"needLoginTips": "前台需要登录才会展示"
"needLoginTips": "前台需要登录才会展示",
"horizontalAlignment": "水平对齐方式",
"verticalAlignment": "垂直对齐方式",
"AlignTips": "当设置文本水平对齐方式时,其内容也会随之改变",
"lineHeight": "行高",
"textAlign": "文字居中方式",
"space": "字间距",
"weight": "文字加粗",
"imgShape": "图片形状"
}

View File

@ -0,0 +1,26 @@
{
"printerSet": "打印机设置",
"printerName": "打印机名称",
"printerNamePlaceholder": "请输入打印机名称",
"brand": "设备品牌",
"brandPlaceholder": "请选择设备品牌",
"printerCode": "打印机编号",
"printerCodePlaceholder": "请输入打印机编号",
"printerCodeTips": "易联云打印机背面的终端号",
"printerKey": "打印机秘钥",
"printerKeyPlaceholder": "请输入打印机秘钥",
"printerKeyTips": "易联云打印机背面的密钥",
"openId": "开发者id",
"openIdPlaceholder": "请输入开发者id",
"openIdTips": "应用ID易联云-开发者中心后台应用中心里获取)",
"apikey": "开发者密钥",
"apikeyPlaceholder": "请输入开发者密钥",
"apikeyTips": "应用密钥(易联云-开发者中心后台应用中心里获取)",
"printWidth": "纸张宽度",
"printWidthPlaceholder": "请输入纸张宽度",
"status": "状态",
"printTrigger": "打印时机",
"usePrintTemplate": "选择模板",
"printNum": "打印联数",
"printTypeEmpty": "缺少打印模板类型"
}

View File

@ -0,0 +1,19 @@
{
"tabPrinterManager": "打印机管理",
"tabPrinterTemplate": "打印模板",
"printerName": "打印机名称",
"printerNamePlaceholder": "请输入打印机名称",
"brand": "设备品牌",
"printWidth": "纸张宽度",
"status": "状态",
"statusOn": "启用",
"statusOff": "禁用",
"createTime": "创建时间",
"addPrinter": "添加打印机",
"updatePrinter": "编辑打印机",
"printerDeleteTips": "确定要删除该数据吗?",
"testPrint": "测试打印",
"testPrintTips": "确定测试打印吗",
"refreshToken": "授权",
"refreshTokenTips": "若易联云打印机在 [测试打印] 时提示 access_token过期或错误请重新授权是否重新授权"
}

View File

@ -0,0 +1,11 @@
{
"templateInfoLabel": "模板信息",
"templateName": "模板名称",
"templateNamePlaceholder": "请输入模板名称",
"templateType": "模板类型",
"printTypeEmpty": "缺少打印模板类型",
"templateTypePlaceholder": "请选择模板类型",
"templateEditLabel": "模板编辑",
"preview": "预览图",
"printTemplateEmpty": "打印模板不存在"
}

View File

@ -0,0 +1,11 @@
{
"tabPrinterManager": "打印机管理",
"tabPrinterTemplate": "打印模板",
"templateName": "模板名称",
"templateNamePlaceholder": "请输入模板名称",
"templateType": "模板类型",
"templateTypePlaceholder": "请选择模板类型",
"createTime": "创建时间",
"addPrinterTemplate": "添加小票打印模板",
"printerTemplateDeleteTips": "确定要删除该数据吗?"
}

View File

@ -6,8 +6,8 @@
"isBindMobile": "强制绑定手机",
"isUsernameTip": "开启之后可以使用账号+密码进行注册和登录",
"isMobileTip": "开启之后可以使用手机+验证码进行注册和登录",
"isAuthRegisterTip": "开启之后,微信公众号、小程序等第三方平台可以自动注册会员。方便会员自动登录",
"isBindMobileTip": "开启之后,会员通过账号或者第三方注册账户会强制绑定手机号,方便商家进行管理,同时方便会员在不同端口统一账号",
"isAuthRegisterTip": "开启之后,微信公众号、小程序等第三方平台可以自动注册会员。方便会员自动登录",
"isBindMobileTip": "开启之后,会员通过普通注册方式会强制绑定手机号,同时在相关页面也会引导会员强制绑定手机账号,否则影响功能正常使用,也方便商家进行管理,同时方便会员在不同端口统一账号",
"agreement": "政策协议",
"agreementTips": "注册时服务协议和隐私协议是否进行展示",
"mobileOrUsernameNoEmpty":"普通注册方式至少需启用一种",

View File

@ -1,6 +1,7 @@
{
"siteId":"站点id",
"noticeKey":"消息模板",
"noticeKeyPlaceholder":"请选择消息模板",
"noticeType":"消息类型",
"noticeInfo":"消息详情",
"uid":"通知的用户id",

View File

@ -1,6 +1,7 @@
{
"siteId":"站点id",
"noticeKey":"消息模板",
"noticeKeyPlaceholder":"请选择消息模板",
"noticeType":"消息类型",
"noticeInfo":"消息详情",
"uid":"通知的用户id",

View File

@ -33,5 +33,6 @@
"siteDomain": "站点域名",
"siteDomainPlaceholder": "请输入站点域名",
"siteDomainTips": "站点域名的配置是针对站点的wap和web端",
"siteDomainTipsTwo": "需要将域名配置到您的服务器,同时域名需要解析您的服务器才可生效"
"siteDomainTipsTwo": "需要将域名配置到您的服务器,同时域名需要解析您的服务器才可生效",
"siteDomainTipsThree": "站点域名不需要加http或者https末尾不需要加/"
}

View File

@ -108,8 +108,8 @@
import { reactive, ref, computed } from 'vue'
import { t } from '@/lang'
import { getVersions } from '@/app/api/auth'
import { getAuthinfo, setAuthinfo, getFrameworkVersionList } from '@/app/api/module'
import { ElMessageBox, FormInstance, FormRules } from 'element-plus'
import { getAuthInfo, setAuthInfo, getFrameworkVersionList } from '@/app/api/module'
import { ElMessageBox, FormInstance, FormRules,ElMessage } from 'element-plus'
import Upgrade from '@/app/components/upgrade/index.vue'
import CloudBuild from '@/app/components/cloud-build/index.vue'
@ -121,9 +121,20 @@ const authCodeApproveDialog = ref(false)
const isCheck = ref(false)
const frameworkVersionList = ref([])
const checkVersion = ref(false)
const getFrameworkVersionListFn = () => {
getFrameworkVersionList().then(({ data }) => {
frameworkVersionList.value = data
if (checkVersion.value) {
if (!newVersion.value || (newVersion.value && newVersion.value.version_no == versions.value)) {
ElMessage({
message: t('versionTips'),
type: 'success'
})
}
} else {
checkVersion.value = true
}
})
}
getFrameworkVersionListFn()
@ -156,7 +167,7 @@ const authinfo = ref<AuthInfo>({
const loading = ref(true)
const saveLoading = ref(false)
const checkAppMange = () => {
getAuthinfo().then((res) => {
getAuthInfo().then((res) => {
loading.value = false
if (res.data.data && res.data.data.length != 0) {
authinfo.value = res.data.data
@ -193,7 +204,7 @@ const save = async (formEl: FormInstance | undefined) => {
if (valid) {
saveLoading.value = true
setAuthinfo(formData).then(() => {
setAuthInfo(formData).then(() => {
saveLoading.value = false
checkAppMange()
}).catch(() => {
@ -220,7 +231,7 @@ getVersionsInfo()
* 升级
*/
const handleUpgrade = () => {
if (!authinfo.value) {
if (!authinfo.value.auth_code) {
authCodeApproveFn()
return
}
@ -228,7 +239,7 @@ const handleUpgrade = () => {
}
const handleCloudBuild = () => {
if (!authinfo.value) {
if (!authinfo.value.auth_code) {
authCodeApproveFn()
return
}

View File

@ -8,22 +8,20 @@
</div>
<div class="flex flex-wrap plug-list pb-10 plug-large" v-if="appList.length">
<div v-for="(item, index) in appList" :key="index + 'b'">
<div class="relative cursor-pointer mt-[20px] mr-4 px-4 border-br-light border-[1px] bg-[var(--el-color-info-light-9)] hover:border-primary">
<div @click="toLink(item.key)" class="flex py-5 items-center">
<div class="flex justify-center items-center">
<el-image class="w-[40px] h-[40px]" :src="img(item.icon)" fit="contain">
<template #error>
<div class="image-slot">
<img class="w-[50px] h-[50px]" src="@/app/assets/images/index/app_default.png" />
</div>
</template>
</el-image>
</div>
<div class="flex flex-col justify-between text-left w-[190px]">
<p class="app-text w-[190px] text-[17px] pl-3">{{ item.title }}</p>
<div v-for="(item, index) in appList" :key="index + 'b'" class="app-item relative cursor-pointer mt-[20px] mr-4 bg-[#f7f7f7] w-[264px] flex py-[20px] px-[17px]" @click="toLink(item.key)">
<el-image class="w-[40px] h-[40px] mr-[10px]" :src="img(item.icon)" fit="contain">
<template #error>
<div class="image-slot">
<img class="w-[50px] h-[50px]" src="@/app/assets/images/index/app_default.png" />
</div>
</template>
</el-image>
<div class="flex flex-col justify-between w-[180px]">
<div class="text-[14px] flex items-center">
<span class="app-text max-w-[170px]">{{ item.title }}</span>
<span class="iconfont iconxiaochengxu2 text-[#00b240] ml-[4px] !text-[14px]"></span>
</div>
<p class="app-text text-[12px] text-[#999]">{{item.desc}}</p>
</div>
</div>
</div>
@ -69,4 +67,8 @@ const toLink = (addon: string) => {
text-overflow: ellipsis;
/* 显示省略号 */
}
.app-item:hover{
transition: 0.5s;
box-shadow: 0px 2px 8px 0px rgba(0,0,0,0.1);
}
</style>

View File

@ -2,10 +2,10 @@
<el-dialog v-model="showDialog" :title="popTitle" width="500px" :destroy-on-close="true">
<el-form :model="formData" label-width="90px" class="page-form" ref="formRef" :rules="formRules" v-loading="loading">
<el-form-item :label="t('menuName')" prop="menu_name">
<el-input v-model="formData.menu_name" :placeholder="t('menuNamePlaceholder')" class="input-width" />
<el-input v-model.trim="formData.menu_name" maxlength="10" show-word-limit :placeholder="t('menuNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('menuKey')" prop="menu_key" v-if="!formData.id">
<el-input v-model="formData.menu_key" :placeholder="t('menuKeyPlaceholder')" class="input-width" />
<el-input v-model.trim="formData.menu_key" maxlength="50" show-word-limit :placeholder="t('menuKeyPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('menuType')">
@ -17,8 +17,8 @@
</el-form-item>
<el-form-item :label="t('addon')" prop="addon" v-show="formData.app_type == 'site'">
<el-select v-model="formData.addon" placeholder="Select" class="input-width" @change="addonChange">
<el-option v-for="(item, index) in addonLst" :label="item.title" :value="item.key" :key="index" />
<el-select v-model="formData.addon" :placeholder="t('addon')" class="input-width" @change="addonChange">
<el-option v-for="(item, index) in addonList" :label="item.title" :value="item.key" :key="index" />
</el-select>
</el-form-item>
@ -77,7 +77,7 @@
</el-form-item>
<el-form-item :label="t('sort')">
<el-input-number v-model="formData.sort" :min="0" />
<el-input-number v-model="formData.sort" :min="0" max="99999999" />
</el-form-item>
</el-form>
@ -124,7 +124,7 @@ const initialFormData = {
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const addonLst = ref<Array<any>>([])
const addonList = ref<Array<any>>([])
const sysMenuList = ref<Array<any>>([])
const addonMenuList = ref<Array<any>>([])
const formRef = ref<FormInstance>()
@ -167,8 +167,8 @@ const formRules = computed(() => {
//
const getAddonDevelopFn = async () => {
const { data } = await getAddonDevelop({})
addonLst.value = [{ title: '系统', key: '' }]
addonLst.value.push(...data)
addonList.value = [{ title: '系统', key: '' }]
addonList.value.push(...data)
}
//

View File

@ -2,7 +2,7 @@
<el-dialog v-model="showDialog" :title="popTitle" width="500px" :destroy-on-close="true">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('roleName')" prop="role_name">
<el-input v-model="formData.role_name" :placeholder="t('roleNamePlaceholder')" clearable :disabled="formData.uid" class="input-width" maxlength="10" :show-word-limit="true" />
<el-input v-model.trim="formData.role_name" :placeholder="t('roleNamePlaceholder')" clearable :disabled="formData.uid" class="input-width" maxlength="10" :show-word-limit="true" />
</el-form-item>
<el-form-item :label="t('status')">
@ -95,6 +95,7 @@ const collapseAll = (data:any) => {
if (data[key].children && data[key].children.length > 0) collapseAll(data[key].children)
})
}
/**
* 表单数据
*/

View File

@ -2,7 +2,7 @@
<el-dialog v-model="showDialog" :title="popTitle" width="500px" :destroy-on-close="true">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('accountNumber')" v-if="!formData.uid" prop="uid">
<!-- <el-form-item :label="t('accountNumber')" v-if="!formData.uid" prop="uid">
<el-select :model-value="uid" :placeholder="t('accountNumberPlaceholder')" class="input-width" filterable clearable :allow-create="true" @change="selectUser" :default-first-option="true">
<el-option v-for="item in userList" :key="item.uid" :label="item.username" :value="item.uid">
<div class="flex items-center">
@ -12,10 +12,10 @@
</div>
</el-option>
</el-select>
</el-form-item>
</el-form-item> -->
<el-form-item :label="t('accountNumber')" prop="username" v-else>
<el-input v-model="formData.username" :placeholder="t('accountNumberPlaceholder')" clearable :disabled="formData.uid" class="input-width" maxlength="10" show-word-limit />
<el-form-item :label="t('accountNumber')" prop="username" >
<el-input v-model.trim="formData.username" :placeholder="t('accountNumberPlaceholder')" clearable :disabled="formData.uid" class="input-width" maxlength="10" show-word-limit />
</el-form-item>
<div v-if="needAddUserInfo">
@ -24,22 +24,22 @@
</el-form-item>
<el-form-item :label="t('userRealName')" prop="real_name">
<el-input v-model="formData.real_name" :placeholder="t('userRealNamePlaceholder')" :readonly="real_name_input" @click="real_name_input = false" @blur="real_name_input = true" clearable class="input-width" maxlength="10" show-word-limit />
<el-input v-model.trim="formData.real_name" :placeholder="t('userRealNamePlaceholder')" :readonly="real_name_input" @click="real_name_input = false" @blur="real_name_input = true" clearable class="input-width" maxlength="10" show-word-limit />
</el-form-item>
<div v-if="!formData.uid">
<el-form-item :label="t('password')" prop="password">
<el-input v-model="formData.password" :placeholder="t('passwordPlaceholder')" :readonly="password_input" @click="password_input = false" @blur="password_input = true" type="password" :show-password="true" clearable class="input-width" />
<el-input v-model.trim="formData.password" :placeholder="t('passwordPlaceholder')" :readonly="password_input" @click="password_input = false" @blur="password_input = true" type="password" :show-password="true" clearable class="input-width" />
</el-form-item>
<el-form-item :label="t('confirmPassword')" prop="confirm_password">
<el-input v-model="formData.confirm_password" :placeholder="t('confirmPasswordPlaceholder')" :readonly="confirm_password_input" @click="confirm_password_input = false" @blur="confirm_password_input = true" type="password" :show-password="true" clearable class="input-width" />
<el-input v-model.trim="formData.confirm_password" :placeholder="t('confirmPasswordPlaceholder')" :readonly="confirm_password_input" @click="confirm_password_input = false" @blur="confirm_password_input = true" type="password" :show-password="true" clearable class="input-width" />
</el-form-item>
</div>
</div>
<el-form-item :label="t('userRoleName')" prop="role_ids" v-if="!formData.userrole.is_admin">
<el-select v-model="formData.role_ids" :placeholder="t('userRolePlaceholder')" class="input-width" multiple collapse-tags collapse-tags-tooltip>
<el-option :label="item.role_name" :value="item.role_id" v-for="(item, index) in roles" :key="index" />
<el-option :label="item.role_name" :value="item.role_id" v-for="(item, index) in roles" :key="index" :disabled="item.disabled" />
</el-select>
</el-form-item>
@ -179,7 +179,6 @@ const confirm = async (formEl: FormInstance | undefined) => {
const data = deepClone(toRaw(formData))
if (!formData.uid && typeof uid.value == 'number') data.uid = uid.value
save(data).then(res => {
loading.value = false
showDialog.value = false

View File

@ -30,5 +30,4 @@ const menuLevel = computed(() => {
</script>
<style lang="scss" scoped>
</style>

View File

@ -78,7 +78,6 @@ const getMenuList = () => {
menusTableData.loading = false
menusTableData.data = res.data
}).catch(() => {
})
}
getMenuList()

View File

@ -9,8 +9,8 @@
<div class="flex justify-between items-center mt-[20px]">
<el-form :inline="true" :model="userTableData.searchParam" ref="searchFormRef">
<el-form-item :label="t('accountNumber')" prop="seach">
<el-input v-model="userTableData.searchParam.seach" class="input-width" :placeholder="t('accountNumberPlaceholder')" />
<el-form-item :label="t('accountNumber')" prop="search">
<el-input v-model="userTableData.searchParam.search" class="input-width" :placeholder="t('accountNumberPlaceholder')" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadUserList()">{{ t('search') }}</el-button>
@ -107,7 +107,7 @@ const userTableData = reactive({
loading: true,
data: [],
searchParam: {
seach: '',
search: '',
user_type: ''
}
})
@ -131,7 +131,7 @@ const loadUserList = (page: number = 1) => {
getUserList({
page: userTableData.page,
limit: userTableData.limit,
username: userTableData.searchParam.seach,
username: userTableData.searchParam.search,
user_type: userTableData.searchParam.user_type
}).then(res => {
userTableData.loading = false

View File

@ -76,7 +76,7 @@
<el-dialog v-model="failReasonDialogVisible" :title="t('failReason')" width="60%">
<el-scrollbar class="h-[60vh] w-full whitespace-pre p-[20px]">
{{ failReason }}
<div v-html="failReason"></div>
</el-scrollbar>
</el-dialog>
@ -97,7 +97,7 @@ import { reactive, ref } from 'vue'
import { setWeappVersion, getWeappPreview, getWeappVersionList, getWeappUploadLog, getWeappConfig } from '@/app/api/weapp'
import { t } from '@/lang'
import { useRoute, useRouter } from 'vue-router'
import { getAuthinfo } from '@/app/api/module'
import { getAuthInfo } from '@/app/api/module'
import { getAppType } from '@/utils/common'
import { ElMessageBox } from 'element-plus'
import { AnyObject } from '@/types/global'
@ -131,7 +131,7 @@ const form = ref({
const uploadSuccessShowDialog = ref(false)
const authCode = ref('')
getAuthinfo().then(res => {
getAuthInfo().then(res => {
if (res.data.data && res.data.data.auth_code) {
authCode.value = res.data.data.auth_code
getWeappPreviewImage()
@ -279,7 +279,6 @@ const configElMessageBox = () => {
}
).then(() => {
router.push({ path: '/channel/weapp/config' })
}).catch((action: string) => {
})
}

View File

@ -132,7 +132,7 @@ import { reactive, ref, watch, computed } from 'vue'
import { t } from '@/lang'
import { getWeappConfig, setWeappConfig } from '@/app/api/weapp'
import { useClipboard } from '@vueuse/core'
import { ElMessage, FormInstance, FormRules } from 'element-plus'
import { ElMessage, FormInstance } from 'element-plus'
import { ArrowLeft } from '@element-plus/icons-vue'
import { useRoute, useRouter } from 'vue-router'

View File

@ -24,8 +24,7 @@
<div v-if="attachment.data.length">
<div class="flex flex-wrap" v-if="prop.type != 'news'">
<div class="attachment-item mr-[10px] mb-[10px] w-[120px]" v-for="(item, index) in attachment.data" :key="index" @click="selectedFile = item">
<div
class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center h-[120px]">
<div class="attachment-wrap w-full rounded cursor-pointer overflow-hidden relative flex items-center justify-center h-[120px]">
<el-image :src="img(item.value)" fit="contain" v-if="type == 'image'" :preview-src-list="item.image_list" />
<video :src="img(item.value)" v-else-if="type == 'video'"></video>
<div class="absolute z-[1] flex items-center justify-center w-full h-full inset-0 bg-black bg-opacity-60" v-show="selectedFile.id == item.id">

View File

@ -17,7 +17,7 @@
<el-form-item :label="t('keyword')" prop="keyword">
<el-input v-model.trim="formData.keyword" :placeholder="t('keywordPlaceholder')" class="input-width" clearable >
<template #prepend>
<el-select v-model="formData.matching_type" placeholder="Select" style="width: 115px">
<el-select v-model="formData.matching_type" style="width: 115px">
<el-option :label="t('allMatching')" value="full" />
<el-option :label="t('fuzzyMatching')" value="like" />
</el-select>

View File

@ -2,10 +2,10 @@
<el-dialog v-model="showDialog" :title="formData.id ? t('updateDict') : t('addDict')" width="480" class="diy-dialog-wrap" :destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('name')" prop="name">
<el-input v-model="formData.name" clearable :placeholder="t('namePlaceholder')" class="input-width" />
<el-input v-model.trim="formData.name" clearable maxlength="40" show-word-limit :placeholder="t('namePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('key')" prop="key">
<el-input v-model="formData.key" clearable :placeholder="t('keyPlaceholder')" class="input-width" />
<el-input v-model.trim="formData.key" clearable maxlength="40" show-word-limit :placeholder="t('keyPlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('memo')">
<el-input v-model="formData.memo" type="textarea" clearable :placeholder="t('memoPlaceholder')" class="input-width" />

View File

@ -242,6 +242,8 @@ diyStore.editComponent.list.forEach((item: any) => {
const showTitleDialog = ref(false)
const showTitleStyle = () => {
selectTitleStyle.title = diyStore.editComponent.titleStyle.title;
selectTitleStyle.value = diyStore.editComponent.titleStyle.value;
showTitleDialog.value = true
}

View File

@ -31,7 +31,10 @@
<upload-image v-model="diyStore.editComponent.search.logo" :limit="1" />
</el-form-item>
<el-form-item :label="t('carouselSearchText')">
<el-input v-model.trim="diyStore.editComponent.search.text" :placeholder="t('carouselSearchPlaceholder')" clearable maxlength="20" show-word-limit />
<div>
<el-input v-model.trim="diyStore.editComponent.search.text" :placeholder="t('carouselSearchPlaceholder')" clearable maxlength="20" show-word-limit />
<p class="text-sm text-gray-400 mt-[10px] leading-[1.5]">{{t('carouselSearchTextTips')}}</p>
</div>
</el-form-item>
<el-form-item :label="t('link')">
<diy-link v-model="diyStore.editComponent.search.link"/>

View File

@ -3,14 +3,41 @@
<div class="content-wrap float-btn" 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="showCouponStyle">{{ diyStore.editComponent.styleName }}</span>
<el-icon>
<ArrowRight />
</el-icon>
</el-form-item>
</el-form>
<el-dialog v-model="showCouponDialog" :title="t('selectStyle')" width="500px">
<div class="flex flex-wrap">
<template v-for="(item,index) in couponStyleList" :key="index">
<div :class="{ 'border-primary': selectCouponStyle.value == item.value }" @click="changeCouponStyle(item)" class="flex 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="showCouponDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" @click="confirmCouponStyle">{{ t('confirm') }}</el-button>
</span>
</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>
<ul class="ml-[10px] flex items-center">
<li v-for="(item,i) in templateList" :key="i" :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', item.src]"></span>
</li>
<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)">
<span :class="['iconfont !text-[20px]', item.src]"></span>
</li>
</template>
</ul>
</el-form-item>
<el-form-item :label="t('floatBtnOffset')">
@ -22,7 +49,7 @@
<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] horz-blank-slider" :min="40" :max="100"/>
<el-slider v-model="diyStore.editComponent.imageSize" show-input size="small" class="ml-[10px] horz-blank-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] graphic-nav-slider" :max="50"/>
@ -59,7 +86,7 @@
</template>
<script lang="ts" setup>
import { ref, computed, onMounted, nextTick } from 'vue'
import { ref, reactive, onMounted, nextTick } from 'vue'
import { t } from '@/lang'
import Sortable from 'sortablejs'
import useDiyStore from '@/stores/modules/diy'
@ -67,7 +94,7 @@ import { img } from '@/utils/common'
import { range } from 'lodash-es'
const diyStore = useDiyStore()
diyStore.editComponent.ignore = [] //
diyStore.editComponent.ignore = ['pageBgColor','marginTop','marginBottom','marginBoth'] //
//
diyStore.editComponent.verify = (index: number) => {
@ -82,30 +109,72 @@ diyStore.editComponent.verify = (index: number) => {
return res
}
/*********** 风格样式 **********/
const showCouponDialog = ref(false)
const selectCouponStyle = reactive({
title: diyStore.editComponent.styleName,
value: diyStore.editComponent.style
})
const showCouponStyle = () => {
showCouponDialog.value = true
selectCouponStyle.title = diyStore.editComponent.styleName;
selectCouponStyle.value = diyStore.editComponent.style;
}
// const couponStyleList = reactive([
// {
// url: 'addon/shop/diy/goods_coupon/style-1.png',
// title: '1',
// value: 'style-1'
// },
// {
// url: 'addon/shop/diy/goods_coupon/style-2.png',
// title: '2',
// value: 'style-2'
// }
// ])
//
const changeCouponStyle = (item:any) => {
selectCouponStyle.title = item.title;
selectCouponStyle.value = item.value;
}
//
const confirmCouponStyle = () => {
diyStore.editComponent.styleName = selectCouponStyle.title;
diyStore.editComponent.style = selectCouponStyle.value;
showCouponDialog.value = false
selectTemplate.value = {
name: '右下',
src: 'iconyouxiajiao',
className: 'lowerRight'
};
diyStore.editComponent.bottomPosition = 'lowerRight'
}
/******** end *******/
const templateList = ref([
{
name: '左上',
src: 'iconzuoshangjiao',
src: 'iconzuoshangpc',
className: 'upperLeft'
},
{
name: '右上',
src: 'iconyoushangjiao',
src: 'iconyoushangpc',
className: 'upperRight'
},
{
name: '左下',
src: 'iconzuoxiajiao',
src: 'iconzuoxiapc',
className: 'lowerLeft'
},
{
name: '右下',
src: 'iconyouxiajiao',
src: 'iconyouxiapc',
className: 'lowerRight'
}
])
let selectTemplate = ref({})
const selectTemplate = ref({})
templateList.value.forEach((item) => {
if (item.className == diyStore.editComponent.bottomPosition) {
selectTemplate.value = item

View File

@ -124,7 +124,7 @@ const handleHeight = (isCalcHeight:boolean = false)=> {
}
const blurImageHeight = () => {
diyStore.editComponent.imageHeight = parseInt(diyStore.editComponent.imageHeight)
diyStore.editComponent.imageHeight = diyStore.editComponent.imageHeight ? parseInt(diyStore.editComponent.imageHeight) : 0
}
const imageBoxRef = ref()

View File

@ -18,7 +18,7 @@
<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="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') }]">
<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>
@ -105,7 +105,6 @@ 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 = [] //
@ -148,7 +147,7 @@ watch(
if(newValue){
diyStore.editComponent.imgType = 'diy';
}else{
diyStore.editComponent.imgType = 'system';
changeStyle('style_1');
}
}
)
@ -204,9 +203,7 @@ defineExpose({})
display: none;
}
}
.operation{
display: none !important;
}
}
}
</style>

View File

@ -13,35 +13,41 @@
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('statusBarContent') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('diyTitle')">
<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>
<el-icon>
<ArrowRight />
</el-icon>
</div>
<div class="text-sm text-gray-400 leading-[1.5]">{{ t('styleShowTips') }}</div>
</el-form-item>
<el-form-item :label="t('topStatusBarImg')" v-if="['style-2','style-3'].indexOf(diyStore.global.topStatusBar.style) > -1">
<upload-image v-model="diyStore.global.topStatusBar.imgUrl" :limit="1" />
<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-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">
<el-radio :label="'left'">{{ t('textAlignLeft') }}</el-radio>
<el-radio :label="'center'">{{ t('textAlignCenter') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('link')" v-if="['style-2','style-3'].indexOf(diyStore.global.topStatusBar.style) > -1">
<diy-link v-model="diyStore.global.topStatusBar.link" />
<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>
<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/>
<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>
<el-icon>
<ArrowRight />
</el-icon>
</div>
<div class="text-sm text-gray-400 leading-[1.5]">{{ t('styleShowTips') }}</div>
</el-form-item>
<el-form-item :label="t('topStatusBarImg')" v-if="['style-2','style-3'].indexOf(diyStore.global.topStatusBar.style) > -1">
<upload-image v-model="diyStore.global.topStatusBar.imgUrl" :limit="1" />
<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-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">
<el-radio :label="'left'">{{ t('textAlignLeft') }}</el-radio>
<el-radio :label="'center'">{{ t('textAlignCenter') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('link')" v-if="['style-2','style-3'].indexOf(diyStore.global.topStatusBar.style) > -1">
<diy-link v-model="diyStore.global.topStatusBar.link" />
</el-form-item>
</template>
</el-form>
</div>
<div class="edit-attr-item-wrap">
@ -69,12 +75,6 @@
<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 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-5' }" @click="selectStyle = 'style-5'">
<img class="max-w-[100%] max-h-[100%]" src="@/app/assets/images/diy/head/nav_style5.png" />
</div>
<div class="flex items-center justify-center overflow-hidden w-[32%] h-[100px] cursor-pointer border bg-gray-50" :class="{ 'border-primary': selectStyle == 'style-6' }" @click="selectStyle = 'style-6'">
<img class="max-w-[100%] max-h-[100%]" src="@/app/assets/images/diy/head/nav_style6.jpg" />
</div>
</div>
<template #footer>
@ -91,7 +91,7 @@
<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="80px" class="px-[10px]">
<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]"/>
@ -114,19 +114,24 @@
</div>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('statusBarStyle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('topStatusBarBgColor')" class="display-block" v-if="selectStyle == 'style-5'">
<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 />
<div class="text-sm text-gray-400 leading-[1.5]">{{ t('topStatusBarBgColorTips') }}</div>
</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="80px" class="px-[10px]">
<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] horz-blank-slider"/>
</el-form-item>
@ -182,8 +187,6 @@ const showStyle = () => {
const selectStyle = ref("style-1")
const changeStyle = () => {
diyStore.global.topStatusBar.isShow = true;
diyStore.global.topStatusBar.isTransparent = false;
switch (selectStyle.value) {
case 'style-1':
diyStore.global.topStatusBar.styleName = '风格1'
@ -197,14 +200,6 @@ const changeStyle = () => {
case 'style-4':
diyStore.global.topStatusBar.styleName = '风格4'
break
case 'style-5':
diyStore.global.topStatusBar.isTransparent = true;
diyStore.global.topStatusBar.styleName = '风格5'
break
case 'style-6':
diyStore.global.topStatusBar.isShow = false;
diyStore.global.topStatusBar.styleName = '风格6'
break
}
diyStore.global.topStatusBar.style = selectStyle.value
showDialog.value = false

View File

@ -96,7 +96,7 @@ diyStore.editComponent.verify = (index: number) => {
const templateList = ref([
{
name: '1行2个',
src: 'iconyihangliangge',
src: 'iconyihang2gepc1',
className: 'row1-of2',
dimensionScale: [
{
@ -114,7 +114,7 @@ const templateList = ref([
},
{
name: '1行3个',
src: 'iconyihangsange',
src: 'iconyihang3gepc',
className: 'row1-of3',
dimensionScale: [
{
@ -137,7 +137,7 @@ const templateList = ref([
},
{
name: '1行4个',
src: 'iconyihangsige',
src: 'iconyihang4gepc',
className: 'row1-of4',
dimensionScale: [
{
@ -165,7 +165,7 @@ const templateList = ref([
},
{
name: '2左2右',
src: 'iconmofang-liangzuoliangyou',
src: 'iconliangzuoliangyoupc',
className: 'row2-lt-of2-rt',
dimensionScale: [
{
@ -193,7 +193,7 @@ const templateList = ref([
},
{
name: '1左2右',
src: 'iconmofang-yizuoliangyou',
src: 'iconyizuoliangyoupc',
className: 'row1-lt-of2-rt',
dimensionScale: [
{
@ -216,7 +216,7 @@ const templateList = ref([
},
{
name: '1上2下',
src: 'iconmofang-yishangliangxia',
src: 'iconyishangliangxiapc',
className: 'row1-tp-of2-bm',
dimensionScale: [
{
@ -239,7 +239,7 @@ const templateList = ref([
},
{
name: '1左3右',
src: 'iconxuanzemoban-yizuosanyou',
src: 'iconyizuosanyoupc',
className: 'row1-lt-of1-tp-of2-bm',
dimensionScale: [
{

View File

@ -191,10 +191,10 @@
<el-slider v-model="diyStore.editComponent.margin.both" show-input size="small" class="ml-[10px] horz-blank-slider" />
</el-form-item>
<el-form-item :label="t('topRounded')" v-if="diyStore.editComponent.ignore.indexOf('topRounded') == -1">
<el-slider v-model="diyStore.editComponent.topRounded" show-input size="small" class="ml-[10px] horz-blank-slider" :max="50" />
<el-slider v-model="diyStore.editComponent.topRounded" show-input size="small" class="ml-[10px] horz-blank-slider" :max="100" />
</el-form-item>
<el-form-item :label="t('bottomRounded')" v-if="diyStore.editComponent.ignore.indexOf('bottomRounded') == -1">
<el-slider v-model="diyStore.editComponent.bottomRounded" show-input size="small" class="ml-[10px] horz-blank-slider" :max="50" />
<el-slider v-model="diyStore.editComponent.bottomRounded" show-input size="small" class="ml-[10px] horz-blank-slider" :max="100" />
</el-form-item>
</el-form>
</div>

View File

@ -31,7 +31,7 @@
<div class="w-[700px]">
<div class="flex flex-wrap">
<diy-link v-model="link" :ignore="['DIY_LINK']" @success="changePage">
<diy-link v-model="link" :ignore="['DIY_LINK','DIY_JUMP_OTHER_APPLET','DIY_MAKE_PHONE_CALL']" @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-input v-model="diyPageTableData.searchParam.title" :placeholder="t('titlePlaceholder')" />
</el-form-item>
<el-form-item :label="t('forAddon')" prop="addon_name">
<el-select v-model="diyPageTableData.searchParam.addon_name" :placeholder="t('pageTypePlaceholder')" @change="handleSelectAddonChange">
<el-select v-model="diyPageTableData.searchParam.addon_name" :placeholder="t('forAddonPlaceholder')" @change="handleSelectAddonChange">
<el-option :label="t('all')" value="" />
<el-option v-for="(item, key) in apps" :label="item.title" :value="key" :key="key"/>
</el-select>

View File

@ -12,7 +12,7 @@
<el-input v-model="diyRouteTableData.searchParam.title" :placeholder="t('titlePlaceholder')" />
</el-form-item>
<el-form-item :label="t('forAddon')" prop="addon_name">
<el-select v-model="diyRouteTableData.searchParam.addon_name" :placeholder="t('pageTypePlaceholder')">
<el-select v-model="diyRouteTableData.searchParam.addon_name" :placeholder="t('forAddonPlaceholder')">
<el-option :label="t('all')" value="" />
<el-option v-for="(item, key) in apps" :label="item.title" :value="key" :key="key"/>
</el-select>
@ -54,7 +54,7 @@
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="diyRouteTableData.page" v-model:page-size="diyRouteTableData.limit" layout="total, sizes, prev, pager, next, jumper" :total="diyRouteTableData.total" @size-change="loadDiyRouteList()" @current-change="loadDiyRouteList" />
<el-pagination v-model:current-page="diyRouteTableData.page" v-model:page-size="diyRouteTableData.limit" layout="total, sizes, prev, pager, next, jumper" :total="diyRouteTableData.total" @size-change="getDiyRouteListFn" @current-change="loadDiyRouteList" />
</div>
</el-card>
@ -99,6 +99,7 @@ import { ElMessage, FormInstance } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { useClipboard } from '@vueuse/core'
import { getUrl } from '@/app/api/sys'
import { cloneDeep } from 'lodash-es'
const route = useRoute()
const router = useRouter()
@ -121,6 +122,8 @@ const diyRouteTableData = reactive({
}
})
const diyRouteList: any = ref([])
const wapDomain = ref('')
const getDomain = async () => {
wapDomain.value = (await getUrl()).data.wap_url
@ -130,42 +133,60 @@ getDomain()
const apps: any = reactive({}) //
getDiyRouteAppList().then(res=>{
if(res.data){
getDiyRouteAppList().then(res=> {
if (res.data) {
for (const key in res.data) {
apps[key] = res.data[key];
}
}
});
const getDiyRouteListFn = () => {
getDiyRouteList({}).then(res => {
diyRouteTableData.loading = false
diyRouteList.value = cloneDeep(res.data)
loadDiyRouteList(diyRouteTableData.page)
}).catch(() => {
diyRouteTableData.loading = false
});
}
getDiyRouteListFn();
/**
* 获取自定义路由列表
*/
const loadDiyRouteList = (page: number = 1) => {
diyRouteTableData.loading = true
diyRouteTableData.page = page
getDiyRouteList({
page: diyRouteTableData.page,
limit: diyRouteTableData.limit,
...diyRouteTableData.searchParam
}).then(res => {
diyRouteTableData.loading = false
const tempData = cloneDeep(diyRouteList.value)
const data: any = [];
const len = Math.ceil(res.data.length / diyRouteTableData.limit)
const data = JSON.parse(JSON.stringify(res.data))
const dataGather = []
for (let i = 0; i < len; i++) {
dataGather[i] = data.splice(0, diyRouteTableData.limit)
//
for (let i = 0; i < tempData.length; i++) {
let isAdd = true;
if (diyRouteTableData.searchParam.title && tempData[i].title.indexOf(diyRouteTableData.searchParam.title) == -1) {
isAdd = false;
}
diyRouteTableData.data = dataGather[diyRouteTableData.page - 1]
diyRouteTableData.total = res.data.length
}).catch(() => {
diyRouteTableData.loading = false
})
if (diyRouteTableData.searchParam.addon_name && tempData[i].addon_info && tempData[i].addon_info.key != diyRouteTableData.searchParam.addon_name) {
isAdd = false;
}
if (isAdd) {
data.push(tempData[i]);
}
}
diyRouteTableData.total = data.length
const len = Math.ceil(data.length / diyRouteTableData.limit)
const dataGather = []
for (let i = 0; i < len; i++) {
dataGather[i] = data.splice(0, diyRouteTableData.limit)
}
diyRouteTableData.data = dataGather[diyRouteTableData.page - 1]
}
loadDiyRouteList()
//
getDiyTemplate({}).then(res => {
@ -273,7 +294,7 @@ const shareEvent = async (formEl: FormInstance | undefined) => {
share: JSON.stringify(shareFormData),
...diyRouteData
}).then(() => {
loadDiyRouteList()
getDiyRouteListFn()
shareDialogVisible.value = false
}).catch(() => {
})
@ -284,7 +305,7 @@ const shareEvent = async (formEl: FormInstance | undefined) => {
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadDiyRouteList()
getDiyRouteListFn()
}
</script>

View File

@ -31,7 +31,7 @@
<el-tabs v-model="activeName" class="demo-tabs mt-[15px]">
<el-tab-pane :label="t('navImage')" name="navPicture">
<div ref="navItemRef">
<div v-for="(item,index) in diyBottomData.value.list" :key="'a'+index" :data-id="index" class="item-wrap border-2 border-dashed pt-[18px] m-[10px] mb-[15px] relative list-item">
<div v-for="(item,index) in diyBottomData.value.list" :key="'a'+index" :data-id="index" class="item-wrap border-2 border-dashed pt-[18px] m-[10px] mb-[15px] relative list-item" :class="{ 'not-sort': useDrag }">
<el-form-item :label="t('navIconOne')">
<div class="flex align-center">
<div class="flex flex-col justify-center items-center">
@ -48,7 +48,7 @@
<el-input class="!w-[215px]" v-model="item.text" :placeholder="t('titleContent')" maxlength="5" show-word-limit />
</el-form-item>
<el-form-item :label="t('navLinkOne')">
<diy-link v-model="item.link"/>
<diy-link v-model="item.link" @confirm="diyLinkFn" />
</el-form-item>
<el-icon class="close-icon cursor-pointer -top-[11px] -right-[8px]" @click="deleteNav(index)">
<CircleCloseFilled />
@ -238,6 +238,7 @@ onMounted(() => {
const sortable = Sortable.create(navItemRef.value, {
group: 'item-wrap',
animation: 200,
filter: '.not-sort', // .not-sort
onEnd: event => {
const temp = diyBottomData.value.list[event.oldIndex!]
diyBottomData.value.list.splice(event.oldIndex!, 1)
@ -253,6 +254,10 @@ onMounted(() => {
})
})
const useDrag = ref(false)
const diyLinkFn = (val) => {
useDrag.value = val
}
</script>
<style lang="scss" scoped>
.close-icon {

View File

@ -89,7 +89,7 @@
<template #default="{ row }">
<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]" v-else src="@/app/assets/images/default_headimg.png" 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">
<span>{{ row.member.nickname || '' }}</span>
<span>{{ row.member.mobile || '' }}</span>
@ -99,7 +99,7 @@
</el-table-column>
<el-table-column :label="t('cashOutMethod')" align="center" min-width="140">
<template #default="{ row }">
{{ Transfertype[row.transfer_type].name }}
{{ row.transfer_type_name }}
</template>
</el-table-column>
@ -183,7 +183,7 @@
<el-dialog v-model="auditShowDialog" :title="t('rejectionAudit')" width="500px" :destroy-on-close="true">
<el-form :model="auditFailure" label-width="90px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('reasonsRefusal')" prop="label_name">
<el-input v-model="auditFailure.refuse_reason" clearable :placeholder="t('reasonsRefusalPlaceholder')" class="input-width" type="textarea" />
<el-input v-model="auditFailure.refuse_reason" clearable maxlength="200" :show-word-limit="true" :placeholder="t('reasonsRefusalPlaceholder')" :rows="4" class="input-width" type="textarea" />
</el-form-item>
</el-form>
<template #footer>
@ -334,10 +334,9 @@ const fnProcessing = (type: string, data: any) => {
}
} else if (type == 'transferFn') {
obj.id = data.id
ElMessageBox.confirm(`${t('isTransfer')}`, `${t('transfer')}`)
.then(() => {
transferFn(obj)
})
ElMessageBox.confirm(`${ t('isTransfer') }`, `${ t('transfer') }`).then(() => {
transferFn(obj)
})
} else {
detailFn(data.id)
}
@ -349,7 +348,9 @@ const fnProcessing = (type: string, data: any) => {
*/
const transferFn = (data:any) => {
memberTransfer({ ...data }).then(res => {
auditFailure.value = { refuse_reason: '', id: 0, action: 0 }
loadOrderList()
}).catch(() => {
loadOrderList()
})
@ -389,6 +390,7 @@ const cashOutAuditFn = (data:any) => {
...data
}).then(res => {
loadOrderList()
}).catch(() => {
loadOrderList()
})

View File

@ -9,8 +9,7 @@
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="payListTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('outTradeNo')" prop="trade_no">
<el-input v-model="payListTable.searchParam.out_trade_no"
:placeholder="t('outTradeNoPlaceholder')" />
<el-input v-model="payListTable.searchParam.out_trade_no" :placeholder="t('outTradeNoPlaceholder')" />
</el-form-item>
<el-form-item :label="t('createTime')" prop="create_time">
<el-date-picker v-model="payListTable.searchParam.create_time" type="datetimerange"
@ -18,7 +17,7 @@
:end-placeholder="t('endDate')" />
</el-form-item>
<el-form-item :label="t('status')" prop="status">
<el-select v-model="payListTable.searchParam.status" placeholder="Select">
<el-select v-model="payListTable.searchParam.status" :placeholder="t('status')">
<el-option :label="t('all')" value="" />
<el-option :label="t('waitAudit')" value="3" />
<el-option :label="t('passed')" value="2" />
@ -137,21 +136,17 @@ loadPayList()
const passEvent = (row: AnyObject) => {
ElMessageBox.confirm(
t('passTips'),
t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
t('passTips'),
t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(({ value }) => {
payAuditPass(row.out_trade_no)
.then(() => {
loadPayList()
})
.catch()
}).catch(() => {
payAuditPass(row.out_trade_no).then(() => {
loadPayList()
})
})
}
@ -163,13 +158,9 @@ const refuseEvent = (row: AnyObject) => {
inputPattern: /\S/,
inputType: 'textarea'
}).then(({ value }) => {
payAuditRefuse({ out_trade_no: row.out_trade_no, reason: value })
.then(() => {
loadPayList()
})
.catch()
}).catch(() => {
payAuditRefuse({ out_trade_no: row.out_trade_no, reason: value }).then(() => {
loadPayList()
})
})
}

View File

@ -72,34 +72,26 @@ const formData: Record<string, any> | null = ref(null)
const setFormData = async () => {
loading.value = true
formData.value = null
await getPayDetail(id)
.then(({ data }) => {
formData.value = data
})
.catch(() => {
})
await getPayDetail(id).then(({ data }) => {
formData.value = data
})
loading.value = false
}
setFormData()
const passEvent = () => {
ElMessageBox.confirm(
t('passTips'),
t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
t('passTips'),
t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning'
}
).then(({ value }) => {
payAuditPass(formData.value.out_trade_no)
.then(() => {
setFormData()
})
.catch()
}).catch(() => {
payAuditPass(formData.value.out_trade_no).then(() => {
setFormData()
})
})
}
@ -113,9 +105,7 @@ const refuseEvent = () => {
}).then(({ value }) => {
payAuditRefuse({ out_trade_no: formData.value.out_trade_no, reason: value }).then(() => {
setFormData()
}).catch()
}).catch(() => {
})
})
}

View File

@ -67,7 +67,7 @@ const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const refundNo: string = route.query.refund_no
const refundNo: any = route.query.refund_no
const loading = ref(true)
const refundList = ref([])
@ -76,15 +76,10 @@ const formData: Record<string, any> | null = ref(null)
const setFormData = async (refundNo: string = '') => {
loading.value = true
formData.value = null
await getPayRefundInfo(refundNo)
.then(({ data }) => {
formData.value = data
refundList.value.push(data)
})
.catch(() => {
})
await getPayRefundInfo(refundNo).then(({ data }) => {
formData.value = data
refundList.value.push(data)
})
loading.value = false
}
if (refundNo) setFormData(refundNo)

View File

@ -105,4 +105,5 @@ const returnFn = () => {
margin-right: auto;
}
}
}</style>
}
</style>

View File

@ -20,8 +20,8 @@
<div class="flex justify-between items-center mt-[18px]">
<div class="w-[800px] text-[14px] whitespace-nowrap">
<el-scrollbar :always="true">
<span :class="['mr-[12px] cursor-pointer', {'text-[var(--el-color-primary)]': params.app == ''}]" @click="cutAppFn('')">所有应用</span>
<span :class="['mr-[12px] cursor-pointer', {'text-[var(--el-color-primary)]': params.app == item.key}]" @click="cutAppFn(item.key)" v-for="(item,index) in addonList" :key="index">{{item.title}}</span>
<span :class="['px-[10px] cursor-pointer h-[35px] leading-[35px] inline-block', {'text-[var(--el-color-primary)]': params.app == ''}]" @click="cutAppFn('')">所有应用</span>
<span :class="['px-[10px] cursor-pointer h-[35px] leading-[35px] inline-block', {'text-[var(--el-color-primary)]': params.app == item.key}]" @click="cutAppFn(item.key)" v-for="(item,index) in addonList" :key="index">{{item.title}}</span>
</el-scrollbar>
</div>
<el-input v-model="params.keywords" class="!w-[300px] !h-[34px]" placeholder="请输入要搜索的站点名称" @keyup.enter.native="getHomeSiteFn()">
@ -73,9 +73,9 @@
<el-dialog v-model="createSiteDialog" width="54vw" :destroy-on-close="true" style="border-radius: 25px;">
<template #title>
<div class="text-[#333333] text-[22px] ml-[10px] leading-[1]">创建站点</div>
<div class="text-[#333333] text-[22px] ml-[15px] leading-[1] mt-[10px]">创建站点</div>
</template>
<div class="flex flex-col mx-[20px] h-[430px]">
<div class="flex flex-col mx-[25px] h-[430px] mt-[15px]">
<div class="flex items-center">
<div class="text-[18px] text-[#333333]">站点名称</div>
<div class="w-[420px] h-[34px] ml-[10px]">
@ -89,7 +89,7 @@
<div class="flex-1 mt-[20px] h-[160px]" v-show="createSiteData.step == 1">
<div class="text-[18px] text-[#333333]">店铺套餐</div>
<el-scrollbar class="w-full mt-[10px] -ml-[10px]" height="350px">
<el-scrollbar class="w-full mt-[10px] meal-site -ml-[10px]" height="350px">
<div class="w-full whitespace-nowrap" v-show="createSiteData.step == 1">
<div v-for="(item, index) in siteGroup" :key="index"
class="inline-flex flex-col w-[300px] h-[330px] box-border rounded-[17px] border-transparent border-[2px] border-solid create-site-item my-[10px]"
@ -116,7 +116,7 @@
</div>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="createSiteFn" class="w-[118px] h-[44px] text-[16px]">创建站点</el-button>
<el-button type="primary" @click="createSiteFn" class="w-[118px] h-[44px] mt-[10px] text-[16px]">创建站点</el-button>
</span>
</template>
</el-dialog>
@ -327,4 +327,7 @@ watch(() => createSiteDialog.value, () => {
.create-site-name .el-input__wrapper{
border-radius: 6px !important;
}
.meal-site{
height: calc(100% - 30px) !important;
}
</style>

View File

@ -127,10 +127,8 @@ import { AnyObject } from '@/types/global'
import useStyleStore from '@/stores/modules/style'
const loading = ref(true)
const newSiteStat = ref<any>(null)
const addUser = ref<any>(null)
const styleStore = useStyleStore()
interface NewVersion{
@ -153,7 +151,7 @@ const newVersion = ref<NewVersion>({
getFrameworkNewVersion().then(({ data }) => {
newVersion.value = data
}).catch()
})
const statInfo = ref<StatInfo>({
today_data: {},
@ -165,6 +163,7 @@ const statInfo = ref<StatInfo>({
site_group_stat: {},
app: {}
})
const getStatInfoFn = async (id: number = 0) => {
statInfo.value = await (await getStatInfo()).data
loading.value = false
@ -255,6 +254,7 @@ const toHref = (url:any, id:any) => {
const toApplication = () => {
window.open('https://www.niucloud.com/app')
}
//
const time = ref('')
const nowTime = () => {

View File

@ -22,8 +22,7 @@
<el-form-item :label="t('link')" v-show="wapPreview">
<el-input readonly :value="wapPreview">
<template #append>
<el-button @click="copyEvent(wapPreview)" class="bg-primary copy">{{ t('copy') }}
</el-button>
<el-button @click="copyEvent(wapPreview)" class="bg-primary copy">{{ t('copy') }}</el-button>
</template>
</el-input>
</el-form-item>

File diff suppressed because one or more lines are too long

View File

@ -87,7 +87,7 @@
<template #default="{ row }">
<el-button class="!text-[13px]" v-if="row.install_info && Object.keys(row.install_info)?.length && row.install_info.version != row.version" type="primary" link @click="upgradeAddonFn(row.key)">{{ t('upgrade') }}</el-button>
<el-button class="!text-[13px]" v-if="row.install_info && Object.keys(row.install_info)?.length" type="primary" link @click="uninstallAddonFn(row.key)">{{ t('unload') }}</el-button>
<template v-if="row.is_download && Object.keys(row.install_info) <= 0">
<template v-if="row.is_download && (!row.install_info || !Object.keys(row.install_info).length)">
<el-button class="!text-[13px]" type="primary" link @click="installAddonFn(row.key)">{{ t('install') }}</el-button>
<el-button class="!text-[13px]" type="primary" link @click="deleteAddonFn(row.key)">{{ t('delete') }}</el-button>
</template>
@ -145,8 +145,7 @@
您在官方应用市场购买任意一款应用即可获得授权码输入正确授权码认证通过后即可支持在线升级和其它相关服务</p>
<div class="flex justify-end mt-[36px]">
<el-button class="w-[182px] !h-[48px]" plain @click="market">去应用市场逛逛</el-button>
<el-button class="w-[100px] !h-[48px]" plain
@click="getAuthCodeDialog.hide()">关闭</el-button>
<el-button class="w-[100px] !h-[48px]" plain @click="getAuthCodeDialog.hide()">关闭</el-button>
</div>
</div>
<template #reference>
@ -376,7 +375,7 @@ import { ref, reactive, watch, h } from 'vue'
import { t } from '@/lang'
import { getAddonLocal, uninstallAddon, installAddon, preInstallCheck, cloudInstallAddon, getAddonInstalltask, getAddonCloudInstallLog, preUninstallCheck, cancelInstall } from '@/app/api/addon'
import { deleteAddonDevelop } from '@/app/api/tools'
import { downloadVersion, getAuthinfo, setAuthinfo } from '@/app/api/module'
import { downloadVersion, getAuthInfo, setAuthInfo } from '@/app/api/module'
import { ElMessage, ElMessageBox, ElNotification, FormInstance, FormRules } from 'element-plus'
import 'vue-web-terminal/lib/theme/dark.css'
import { Terminal, TerminalFlash } from 'vue-web-terminal'
@ -432,7 +431,7 @@ const downEvent = (param: Record<string, any>, isDown = false) => {
}
const authCode = ref('')
getAuthinfo().then(res => {
getAuthInfo().then(res => {
if (res.data.data && res.data.data.auth_code) {
authCode.value = res.data.data.auth_code
}
@ -831,7 +830,7 @@ const saveLoading = ref(false)
const authLoading = ref(true)
const checkAppMange = () => {
authLoading.value = true
getAuthinfo()
getAuthInfo()
.then((res) => {
authLoading.value = false
if (res.data.data && res.data.data.length != 0) {
@ -871,7 +870,7 @@ const save = async (formEl: FormInstance | undefined) => {
if (valid) {
saveLoading.value = true
setAuthinfo(formData)
setAuthInfo(formData)
.then(() => {
saveLoading.value = false
setTimeout(() => {

View File

@ -65,8 +65,7 @@
</el-form-item>
<el-form-item prop="password">
<el-input type="password" v-model="form.password" @keyup.enter="handleLogin(formRef)"
autocomplete="new-password" :show-password="true" class="w-50 m-1 h-[40px]" :placeholder="t('passwordPlaceholder')">
<el-input type="password" v-model="form.password" @keyup.enter="handleLogin(formRef)" autocomplete="new-password" :show-password="true" class="w-50 m-1 h-[40px]" :placeholder="t('passwordPlaceholder')">
<template #prefix>
<icon name="element Lock" />
</template>
@ -74,8 +73,7 @@
</el-form-item>
<el-form-item>
<el-button type="primary" class="mt-[30px] h-[40px] w-full" @click="handleLogin(formRef)" :loading="loading">{{ loading ? t('logging') :
t('login') }}</el-button>
<el-button type="primary" class="mt-[30px] h-[40px] w-full" @click="handleLogin(formRef)" :loading="loading">{{ loading ? t('logging') : t('login') }}</el-button>
</el-form-item>
</el-form>
</div>

View File

@ -350,7 +350,6 @@ const setContinueSignAward = async () => {
setMemberBenefitsContents(contentData, continue_award.value, 0, 1)
if (!isEdit) {
formData.continue_award.push(JSON.parse(JSON.stringify(continue_award.value)))
} else {

View File

@ -37,7 +37,7 @@
<template #default="{ row }">
<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]" v-else src="@/app/assets/images/default_headimg.png" 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">
<span>{{ row.member.nickname || '' }}</span>
</div>

View File

@ -18,7 +18,7 @@
<template #default="{ row }">
<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]" v-else src="@/app/assets/images/default_headimg.png" 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">
<span>{{ row.member.nickname || '' }}</span>
<span>{{ row.member.mobile || '' }}</span>
@ -157,7 +157,6 @@ const deleteEvent = (id: number) => {
).then(() => {
deleteVerifier(id).then(() => {
loadVerifierList()
}).catch(() => {
})
})
}

View File

@ -89,7 +89,7 @@
<template #default="{ row }">
<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]" v-else src="@/app/assets/images/default_headimg.png" 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">
<span>{{ row.member.nickname || '' }}</span>
</div>

View File

@ -92,7 +92,7 @@
<template #default="{ row }">
<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]" v-else src="@/app/assets/images/default_headimg.png" 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">
<span>{{ row.member.nickname || '' }}</span>
</div>

View File

@ -73,7 +73,7 @@ const sexSelectData = ref([
name: t('girlSex')
}
])
const labelSelectData = ref(null)
const labelSelectData:any = ref(null)
//
const getMemberLabelAllFn = async () => {
labelSelectData.value = await (await getMemberLabelAll()).data
@ -127,7 +127,11 @@ const confirm = async (formEl: FormInstance | undefined) => {
if (repeat.value) return
repeat.value = true
const val = saveData[type.value] ? deepClone(saveData[type.value]) : ''
let val = saveData[type.value];
if(type.value == 'member_label'){
// saveData[type.value]
val = saveData[type.value] && saveData[type.value].length ? deepClone(saveData[type.value]).join(',').split(',') : '';
}
const data = ref({
member_id: memberId.value,
@ -155,8 +159,20 @@ const setDialogType = async (row: any = null) => {
memberId.value = row.id
saveData[type.value] = row.data[type.value]
if (type.value == 'member_label' && saveData[type.value]) {
saveData[type.value].forEach((item:any, index:any) => {
saveData[type.value][index] = Number.parseFloat(item)
saveData[type.value].forEach((item: any, index: any) => {
let isExist = false;
for (let i = 0; i < labelSelectData.value.length; i++) {
if (labelSelectData.value[i].label_id == item) {
isExist = true;
break;
}
}
if (isExist) {
saveData[type.value][index] = Number.parseFloat(item)
} else {
saveData[type.value].splice(index, 1); // id
}
})
}
loading.value = false

View File

@ -5,7 +5,7 @@
<el-form-item :label="t('headimg')" >
<div class="flex items-center">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="formData.member.headimg" :src="img(formData.member.headimg)" alt="" >
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="" >
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
</div>
</el-form-item>

View File

@ -5,7 +5,7 @@
<el-form-item :label="t('headimg')">
<div class="flex items-center">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="formData.member.headimg" :src="img(formData.member.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="">
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
</div>
</el-form-item>

View File

@ -5,7 +5,7 @@
<el-form-item :label="t('headimg')" >
<div class="flex items-center">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="formData.headimg" :src="img(formData.headimg)" alt="" >
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="" >
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
</div>
</el-form-item>

View File

@ -5,7 +5,7 @@
<el-form-item :label="t('headimg')" >
<div class="flex items-center">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="formData.member.headimg" :src="img(formData.member.headimg)" alt="" >
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" alt="" >
<img class="w-[50px] h-[50px] mr-[10px] rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
</div>
</el-form-item>

View File

@ -43,7 +43,7 @@
<template #default="{ row }">
<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]" v-else src="@/app/assets/images/default_headimg.png" 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">
<span>{{ row.member.nickname || '' }}</span>
</div>

View File

@ -57,7 +57,7 @@
<template #default="{ row }">
<div class="flex items-center">
<img class="w-[50px] h-[50px] mr-[10px]" v-if="row.headimg" :src="img(row.headimg)" alt="">
<img class="w-[50px] h-[50px] mr-[10px]" v-else src="@/app/assets/images/default_headimg.png" 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">
<span>{{ row.nickname || '' }}</span>
</div>
@ -72,7 +72,7 @@
</template>
</el-table-column>
<el-table-column prop="balance" :label="t('balance')" min-width="130" align="right" />
<el-table-column prop="member_label" :label="t('lable')" min-width="120" align="center">
<el-table-column prop="member_label" :label="t('memberLabelTag')" min-width="120" align="center">
<template #default="{ row }">
<div class="flex flex-col items-center">
<div v-for="(item, key) in row.member_label_array" class="my-[3px]" :key="key">
@ -105,7 +105,7 @@
<template #default="{ row }">
<div class="flex items-center">
<el-button type="primary" link @click="detailEvent(row)">{{ t('detail') }}</el-button>
<el-button type="primary" link @click="setMemberLablel(row)">{{ t('setLable') }}</el-button>
<el-button type="primary" link @click="setMemberLabel(row)">{{ t('setLabel') }}</el-button>
<!-- <el-button type="primary" link @click="deleteEvent(row)">{{ t('memberDelete') }}</el-button> -->
</div>
</template>
@ -205,27 +205,14 @@ const router = useRouter()
const addMemberDialog: Record<string, any> | null = ref(null)
const editMemberDialog: Record<string, any> | null = ref(null)
/**
* 获取标签
*/
function memberLablel(res: any) {
let data
if (!res.member_label_array) return ''
data = res.member_label_array.map((item: any) => {
return item.label_name
})
data = data.toString()
return data
}
/**
* 设置标签
*/
function setMemberLablel(res: any) {
function setMemberLabel(res: any) {
const data = ref({
type: 'member_label',
id: res.member_id,
title: t('setLable'),
title: t('setLabel'),
data: res
})
editMemberDialog.value.setDialogType(data.value)

View File

@ -13,7 +13,7 @@
<span class="text-[14px] min-w-[110px] text-right mr-[20px]">{{ t('headimg') }}</span>
<span class="flex items-end text-[14px]">
<img class="w-[50px] h-[50px] inline-block" v-if="formData.headimg" :src="img(formData.headimg)" alt="">
<img class="w-[50px] h-[50px] inline-block" v-else src="@/app/assets/images/default_headimg.png" alt="">
<img class="w-[50px] h-[50px] inline-block rounded-full" v-else src="@/app/assets/images/member_head.png" alt="">
<el-icon @click="editMemberInfo('headimg')" class="-bottom-[2px] -right-[4px] cursor-pointer">
<EditPen color="#273CE2" />
</el-icon>

View File

@ -71,7 +71,7 @@
<template #default="{ row }">
<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]" v-else src="@/app/assets/images/default_headimg.png" 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">
<span>{{ row.member.nickname || '' }}</span>
</div>

View File

@ -7,8 +7,15 @@
</div>
<!-- 组件公共属性 -->
<slot name="common"></slot>
<slot name="common"></slot>
<el-form label-width="80px" class="px-[10px]">
<el-form-item :label="t('imgShape')">
<div class="flex items-center">
<div class="bg-[#DFDFDF] cursor-pointer w-[50px] h-[50px] border-solid border-[1px] border-transparent rounded-[50%]" :class="{'border-[var(--el-color-primary)]': posterStore.editComponent.shape == 'circle'}" @click="imgShapeChangeFn('circle')"></div>
<div class="bg-[#DFDFDF] cursor-pointer w-[50px] h-[50px] ml-[25px] border-solid border-[1px] border-transparent" :class="{'border-[var(--el-color-primary)]': posterStore.editComponent.shape == 'normal'}" @click="imgShapeChangeFn('normal')"></div>
</div>
</el-form-item>
</el-form>
</div>
</template>
@ -19,6 +26,11 @@ import usePosterStore from '@/stores/modules/poster'
const posterStore = usePosterStore()
//
const imgShapeChangeFn = (data)=>{
posterStore.editComponent.shape = data;
}
defineExpose({})
</script>

View File

@ -18,7 +18,7 @@
<div class="text-sm text-gray-400 mt-[10px]">{{ t('bgUrlTips') }}</div>
</el-form-item>
<el-form-item :label="t('bgColor')" v-show="posterStore.global.bgType == 'color'">
<el-color-picker v-model="posterStore.editComponent.bgColor" show-alpha :predefine="posterStore.predefineColors" />
<el-color-picker v-model="posterStore.editComponent.bgColor" :predefine="posterStore.predefineColors" />
</el-form-item>
<el-form-item :label="t('statusLabel')" class="display-block">
<el-switch v-model="posterStore.status" :active-value="1" :inactive-value="0"/>

View File

@ -1,6 +1,6 @@
<template>
<div class="pointer-events-none max-w-[360px]" :style="componentStyle">
<img src="@/app/assets/images/default_headimg.png" class="w-full h-full" />
<div class="pointer-events-none max-w-[720px]" :style="componentStyle">
<img src="@/app/assets/images/default_headimg_square.jpg" class="w-full h-full" />
</div>
</template>
@ -22,6 +22,9 @@ const data = computed(()=> {
const componentStyle = computed(()=> {
var style = '';
style += `width: ${prop.value.width}px;`;
if(prop.value.shape == 'circle'){
style += `border-radius: 50%; overflow: hidden;`;
}
return style;
})

View File

@ -1,5 +1,5 @@
<template>
<div class="pointer-events-none max-w-[360px]" :style="componentStyle">
<div class="pointer-events-none max-w-[720px]" :style="componentStyle">
<img v-if="data.value" :src="img(data.value)" class="w-full h-full" />
<img v-else :src="img('static/resource/images/diy/crack_figure.png')" class="w-full h-full" />
</div>

View File

@ -4,6 +4,9 @@
<script lang="ts" setup>
import { ref,computed } from 'vue'
import usePosterStore from '@/stores/modules/poster'
const posterStore = usePosterStore()
const prop = defineProps({
value: {
@ -18,7 +21,22 @@ const data = computed(()=> {
const componentStyle = computed(()=> {
var style = '';
style += `font-size: ${prop.value.fontSize}px;color: ${prop.value.fontColor};`;
style += `font-size: ${prop.value.fontSize}px;color: ${prop.value.fontColor};line-height: ${prop.value.lineHeight + prop.value.fontSize}px;`;
if(prop.value.x == 'left' || prop.value.x == 'center' || prop.value.x == 'right'){
style += `text-align: ${prop.value.x};`;
}
if(prop.value.weight){
style += `font-weight: bold;`;
}
if(!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf'){
style += `font-family: poster_default_font;`;
}
let box: any = document.getElementById(prop.value.id)
if (box) {
style += `width:${box.offsetWidth}px;height:${box.offsetHeight}px;`;
}else{
style += `width:${prop.value.width}px;height:${prop.value.height}px;`;
}
return style;
})

View File

@ -1,5 +1,5 @@
<template>
<div class="pointer-events-none max-w-[360px]" :style="componentStyle">
<div class="pointer-events-none max-w-[720px]" :style="componentStyle">
<img :src="img('static/resource/images/diy/qrcode.png')" class="w-full h-full" />
</div>
</template>

View File

@ -4,6 +4,9 @@
<script lang="ts" setup>
import { ref,computed } from 'vue'
import usePosterStore from '@/stores/modules/poster'
const posterStore = usePosterStore()
const prop = defineProps({
value: {
@ -18,10 +21,21 @@ const data = computed(()=> {
const componentStyle = computed(()=> {
var style = '';
style += `font-size: ${prop.value.fontSize}px;color: ${prop.value.fontColor};`;
style += `font-size: ${prop.value.fontSize}px;color: ${prop.value.fontColor};line-height: ${prop.value.lineHeight + prop.value.fontSize}px;`;
if(prop.value.x == 'left' || prop.value.x == 'center' || prop.value.x == 'right'){
style += `text-align: ${prop.value.x};`;
}
if(prop.value.weight){
style += `font-weight: bold;`;
}
if(!prop.value.fontFamily || prop.value.fontFamily == 'static/font/SourceHanSansCN-Regular.ttf'){
style += `font-family: poster_default_font;`;
}
let box: any = document.getElementById(prop.value.id)
if (box) {
style += `width:${box.offsetWidth}px;height:${box.offsetHeight}px;`;
}else{
style += `width:${prop.value.width}px;height:${prop.value.height}px;`;
}
return style;
})

View File

@ -12,12 +12,14 @@
<span class="mr-[5px] text-[14px]">{{ t('decorating') }}{{ posterStore.typeName }}</span>
</div>
<div>
<div class="flex items-center">
<span class="text-white mr-[10px] text-base">{{ t('templatePosterPlaceholder') }}</span>
<el-select size="small" v-model="template" class="w-[180px]" :placeholder="t('templatePosterPlaceholder')" @change="changeTemplatePoster">
<el-option :label="t('templatePosterEmpty')" value="" />
<el-option v-for="(item, index) in templatePoster" :label="item.name" :value="index" :key="index"/>
</el-select>
<div class="w-[180px]">
<el-select size="small" v-model="template" :placeholder="t('templatePosterPlaceholder')" @change="changeTemplatePoster">
<el-option :label="t('templatePosterEmpty')" value="" />
<el-option v-for="(item, index) in templatePoster" :label="item.name" :value="index" :key="index"/>
</el-select>
</div>
</div>
<div class="flex-1"></div>
<el-button @click="preview()" v-if="posterStore.id">{{ t('preview') }}</el-button>
@ -55,7 +57,7 @@
<div class="title-wrap text-center text-[14px]">{{ posterStore.name }}</div>
</div>
</div>
<div class="preview-block relative">
<div class="preview-block relative max-h-[640px]">
<ul class="quick-action absolute text-center -right-[70px] top-[20px] w-[42px] rounded shadow-md">
<el-tooltip effect="light" :content="t('moveUpComponentZIndex')" placement="right">
<icon name="iconfont iconjiantoushang" size="20px" class="block cursor-pointer leading-[40px]" @click="posterStore.moveUpComponent" />
@ -76,8 +78,8 @@
<!-- 组件预览渲染区域 -->
<div class="preview-iframe" :style="posterStore.getGlobalStyle()" @click="posterStore.changeCurrentIndex(-99)">
<div class="item-wrap area-box select-none max-w-[360px] cursor-move" v-for="(item,index) in posterStore.value" :id="item.id" :key="item.id"
:style="{ top: item.y + 'px', left: item.x + 'px', zIndex: item.zIndex, transform : 'rotate(' + item.angle + 'deg)' }"
<div class="item-wrap area-box select-none max-w-[720px] cursor-move" v-for="(item,index) in posterStore.value" :id="item.id" :key="item.id"
:style="previewIframeStyle(item)"
:class="{ 'selected' : posterStore.currentIndex == index }"
@mousedown="posterStore.mouseDown($event,item.id,index)"
@click.stop="posterStore.changeCurrentIndex(index,item)"
@ -104,7 +106,7 @@
<el-card class="box-card" shadow="never">
<template #header>
<div class="card-header flex justify-between items-center">
<span class="title flex-1">{{ posterStore.currentIndex == -99 ? t('posterSet') : posterStore.editComponent.componentTitle }}</span>
<span class="title flex-1">{{ posterStore.currentIndex == -99 ? t('posterSet') : posterStore.editComponent?.componentTitle }}</span>
</div>
</template>
@ -114,7 +116,7 @@
<template #common>
<div class="edit-attr-item-wrap">
<h3 class="mb-[10px]">{{ t('componentStyleTitle') }}</h3>
<el-form label-width="80px" class="px-[10px]">
<el-form label-width="100px" class="px-[10px]">
<!-- 角度旋转这里根据类型展示 文本图片绘画的编辑属性 -->
@ -122,22 +124,30 @@
<span>{{ posterStore.editComponent.zIndex }}</span>
</el-form-item>
<el-form-item :label="t('coordinate')">
<!-- <el-form-item :label="t('coordinate')">
<el-slider v-model="posterStore.editComponent.x" show-input size="small" class="ml-[10px]" :min="0" :max="posterStore.getMaxX()" />
<div class="my-[10px]"></div>
<el-slider v-model="posterStore.editComponent.y" show-input size="small" class="ml-[10px]" :min="0" :max="posterStore.getMaxY()" />
</el-form-item>
<div class="ml-[92px] mb-[18px] text-sm text-gray-400">{{ t('coordinateTips') }}</div>
<div class="ml-[92px] mb-[18px] text-sm text-gray-400">{{ t('coordinateTips') }}</div> -->
<!-- 文本 -->
<template v-if="posterStore.editComponent.type == 'text'">
<el-form-item :label="t('textFontSize')">
<el-slider v-model="posterStore.editComponent.fontSize" show-input size="small" class="ml-[10px]" :min="14" :max="36" />
<el-slider v-model="posterStore.editComponent.fontSize" show-input size="small" class="ml-[10px]" :min="14" :max="50" />
</el-form-item>
<el-form-item :label="t('textColor')">
<el-color-picker v-model="posterStore.editComponent.fontColor" />
</el-form-item>
<el-form-item :label="t('weight')">
<el-switch v-model="posterStore.editComponent.weight" />
</el-form-item>
<!-- <el-form-item :label="t('space')">
<el-slider v-model="posterStore.editComponent.space" show-input size="small" class="ml-[10px]" :min="0" :max="20" />
</el-form-item> -->
<el-form-item :label="t('lineHeight')">
<el-slider v-model="posterStore.editComponent.lineHeight" show-input size="small" class="ml-[10px]" :min="0" :max="50" />
</el-form-item>
</template>
<!-- 图片 -->
@ -160,6 +170,31 @@
</el-form-item>
</template>
<!-- 对齐方式 -->
<template v-if="posterStore.editComponent.type != 'draw' && posterStore.editComponent.type != 'image' && posterStore.editComponent.type != 'qrcode'">
<el-form-item :label="t('horizontalAlignment')">
<ul class="flex items-center">
<template v-for="(item,i) in xAlignList">
<li :class="['w-[50px] h-[32px] flex items-center justify-center border-solid border-[1px] border-[#eee] cursor-pointer', {'border-r-transparent': xAlignList.length != (i+1)}, (item.className == posterStore.editComponent.x) ? '!border-[var(--el-color-primary)]' : '' ]" @click="alignChangeFn('x',item)">
<span :class="['iconfont !text-[20px]', item.src]" :title="item.name"></span>
</li>
</template>
</ul>
<div class="text-sm mt-[10px] leading-[1.4] text-gray-400">{{ t('AlignTips') }}</div>
</el-form-item>
<el-form-item :label="t('verticalAlignment')">
<ul class="flex items-center">
<template v-for="(item,i) in yAlignList">
<li :class="['w-[50px] h-[32px] flex items-center justify-center border-solid border-[1px] border-[#eee] cursor-pointer', {'border-r-transparent': yAlignList.length != (i+1)}, (item.className == posterStore.editComponent.y) ? '!border-[var(--el-color-primary)]' : '' ]" @click="alignChangeFn('y',item)">
<span :class="['iconfont !text-[20px]', item.src]" :title="item.name"></span>
</li>
</template>
</ul>
</el-form-item>
</template>
<!-- <el-form-item :label="t('旋转角度')">-->
<!-- <el-slider v-model="posterStore.editComponent.angle" show-input size="small" class="ml-[10px]" :min="0" :max="360" />-->
<!-- </el-form-item>-->
@ -207,10 +242,13 @@ const posterStore = usePosterStore()
const route = useRoute()
const router = useRouter()
route.query.id = route.query.id || 0
route.query.type = route.query.type || '' //
route.query.name = route.query.name || ''
route.query.back = route.query.back || '/site/poster/list'
if(route && route.query){
route.query.id = route.query.id || 0
route.query.type = route.query.type || '' //
route.query.name = route.query.name || ''
route.query.back = route.query.back || '/site/poster/list'
}
const backPath:any = route.query.back
const template = ref('');
@ -224,6 +262,90 @@ const activeNames = ref(componentType)
const handleChange = (val: string[]) => {
}
const previewIframeStyle = (data)=>{
let style = {
transform: '',
zIndex: '',
top: '',
left: '',
right: '',
bottom: ''
};
style.transform = `rotate(${data.angle}deg)`;
style.zIndex = `${data.zIndex}`;
switch(data.y) {
case 'top':
style.top = 0;
break;
case 'center':
style.top = '50%';
style.transform = style.transform + ' translateY(-50%)';
break;
case 'bottom':
style.bottom = 0;
break;
default:
style.top = data.y + 'px';
}
switch(data.x) {
case 'left':
style.left = 0;
break;
case 'center':
style.left = '50%';
style.transform = style.transform + ' translateX(-50%)';
break;
case 'right':
style.right = 0;
break;
default:
style.left = data.x + 'px';
}
// console.log(data.x,data.y)
return style;
}
//
const xAlignList = ref([
{
name: '左',
src: 'iconzuoduiqi1',
className: 'left'
},
{
name: '中',
src: 'iconshuipingjuzhong1',
className: 'center'
},
{
name: '右',
src: 'iconyouduiqi1',
className: 'right'
}
])
//
const yAlignList = ref([
{
name: '上',
src: 'icondingduiqi1',
className: 'top'
},
{
name: '中',
src: 'iconchuizhijuzhong1',
className: 'center'
},
{
name: '下',
src: 'icondiduiqi1',
className: 'bottom'
},
])
const alignChangeFn = (type,data)=>{
posterStore.editComponent[type] = data.className;
}
//
const isChange = ref(true) // truefalse
const goBack = () => {
@ -374,17 +496,17 @@ const save = (callback: any) => {
if (isRepeat.value) return
isRepeat.value = true
posterStore.value.forEach((item:any,index: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;
if (item.type == 'draw') {
// [x,y]
let leftTop = [item.x * 2, item.y * 2]; //
let rightTop = [(item.x + item.width) * 2, item.y * 2]; //
let rightBottom = [(item.x + item.width) * 2, (item.y + item.height) * 2]; //
let leftBottom = [item.x * 2, (item.y + item.height) * 2]; //
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];
}
}
@ -479,12 +601,14 @@ const preview = () => {
}
.preview-iframe {
transform: scale(0.5);
margin: 0 auto;
width: 360px;
height: 640px;
background-size: 100% 640px;
width: 720px;
height: 1280px;
background-size: 100% 1280px;
background-repeat: no-repeat;
position: relative;
transform-origin: left top;
.item-wrap {
position: absolute;
@ -522,8 +646,8 @@ const preview = () => {
.box2,
.box3,
.box4 {
width: 10px;
height: 10px;
width: 20px;
height: 20px;
background-color: #fff;
position: absolute;
border-radius: 50%;
@ -532,26 +656,26 @@ const preview = () => {
}
.box1 {
top: -4px;
left: -4px;
top: -8px;
left: -8px;
cursor: nw-resize;
}
.box2 {
top: -4px;
right: -4px;
top: -8px;
right: -8px;
cursor: ne-resize;
}
.box3 {
left: -4px;
bottom: -4px;
left: -8px;
bottom: -8px;
cursor: sw-resize;
}
.box4 {
bottom: -4px;
right: -4px;
bottom: -8px;
right: -8px;
cursor: se-resize;
}
}

View File

@ -0,0 +1,363 @@
<template>
<div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
</el-card>
<el-form class="page-form" :model="formData" :rules="formRules" label-width="150px" ref="formRef" v-loading="loading">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title !text-sm">{{ t('printerSet') }}</h3>
<el-form-item :label="t('printerName')" prop="printer_name">
<el-input v-model.trim="formData.printer_name" clearable :placeholder="t('printerNamePlaceholder')" class="input-width" maxlength="20" />
</el-form-item>
<el-form-item :label="t('brand')" prop="brand">
<el-select v-model="formData.brand" :placeholder="t('brandPlaceholder')" clearable>
<el-option v-for="(item,key) in brandList" :key="key" :label="item" :value="key" />
</el-select>
</el-form-item>
<el-form-item :label="t('printerCode')" prop="printer_code">
<div>
<el-input v-model.trim="formData.printer_code" clearable :placeholder="t('printerCodePlaceholder')" class="input-width" maxlength="30" />
<p class="text-[12px] text-[#b2b2b2]">{{ t('printerCodeTips') }}</p>
</div>
</el-form-item>
<el-form-item :label="t('printerKey')" prop="printer_key">
<div>
<el-input v-model.trim="formData.printer_key" clearable :placeholder="t('printerKeyPlaceholder')" class="input-width" maxlength="30" />
<p class="text-[12px] text-[#b2b2b2]">{{ t('printerKeyTips') }}</p>
</div>
</el-form-item>
<el-form-item :label="t('openId')" prop="open_id">
<div>
<el-input v-model.trim="formData.open_id" clearable :placeholder="t('openIdPlaceholder')" class="input-width" maxlength="30" />
<p class="text-[12px] text-[#b2b2b2]">{{ t('openIdTips') }}</p>
</div>
</el-form-item>
<el-form-item :label="t('apikey')" prop="apikey">
<div>
<el-input v-model.trim="formData.apikey" clearable :placeholder="t('apikeyPlaceholder')" class="input-width" maxlength="60" />
<p class="text-[12px] text-[#b2b2b2]">{{ t('apikeyTips') }}</p>
</div>
</el-form-item>
<el-form-item :label="t('printWidth')" prop="print_width">
<el-radio-group v-model="formData.print_width">
<el-radio value="58mm">58mm</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('status')">
<el-switch v-model="formData.status" :active-value="1" :inactive-value="0" />
</el-form-item>
</el-card>
<el-card v-for="(item,index) in printerType" :key="item.key" class="box-card !border-none" shadow="never">
<h3 class="panel-title !text-sm">{{ item.title }}</h3>
<div class="flex mb-[10px] py-[8px] bg-[#F5F7F9] text-[14px]">
<div class="px-[12px] w-[200px]">{{ t('printTrigger') }}</div>
<div class="px-[12px] w-[100px]">{{ t('status') }}</div>
<div class="px-[12px] w-[250px]">{{ t('usePrintTemplate') }}</div>
<div class="px-[12px] w-[300px] flex-1" v-for="childItem in item.condition" :key="childItem.key">{{ childItem.title }}</div>
<div class="px-[12px] w-[200px]">{{ t('printNum') }}</div>
</div>
<template v-if="item.trigger">
<div class="flex bg-[#f8f8f9] mb-[10px] py-[20px]" v-for="(triggerItem,triggerKey) in item.trigger" :key="triggerKey">
<template v-if="formData.value[item.key]['trigger_' + triggerKey]">
<div class="font-bold w-[200px] px-[12px]">{{ triggerItem }}</div>
<div class="w-[100px] px-[12px]">
<el-switch v-model="formData.value[item.key]['trigger_' + triggerKey].status" :active-value="1" :inactive-value="0" />
</div>
<div class="w-[250px] px-[12px]">
<el-select v-model="formData.value[item.key]['trigger_' + triggerKey].template_id" :placeholder="t('请选择小票打印模板')" clearable>
<el-option v-for="templateItem in templateList[item.key]" :key="templateItem.template_id" :label="templateItem.template_name" :value="templateItem.template_id" />
</el-select>
</div>
<template v-for="childItem in item.condition">
<div class="w-[300px] px-[12px] flex-1" v-if="childItem.type == 'checkbox'">
<el-checkbox-group v-model="formData.value[item.key]['trigger_' + triggerKey][childItem.key]">
<el-checkbox v-for="(checkboxItem, index) in childItem.list" :label="checkboxItem.value" :key="index">{{ checkboxItem.name }}</el-checkbox>
</el-checkbox-group>
</div>
</template>
<div class="w-[200px] px-[12px]">
<el-select v-model="formData.value[item.key]['trigger_' + triggerKey].print_num">
<el-option label="1联" :value="1" />
<el-option label="2联" :value="2" />
<el-option label="3联" :value="3" />
<el-option label="4联" :value="4" />
</el-select>
</div>
</template>
</div>
</template>
</el-card>
</el-form>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" :loading="repeat" @click="confirm(formRef)">{{ t('save') }}</el-button>
<el-button @click="back()">{{ t('cancel') }}</el-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import { FormInstance, ElMessage } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { deepClone } from '@/utils/common';
import { addPrinter, editPrinter,getPrinterInfo,getPrinterType,getPrinterBrand,getPrinterTemplateList } from '@/app/api/printer'
const route = useRoute()
const router = useRouter()
const repeat = ref(false)
const loading = ref(true)
const pageName = route.meta.title
/**
* 表单数据
*/
const initialFormData:any = {
printer_id: route.query.printer_id || 0,
brand: '',
printer_name: '',
printer_code: '',
printer_key: '',
open_id: '',
apikey: '',
template_type: [],
trigger: [],
value: {},
print_width: '58mm',
status: 1,
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
printer_name: [
{ required: true, message: t('printerNamePlaceholder'), trigger: 'blur' },
],
brand: [
{ required: true, message: t('brandPlaceholder'), trigger: 'blur' },
],
printer_code: [
{ required: true, message: t('printerCodePlaceholder'), trigger: 'blur' },
],
printer_key: [
{ required: true, message: t('printerKeyPlaceholder'), trigger: 'blur' },
],
open_id: [
{ required: true, message: t('openIdPlaceholder'), trigger: 'blur' },
],
apikey: [
{ required: true, message: t('apikeyPlaceholder'), trigger: 'blur' },
]
}
})
const printerType = ref([])
const init = async ()=> {
await getPrinterType({}).then((res: any) => {
if (res.data) {
printerType.value = res.data;
for (let i = 0; i < printerType.value.length; i++) {
let item: any = printerType.value[i];
formData.value[item.key] = {};
let extendData: any = {};
for (let ci = 0; ci < item.condition.length; ci++) {
let condition = item.condition[ci];
extendData[condition.key] = [];
if (condition.type == 'checkbox') {
extendData[condition.key] = []; //
for (let k = 0; k < condition.list.length; k++) {
extendData[condition.key].push(condition.list[k].value);
}
}
}
for (let key in item.trigger) {
formData.value[item.key]['trigger_' + key] = {
status: 1,
template_id: '',
print_num: 1,
};
Object.assign(formData.value[item.key]['trigger_' + key], deepClone(extendData));
}
}
}
if (!formData.printer_id) {
loading.value = false
}
})
if (formData.printer_id) {
getPrinterInfo(formData.printer_id).then((res: any) => {
let data = res.data;
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) {
if (key == 'value') {
for (let ck in formData[key]){
Object.assign(formData[key][ck],data[key][ck])
}
} else {
formData[key] = data[key]
}
}
})
loading.value = false
})
}
}
init()
const brandList = ref([])
getPrinterBrand({}).then((res: any) => {
brandList.value = res.data;
})
const templateList:any = ref({}) //
getPrinterTemplateList({}).then((res:any)=> {
if (res.data) {
let data = res.data;
for (let i = 0; i < data.length; i++) {
let item = data[i];
if (templateList.value[item.template_type] == undefined) {
templateList.value[item.template_type] = []
}
templateList.value[item.template_type].push({
template_id: item.template_id,
template_name: item.template_name,
})
}
}
})
/**
* 确认
* @param formEl
*/
const confirm = async(formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
if (printerType.value.length == 0) {
ElMessage({
type: 'warning',
message: t('printTypeEmpty')
})
return;
}
let save = formData.printer_id ? editPrinter : addPrinter
await formEl.validate(async(valid) => {
if (valid) {
let validateFlag = false;
let validateMessage = '';
for (let i = 0; i < printerType.value.length; i++) {
let item: any = printerType.value[i];
for (let k = 0; k < Object.keys(item.trigger).length; k++) {
let triggerItem = Object.keys(item.trigger)[k];
if (formData.value[item.key]['trigger_' + triggerItem].status == 0) {
continue;
}
if (!formData.value[item.key]['trigger_' + triggerItem].template_id) {
validateFlag = true;
validateMessage = `请设置${ item.title }[${ item.trigger[triggerItem] }]的小票打印模板`
break;
}
let isFail = false;
for (let ck = 0; ck < item.condition.length; ck++) {
let condition = item.condition[ck];
if (condition.type == 'checkbox') {
if (formData.value[item.key]['trigger_' + triggerItem][condition.key].length == 0) {
validateFlag = true;
validateMessage = `请设置${ item.title }[${ item.trigger[triggerItem] }]的${ condition.title }`
isFail = true;
break;
}
}
}
//
if (isFail) {
break;
}
}
//
if (validateFlag) {
break;
}
}
if (validateFlag) {
ElMessage({
type: 'warning',
message: validateMessage
})
return;
}
formData.template_type = [];
formData.trigger = [];
for (let key in formData.value) {
for (let childKey in formData.value[key]) {
formData.trigger.push(key + '_' + childKey);
}
formData.template_type.push(key)
}
if (repeat.value) return
repeat.value = true
let data = formData
save(data).then(res => {
repeat.value = false
if (!formData.printer_id) {
router.push('/printer/list')
}
}).catch(err => {
repeat.value = false
})
}
})
}
const back = () => {
router.push('/printer/list')
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,227 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center mb-[5px]">
<span class="text-lg">{{pageName}}</span>
<el-button type="primary" @click="addEvent">
{{ t('addPrinter') }}
</el-button>
</div>
<el-tabs class="demo-tabs" model-value="/printer/list" @tab-change="handleClick">
<el-tab-pane :label="t('tabPrinterManager')" name="/printer/list" />
<el-tab-pane :label="t('tabPrinterTemplate')" name="/printer/template/list" />
</el-tabs>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="printerTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('printerName')" prop="printer_name">
<el-input v-model.trim="printerTable.searchParam.printer_name" :placeholder="t('printerNamePlaceholder')" maxlength="20" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadPrinterList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table :data="printerTable.data" size="large" v-loading="printerTable.loading">
<template #empty>
<span>{{ !printerTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="printer_name" :label="t('printerName')" min-width="220" :show-overflow-tooltip="true"/>
<el-table-column prop="brand_name" :label="t('brand')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="print_width" :label="t('printWidth')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="status" :label="t('status')" min-width="80" :show-overflow-tooltip="true" >
<template #default="{ row }">
<el-tag type="success" v-if="row.status == 1" @click="modifyPrinterStatusEvent(row.printer_id, 0)" class="cursor-pointer">{{ t('statusOn') }}</el-tag>
<el-tag type="info" v-else @click="modifyPrinterStatusEvent(row.printer_id, 1)" class="cursor-pointer">{{ t('statusOff') }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" link @click="testPrintEvent(row.printer_id)">{{ t('testPrint') }}</el-button>
<el-button type="primary" link @click="refreshTokenEvent(row.printer_id)">{{ t('refreshToken') }}</el-button>
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
<el-button type="primary" link @click="deleteEvent(row.printer_id)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="printerTable.page" v-model:page-size="printerTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="printerTable.total"
@size-change="loadPrinterList()" @current-change="loadPrinterList" />
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getPrinterPageList, modifyPrinterStatus, deletePrinter,refreshPrinterToken,testPrint } from '@/app/api/printer'
import { ElMessageBox,FormInstance } from 'element-plus'
import { useRoute,useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title;
const repeat = ref(false)
const handleClick = (path: string) => {
router.push({ path })
}
const printerTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam:{
printer_name:''
}
})
const searchFormRef = ref<FormInstance>()
/**
* 获取小票打印机列表
*/
const loadPrinterList = (page: number = 1) => {
printerTable.loading = true
printerTable.page = page
getPrinterPageList({
page: printerTable.page,
limit: printerTable.limit,
...printerTable.searchParam
}).then(res => {
printerTable.loading = false
printerTable.data = res.data.data
printerTable.total = res.data.total
}).catch(() => {
printerTable.loading = false
})
}
loadPrinterList()
const isRepeat = ref(false)
//
const modifyPrinterStatusEvent = (printer_id: any, status: any) => {
if (isRepeat.value) return
isRepeat.value = true
modifyPrinterStatus({
printer_id,
status
}).then((res) => {
loadPrinterList()
isRepeat.value = false
})
}
/**
* 添加小票打印机
*/
const addEvent = () => {
router.push('/printer/add')
}
/**
* 编辑小票打印机
* @param data
*/
const editEvent = (data: any) => {
router.push('/printer/edit?printer_id=' + data.printer_id)
}
/**
* 删除小票打印机
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('printerDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
if (repeat.value) return
repeat.value = true
deletePrinter(id).then(() => {
loadPrinterList()
repeat.value = false
}).catch(() => {
repeat.value = false
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadPrinterList()
}
/**
* 测试打印
* @param printer_id
*/
const testPrintEvent = (printer_id: any) => {
ElMessageBox.confirm(t('testPrintTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
if (repeat.value) return
repeat.value = true
testPrint(printer_id).then((res: any) => {
repeat.value = false
}).catch(() => {
repeat.value = false
})
})
}
/**
* 授权重新获取token
* @param printer_id
*/
const refreshTokenEvent = (printer_id: any) => {
ElMessageBox.confirm(t('refreshTokenTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
if (repeat.value) return
repeat.value = true
refreshPrinterToken(printer_id).then((res: any) => {
loadPrinterList()
repeat.value = false
}).catch(() => {
repeat.value = false
})
})
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,350 @@
<template>
<div class="main-container">
<el-card class="card !border-none mb-[15px]" shadow="never">
<el-page-header :content="pageName" :icon="ArrowLeft" @back="back" />
</el-card>
<el-form class="page-form" :model="formData" :rules="formRules" label-width="150px" ref="formRef" v-loading="loading">
<div class="flex">
<div class="flex-1 mr-[20px] bg-[#fff]">
<el-card class="box-card !border-none" shadow="never">
<h3 class="panel-title !text-sm">{{ t('templateInfoLabel') }}</h3>
<el-form-item :label="t('templateName')" prop="template_name">
<el-input v-model.trim="formData.template_name" clearable :placeholder="t('templateNamePlaceholder')" class="input-width" maxlength="20" />
</el-form-item>
<el-form-item :label="t('templateType')" prop="template_type" v-if="printerType.length">
<el-radio-group v-model="formData.template_type">
<el-radio v-for="item in printerType" :key="item.key" :label="item.key" @change="handlePrintType">{{ item.title }}</el-radio>
</el-radio-group>
</el-form-item>
</el-card>
<el-card class="box-card !border-none" shadow="never" v-if="printerType.length">
<h3 class="panel-title !text-sm">{{ t('templateEditLabel') }}</h3>
<div v-for="item in template" :key="item.key" class="bg-[#f8f8f9] mb-[20px] py-[20px] px-[40px] text-[14px]">
<h4 class="panel-title !text-sm">{{ item.title }}</h4>
<div v-for="(childItem,index) in item.list" :key="childItem.key" class="ml-[30px]" :style="{ 'margin-bottom' : item.list.length == (index + 1) ? '0' : '20px' }">
<div class="flex">
<el-checkbox v-model="formData.value[item.key][childItem.key].status" v-if="childItem.label" :label="childItem.label" :value="childItem.status" :true-value="1" :false-value="0" class="w-[180px] mr-[10px]" :disabled="childItem.disabled" />
<template v-if="childItem.type == 'input'">
<el-input v-model.trim="formData.value[item.key][childItem.key].value" clearable :placeholder="'请输入' + (childItem.placeholder ? childItem.placeholder : childItem.label)" class="input-width mr-[30px]" maxlength="32" />
</template>
<template v-if="childItem.type == 'checkbox'">
<el-checkbox-group v-model="formData.value[item.key][childItem.key].value" class="mr-[30px]">
<el-checkbox v-for="(checkboxItem, key) in childItem.list" :label="key" :key="key" :disabled="childItem.disabled">{{ checkboxItem }}</el-checkbox>
</el-checkbox-group>
</template>
<template v-if="childItem.type == 'select'">
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">{{ childItem.text }}</div>
<el-select v-model="formData.value[item.key][childItem.key].value" class="!w-[130px] mr-[30px]">
<el-option v-for="(item,key) in childItem.list" :key="key" :label="item" :value="key" />
</el-select>
</template>
<template v-if="childItem.fontSize">
<div class="flex mr-[30px]">
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">字号</div>
<el-select v-model="formData.value[item.key][childItem.key].fontSize" class="!w-[130px]">
<el-option label="小" value="normal" />
<!-- <el-option label="小" value="small" />-->
<el-option label="大" value="big" />
</el-select>
</div>
</template>
<template v-if="childItem.fontWeight">
<div class="flex mr-[30px]">
<div class="leading-[30px] w-[50px] text-center text-[#707070] bg-[#d7d7d7] border-1 border-solid border-[#ededed]">粗细</div>
<el-select v-model="formData.value[item.key][childItem.key].fontWeight" class="!w-[130px]">
<el-option label="正常" value="normal" />
<el-option label="加粗" value="bold" />
</el-select>
</div>
</template>
</div>
<div v-if="childItem.remark" class="text-[12px] text-[#b2b2b2] mt-[10px]">{{ childItem.remark }}</div>
</div>
</div>
</el-card>
</div>
<el-card class="box-card !border-none w-[450px]" shadow="never">
<h3 class="panel-title !text-sm">{{ t('preview') }}</h3>
<!-- 动态加载组件 -->
<component :is="modules[previewPath]" :value="formData.value"/>
</el-card>
</div>
</el-form>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" :loading="repeat" @click="confirm(formRef)">{{ t('save') }}</el-button>
<el-button @click="back()">{{ t('cancel') }}</el-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import { FormInstance, ElMessage } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import { getPrinterType, addPrinterTemplate, editPrinterTemplate, getPrinterTemplateInfo } from '@/app/api/printer'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const repeat = ref(false)
const loading = ref(true)
/**
* 表单数据
*/
const initialFormData:any = {
template_id: route.query.template_id || 0,
template_type: '',
template_name: '',
value: {},
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
template_name: [
{ required: true, message: t('templateNamePlaceholder'), trigger: 'blur' },
],
template_type: [
{ required: true, message: t('templateTypePlaceholder'), trigger: 'blur' },
]
}
})
//
const modulesFiles = import.meta.glob('./components/*.vue', { eager: true })
const addonModulesFiles = import.meta.glob('@/addon/**/views/printer/components/*.vue', { eager: true })
addonModulesFiles && Object.assign(modulesFiles, addonModulesFiles)
const modules:any = {}
for (const [key, value] of Object.entries(modulesFiles)) {
const moduleName:any = key.split('/').pop()
const name = moduleName.split('.')[0]
modules[name] = value.default
}
const previewPath = ref('')
const printerType:any = ref([])
const template:any = ref([])
const init = async ()=> {
await getPrinterType({}).then((res: any) => {
if (res.data && res.data.length) {
printerType.value = res.data;
handlePrintType(printerType.value[0].key, Boolean(parseInt(formData.template_id)));
}
if (!formData.template_id) {
loading.value = false
}
})
if(formData.template_id) {
getPrinterTemplateInfo(formData.template_id).then((res:any)=>{
let data = res.data;
if (data && Object.keys(data).length) {
Object.keys(formData).forEach((key: string) => {
if (key == 'value') {
for (let ck in formData[key]){
Object.assign(formData[key][ck],data[key][ck])
}
} else {
formData[key] = data[key]
}
})
loading.value = false
}else {
ElMessage({
type: 'warning',
duration: 1500,
message: t('printTemplateEmpty')
})
setTimeout(()=>{
back();
loading.value = false
}, 2000);
}
})
}
};
init();
//
const handlePrintType = (value: any, load: boolean = false) => {
for (let i = 0; i < printerType.value.length; i++) {
if (printerType.value[i].key == value) {
formData.template_type = printerType.value[i].key;
previewPath.value = printerType.value[i].path;
template.value = printerType.value[i].template;
break;
}
}
//
for (let key in formData.value) {
delete formData.value[key];
}
refreshTemplateData();
}
//
const refreshTemplateData = ()=> {
for (let i = 0; i < template.value.length; i++) {
let item: any = template.value[i];
formData.value[item.key] = {};
for (let k = 0; k < item.list.length; k++) {
let childItem = item.list[k];
formData.value[item.key][childItem.key] = {
type: childItem.type,
value: childItem.value,
status: childItem.status,
fontSize: childItem.fontSize,
fontWeight: childItem.fontWeight,
};
}
}
}
/**
* 确认
* @param formEl
*/
const confirm = async(formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
if (printerType.value.length == 0) {
ElMessage({
type: 'warning',
message: t('printTypeEmpty')
})
return;
}
let save = formData.template_id ? editPrinterTemplate : addPrinterTemplate
await formEl.validate(async(valid) => {
if (valid) {
let validateFlag = false;
let validateMessage = '';
for (let i = 0; i < template.value.length; i++) {
let item: any = template.value[i];
let isFail = false;
for (let k = 0; k < item.list.length; k++) {
let childItem = item.list[k];
if (formData.value[item.key][childItem.key].status == 0) {
continue;
}
if (childItem.type == 'input') {
if (formData.value[item.key][childItem.key].value == '') {
validateFlag = true;
validateMessage = `请输入${ childItem.label }`;
isFail = true;
break;
}
} else if (childItem.type == 'select') {
if (formData.value[item.key][childItem.key].value == '') {
validateFlag = true;
validateMessage = `${ childItem.label }未设置[${ childItem.text }]`;
isFail = true;
break;
}
}
}
//
if (isFail) {
break;
}
}
if (validateFlag) {
ElMessage({
type: 'warning',
message: validateMessage
})
return;
}
for (let i = 0; i < template.value.length; i++) {
let item: any = template.value[i];
for (let k = 0; k < item.list.length; k++) {
let childItem = item.list[k];
if (childItem.type == 'checkbox') {
if (formData.value[item.key][childItem.key].value.length) {
formData.value[item.key][childItem.key].status = 1;
} else {
formData.value[item.key][childItem.key].status = 0;
}
}
}
}
if (repeat.value) return
repeat.value = true
let data = formData
save(data).then(res => {
repeat.value = false
if (!formData.template_id) {
back()
}
}).catch(err => {
repeat.value = false
})
}
})
}
const back = () => {
router.push('/printer/template/list')
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,162 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center mb-[5px]">
<span class="text-lg">{{pageName}}</span>
<el-button type="primary" @click="addEvent">
{{ t('addPrinterTemplate') }}
</el-button>
</div>
<el-tabs class="demo-tabs" model-value="/printer/template/list" @tab-change="handleClick">
<el-tab-pane :label="t('tabPrinterManager')" name="/printer/list" />
<el-tab-pane :label="t('tabPrinterTemplate')" name="/printer/template/list" />
</el-tabs>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="printerTemplateTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('templateName')" prop="template_name">
<el-input v-model="printerTemplateTable.searchParam.template_name" :placeholder="t('templateNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('templateType')" prop="template_type">
<el-select v-model="printerTemplateTable.searchParam.template_type" :placeholder="t('templateTypePlaceholder')" clearable>
<el-option v-for="(item,key) in printerType" :key="itemkey" :label="item.title" :value="item.key" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadPrinterTemplateList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table :data="printerTemplateTable.data" size="large" v-loading="printerTemplateTable.loading">
<template #empty>
<span>{{ !printerTemplateTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="template_name" :label="t('templateName')" min-width="220" :show-overflow-tooltip="true"/>
<el-table-column prop="template_type_name" :label="t('templateType')" min-width="180" :show-overflow-tooltip="true"/>
<el-table-column prop="create_time" :label="t('createTime')" min-width="120" />
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
<el-button type="primary" link @click="deleteEvent(row.template_id)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="printerTemplateTable.page" v-model:page-size="printerTemplateTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="printerTemplateTable.total"
@size-change="loadPrinterTemplateList()" @current-change="loadPrinterTemplateList" />
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getPrinterTemplatePageList, deletePrinterTemplate,getPrinterType } from '@/app/api/printer'
import { ElMessageBox,FormInstance } from 'element-plus'
import { useRoute,useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title;
const handleClick = (path: string) => {
router.push({ path })
}
const printerTemplateTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
template_name: '',
template_type: '',
}
})
const searchFormRef = ref<FormInstance>()
const printerType = ref([])
getPrinterType({}).then((res: any) => {
if (res.data) {
printerType.value = res.data;
}
})
/**
* 获取小票打印模板列表
*/
const loadPrinterTemplateList = (page: number = 1) => {
printerTemplateTable.loading = true
printerTemplateTable.page = page
getPrinterTemplatePageList({
page: printerTemplateTable.page,
limit: printerTemplateTable.limit,
...printerTemplateTable.searchParam
}).then(res => {
printerTemplateTable.loading = false
printerTemplateTable.data = res.data.data
printerTemplateTable.total = res.data.total
}).catch(() => {
printerTemplateTable.loading = false
})
}
loadPrinterTemplateList()
/**
* 添加小票打印模板
*/
const addEvent = () => {
router.push('/printer/template/add')
}
/**
* 编辑小票打印模板
* @param data
*/
const editEvent = (data: any) => {
router.push('/printer/template/edit?template_id=' + data.template_id)
}
/**
* 删除小票打印模板
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('printerTemplateDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deletePrinterTemplate(id).then(() => {
loadPrinterTemplateList()
})
})
}
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadPrinterTemplateList()
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -91,8 +91,6 @@ const formRules = computed(() => {
}
})
// const emit = defineEmits(['complete'])
const setFormData = async (row: any = null) => {
loading.value = true
Object.assign(formData, initialFormData)

View File

@ -40,7 +40,6 @@
import { ref, reactive, computed } from 'vue'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
// import { editNoticeStatus } from '@/app/api/notice'
const showDialog = ref(false)
const loading = ref(true)

View File

@ -13,7 +13,7 @@
</el-form-item>
<el-form-item :label="t('weappTempKey')">
<div class="input-width"> {{ formData.temp_key }} </div>
<div class="input-width"> {{ formData.tid }} </div>
</el-form-item>
<el-form-item :label="t('content')">
@ -54,7 +54,7 @@ const initialFormData = {
content: [],
first: '',
remark: '',
temp_key: ''
tid: ''
}
const formData: Record<string, any> = reactive({ ...initialFormData })

View File

@ -9,15 +9,15 @@
</el-form-item>
<el-form-item :label="t('aliSign')" prop="sign">
<el-input v-model="formData.sign" :placeholder="t('aliSignPlaceholder')" class="input-width" show-word-limit clearable />
<el-input v-model.trim="formData.sign" :placeholder="t('aliSignPlaceholder')" class="input-width" show-word-limit clearable />
</el-form-item>
<el-form-item :label="t('aliAppKey')" prop="app_key">
<el-input v-model="formData.app_key" :placeholder="t('aliAppKeyPlaceholder')" class="input-width" clearable />
<el-input v-model.trim="formData.app_key" :placeholder="t('aliAppKeyPlaceholder')" class="input-width" clearable />
</el-form-item>
<el-form-item :label="t('aliSecretKey')" prop="secret_key">
<el-input v-model="formData.secret_key" :placeholder="t('aliSecretKeyPlaceholder')" class="input-width" clearable />
<el-input v-model.trim="formData.secret_key" :placeholder="t('aliSecretKeyPlaceholder')" class="input-width" clearable />
</el-form-item>
</el-form>

View File

@ -9,19 +9,19 @@
</el-form-item>
<el-form-item :label="t('tencentSign')" prop="sign">
<el-input v-model="formData.sign" :placeholder="t('tencentSignPlaceholder')" class="input-width" show-word-limit clearable />
<el-input v-model.trim="formData.sign" :placeholder="t('tencentSignPlaceholder')" class="input-width" show-word-limit clearable />
</el-form-item>
<el-form-item :label="t('tencentAppId')" prop="app_id">
<el-input v-model="formData.app_id" :placeholder="t('tencentAppIdPlaceholder')" class="input-width" show-word-limit clearable />
<el-input v-model.trim="formData.app_id" :placeholder="t('tencentAppIdPlaceholder')" class="input-width" show-word-limit clearable />
</el-form-item>
<el-form-item :label="t('tencentSecretId')" prop="secret_id">
<el-input v-model="formData.secret_id" :placeholder="t('tencentSecretIdPlaceholder')" class="input-width" clearable />
<el-input v-model.trim="formData.secret_id" :placeholder="t('tencentSecretIdPlaceholder')" class="input-width" clearable />
</el-form-item>
<el-form-item :label="t('tencentSecretKey')" prop="secret_key">
<el-input v-model="formData.secret_key" :placeholder="t('tencentSecretKeyPlaceholder')" class="input-width" clearable />
<el-input v-model.trim="formData.secret_key" :placeholder="t('tencentSecretKeyPlaceholder')" class="input-width" clearable />
</el-form-item>
</el-form>

View File

@ -63,19 +63,19 @@ const formData = reactive<Record<string, number | boolean>>({
const formRules = computed(() => {
return {
type: [
{
required: true,
trigger: 'change',
validator: (rule: any, value: any, callback: any) => {
if (!formData.is_mobile && !formData.is_username) {
callback(new Error(t('mobileOrUsernameNoEmpty')))
} else {
callback()
}
}
}
]
// type: [
// {
// required: true,
// trigger: 'change',
// validator: (rule: any, value: any, callback: any) => {
// if (!formData.is_mobile && !formData.is_username) {
// callback(new Error(t('mobileOrUsernameNoEmpty')))
// } else {
// callback()
// }
// }
// }
// ]
}
})

View File

@ -14,7 +14,7 @@
</el-form-item>
<el-form-item :label="t('noticeKey')" prop="key">
<el-select v-model="recordsTableData.searchParam.key" clearable :placeholder="t('groupIdPlaceholder')" class="input-width">
<el-select v-model="recordsTableData.searchParam.key" clearable :placeholder="t('noticeKeyPlaceholder')" class="input-width" popper-class="notice">
<el-option :label="t('selectPlaceholder')" value="" />
<el-option-group v-for="(group, gindex) in templateList" :key="gindex" :label="group.label">
<el-option :label="item.name" :value="item.value" :disabled="item.disabled ?? false" v-for="(item, index) in group.list" :key="index" />
@ -172,4 +172,9 @@ const infoEvent = (data: any) => {
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.notice .el-select-group__title{
font-size: 14px;;
}
</style>

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