update admin

This commit is contained in:
全栈小学生 2024-08-06 17:45:16 +08:00
parent cccb572788
commit 62fd03ae55
143 changed files with 3756 additions and 2698 deletions

View File

@ -1,13 +0,0 @@
import request from '@/utils/request'
/**
*
* @returns
*/
export function getApply(params: Record<string, any>) {
return request.get(`auth/authaddon`, {params})
}
export function getAppManage(params: Record<string, any>) {
return request.get(`auth/app_manage`, {params})
}

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

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

View File

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

View File

@ -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,17 +0,0 @@
import request from '@/utils/request'
/***************************************************** 统计信息 **************************************************/
/**
*
*/
export function getStatInfo() {
return request.get(`stat/index`)
}
/**
*
*/
export function getSiteStatInfo() {
return request.get(`stat/siteindex`)
}

View File

@ -33,7 +33,7 @@ export function getRoleList(params: Record<string, any>) {
* @param roleId
*/
export function getRoleInfo(roleId: number) {
return request.get(`sys/role/${roleId}`)
return request.get(`sys/role/${ roleId }`)
}
/**
@ -50,7 +50,7 @@ export function addRole(params: Record<string, any>) {
* @param params
*/
export function editRole(params: Record<string, any>) {
return request.put(`sys/role/${params.role_id}`, params, { showSuccessMessage: true })
return request.put(`sys/role/${ params.role_id }`, params, { showSuccessMessage: true })
}
/**
@ -58,15 +58,7 @@ export function editRole(params: Record<string, any>) {
* @param roleId
*/
export function deleteRole(roleId: number) {
return request.delete(`sys/role/${roleId}`, { showSuccessMessage: true })
}
/**
*
* @param params
*/
export function setRoleStatus(params: Record<string, any>) {
return request.put(`sys/role/status/${params.role_id}`, params, { showSuccessMessage: true })
return request.delete(`sys/role/${ roleId }`, { showSuccessMessage: true })
}
/**
@ -92,7 +84,7 @@ export function getMenus() {
* @param menu_key
*/
export function getMenuInfo(menu_key: string) {
return request.get(`sys/menu/info/${menu_key}`);
return request.get(`sys/menu/info/${ menu_key }`);
}
/**
@ -109,7 +101,7 @@ export function addMenu(params: Record<string, any>) {
* @param params
*/
export function editMenu(params: Record<string, any>) {
return request.put(`sys/menu/${params.menu_key}`, params, { showSuccessMessage: true })
return request.put(`sys/menu/${ params.menu_key }`, params, { showSuccessMessage: true })
}
/**
@ -117,7 +109,7 @@ export function editMenu(params: Record<string, any>) {
* @param menu_key
*/
export function deleteMenu(menu_key: string) {
return request.delete(`sys/menu/${menu_key}`, { showSuccessMessage: true })
return request.delete(`sys/menu/${ menu_key }`, { showSuccessMessage: true })
}
/**
@ -128,20 +120,12 @@ export function getSystemMenu(params: Record<string, any> = {}) {
return request.get(`sys/menu/system_menu`, { params })
}
/**
*
*
*/
export function getAllAddonMenu() {
return request.get(`sys/menu/addon_menu/all`)
}
/**
*
*
*/
export function getAddonMenu(key: any) {
return request.get(`sys/menu/addon_menu/${key}`)
return request.get(`sys/menu/addon_menu/${ key }`)
}
/**
@ -149,7 +133,7 @@ export function getAddonMenu(key: any) {
* @param key
*/
export function getMenuByTypeDir(key: any = 'system') {
return request.get(`sys/menu/dir/${key}`)
return request.get(`sys/menu/dir/${ key }`)
}
/***************************************************** 设置 ****************************************************/
@ -235,7 +219,7 @@ export function addAttachmentCategory(params: Record<string, any>) {
* @returns
*/
export function editAttachmentCategory(params: Record<string, any>) {
return request.put(`sys/attachment/category/${params.id}`, params, { showSuccessMessage: true })
return request.put(`sys/attachment/category/${ params.id }`, params, { showSuccessMessage: true })
}
/**
@ -244,7 +228,7 @@ export function editAttachmentCategory(params: Record<string, any>) {
* @returns
*/
export function deleteAttachmentCategory(id: number) {
return request.delete(`sys/attachment/category/${id}`, { showSuccessMessage: true })
return request.delete(`sys/attachment/category/${ id }`, { showSuccessMessage: true })
}
/**
@ -299,6 +283,7 @@ export function getIconList(params: Record<string, any>) {
export function getEnv() {
return request.get(`sys/env`)
}
/***************************************************** 地址管理 ****************************************************/
/**
@ -306,7 +291,7 @@ export function getEnv() {
* @param pid
*/
export function getAreaListByPid(pid: number = 0) {
return request.get(`sys/area/list_by_pid/${pid}`)
return request.get(`sys/area/list_by_pid/${ pid }`)
}
/**
@ -314,10 +299,9 @@ export function getAreaListByPid(pid: number = 0) {
* @param level
*/
export function getAreatree(level: number = 1) {
return request.get(`sys/area/tree/${level}`)
return request.get(`sys/area/tree/${ level }`)
}
/**
*
*/
@ -337,8 +321,9 @@ export function getContraryAddress(params: any) {
* @param code
*/
export function getAreaByCode(code: number | string) {
return request.get(`sys/area/code/${code}`)
return request.get(`sys/area/code/${ code }`)
}
/***************************************************** 存储设置 ****************************************************/
/**
@ -353,7 +338,7 @@ export function getStorageList() {
* @param type
*/
export function getStorageInfo(type: string) {
return request.get(`sys/storage/${type}`)
return request.get(`sys/storage/${ type }`)
}
/**
@ -362,7 +347,7 @@ export function getStorageInfo(type: string) {
* @returns
*/
export function editStorage(params: Record<string, any>) {
return request.put(`sys/storage/${params.storage_type}`, params, { showSuccessMessage: true })
return request.put(`sys/storage/${ params.storage_type }`, params, { showSuccessMessage: true })
}
/***************************************************** 支付设置 ****************************************************/
@ -372,7 +357,7 @@ export function editStorage(params: Record<string, any>) {
* @returns
*/
export function getPayConfig(type: string) {
return request.get(`pay/config/${type}`)
return request.get(`pay/config/${ type }`)
}
/**
@ -380,7 +365,7 @@ export function getPayConfig(type: string) {
* @returns
*/
export function setPayConfig(params: Record<string, any>) {
return request.put(`pay/config/${params.type}`, params, { showSuccessMessage: true });
return request.put(`pay/config/${ params.type }`, params, { showSuccessMessage: true });
}
/**
@ -397,7 +382,7 @@ export function getPayList() {
* @param channel
*/
export function getTransferInfo(channel: string) {
return request.get(`pay/channel/lists/${channel}`)
return request.get(`pay/channel/lists/${ channel }`)
}
/**
@ -424,7 +409,7 @@ export function getCronList(params: any) {
* @returns
*/
export function getCronInfo(id: string) {
return request.get(`sys/cron/${id}`);
return request.get(`sys/cron/${ id }`);
}
/**
@ -464,7 +449,7 @@ export function addCron(params: Record<string, any>) {
* @returns
*/
export function editCron(params: Record<string, any>) {
return request.put(`sys/schedule/${params.id}`, params, { showSuccessMessage: true })
return request.put(`sys/schedule/${ params.id }`, params, { showSuccessMessage: true })
}
/**
@ -472,7 +457,7 @@ export function editCron(params: Record<string, any>) {
* @returns
*/
export function deleteCron(id: string) {
return request.delete(`sys/schedule/${id}`, { showSuccessMessage: true })
return request.delete(`sys/schedule/${ id }`, { showSuccessMessage: true })
}
/***************************************************** 协议管理 ****************************************************/
@ -490,7 +475,7 @@ export function getAgreementList() {
* @returns
*/
export function getAgreementInfo(key: string) {
return request.get(`sys/agreement/${key}`);
return request.get(`sys/agreement/${ key }`);
}
/**
@ -498,7 +483,7 @@ export function getAgreementInfo(key: string) {
* @returns
*/
export function editAgreement(params: Record<string, any>) {
return request.put(`sys/agreement/${params.key}`, params, { showSuccessMessage: true })
return request.put(`sys/agreement/${ params.key }`, params, { showSuccessMessage: true })
}
/**
@ -509,7 +494,6 @@ export function getChannelType() {
return request.get(`sys/channel`);
}
/**
*
* @returns
@ -556,7 +540,7 @@ export function setPatConfig(params: Record<string, any>) {
*
*/
export function menuRefresh(params: Record<string, any>) {
return request.post(`sys/menu/refresh`, {}, { showSuccessMessage: true })
return request.post(`sys/menu/refresh`, {})
}
/**
@ -566,7 +550,6 @@ export function clearSchemaCache(params: Record<string, any>) {
return request.post(`sys/schema/clear`, {}, { showSuccessMessage: true })
}
/***************************************************** 获取应用 ****************************************************/
/**
*
@ -592,19 +575,6 @@ export function getMap() {
}
/***************************************************** 首页 ****************************************************/
/**
*
*/
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 })
}
/**
*
@ -618,7 +588,7 @@ export function getPayAuditList(params: Record<string, any>) {
* @returns
*/
export function payAuditPass(outTradeNo: string) {
return request.put(`pay/pass/${outTradeNo}`, {}, { showSuccessMessage: true })
return request.put(`pay/pass/${ outTradeNo }`, {}, { showSuccessMessage: true })
}
/**
@ -626,14 +596,14 @@ export function payAuditPass(outTradeNo: string) {
* @returns
*/
export function payAuditRefuse(params: Record<string, any>) {
return request.put(`pay/refuse/${params.out_trade_no}`, params, { showSuccessMessage: true })
return request.put(`pay/refuse/${ params.out_trade_no }`, params, { showSuccessMessage: true })
}
/**
*
*/
export function getPayDetail(id: number) {
return request.get(`pay/detail/${id}`)
return request.get(`pay/detail/${ id }`)
}
/**
@ -643,13 +613,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
@ -667,7 +630,6 @@ export function setDeveloperToken(params: Record<string, any>) {
return request.put(`sys/config/developer_token`, params, { showSuccessMessage: true })
}
/**
*
* @returns
@ -707,7 +669,7 @@ export function getExportKeyList() {
* @returns
*/
export function exportData(type: string, params: Record<string, any>) {
return request.get(`sys/export/${type}`, { params })
return request.get(`sys/export/${ type }`, { params })
}
/**
@ -715,7 +677,7 @@ export function exportData(type: string, params: Record<string, any>) {
* @returns
*/
export function exportDataCheck(type: string, params: Record<string, any>) {
return request.get(`sys/export/check/${type}`, { params })
return request.get(`sys/export/check/${ type }`, { params })
}
/**
@ -723,7 +685,7 @@ export function exportDataCheck(type: string, params: Record<string, any>) {
* @param id
*/
export function deleteExport(id: number) {
return request.delete(`sys/export/${id}`, { showSuccessMessage: true })
return request.delete(`sys/export/${ id }`, { showSuccessMessage: true })
}
/**

View File

@ -19,7 +19,7 @@ export function getUserList(params: Record<string, any>) {
* @returns
*/
export function getUserInfo(uid: number) {
return request.get(`user/${uid}`);
return request.get(`user/${ uid }`);
}
/**
@ -31,26 +31,35 @@ export function addUser(params: Record<string, any>) {
return request.post('user', params, { showSuccessMessage: true })
}
/**
*
* @param params
* @returns
*/
export function getAllUserList(params: Record<string, any>) {
return request.get(`user/user_all`, { params })
}
/**
*
* @param params
*/
export function editUser(params: Record<string, any>) {
return request.put(`user/${params.uid}`, params, { showSuccessMessage: true })
return request.put(`user/${ params.uid }`, params, { showSuccessMessage: true })
}
/**
*
*/
export function lockUser(uid: number) {
return request.put(`user/lock/${uid}`, {}, { showSuccessMessage: true })
return request.put(`user/lock/${ uid }`, {}, { showSuccessMessage: true })
}
/**
*
*/
export function unlockUser(uid: number) {
return request.put(`user/unlock/${uid}`, {}, { showSuccessMessage: true })
return request.put(`user/unlock/${ uid }`, {}, { showSuccessMessage: true })
}
/***************************************************** 操作日志 **************************************************/
@ -69,5 +78,5 @@ export function getLogList(params: Record<string, any>) {
* @param id
*/
export function getLogInfo(id: number) {
return request.get(`user/userlog/${id}`)
return request.get(`user/userlog/${ id }`)
}

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: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 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

@ -30,4 +30,4 @@
"addon":"选择应用",
"system":"系统菜单",
"application":"应用菜单"
}
}

View File

@ -1,13 +0,0 @@
{
"addRole": "新增角色",
"updateRole": "编辑角色",
"roleName": "角色名称",
"roleDeleteTips": "确定要删除该角色吗?",
"roleNamePlaceholder": "请输入角色名称",
"rulesPlaceholder": "请选择权限",
"checkStrictly": "父子级不关联",
"permission": "权限",
"foldText":"展开/折叠",
"system": "系统菜单",
"application": "应用菜单"
}

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

@ -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

@ -109,10 +109,11 @@ import { reactive, ref, computed } from 'vue'
import { t } from '@/lang'
import { getVersions } from '@/app/api/auth'
import { getInstallConfig } from "@/app/api/sys"
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'
import { cloneDeep } from 'lodash-es'
const upgradeRef = ref<any>(null)
const cloudBuildRef = ref<any>(null)
@ -128,9 +129,20 @@ getInstallConfig().then(({ data }) => {
installPhpConfig.value = data
}).catch()
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()
@ -140,7 +152,7 @@ const newVersion:any = computed(() => {
})
const hideAuthCode = (res:any) => {
const authCode = JSON.parse(JSON.stringify(res))
const authCode = cloneDeep(res)
const data = authCode.slice(0, authCode.length / 2) + authCode.slice(authCode.length / 2, authCode.length - 1).replace(/./g, '*')
return data
}
@ -163,7 +175,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
@ -200,7 +212,7 @@ const save = async (formEl: FormInstance | undefined) => {
if (valid) {
saveLoading.value = true
setAuthinfo(formData).then(() => {
setAuthInfo(formData).then(() => {
saveLoading.value = false
checkAppMange()
}).catch(() => {
@ -227,7 +239,7 @@ getVersionsInfo()
* 升级
*/
const handleUpgrade = () => {
if (!authinfo.value) {
if (!authinfo.value.auth_code) {
authCodeApproveFn()
return
}
@ -235,7 +247,7 @@ const handleUpgrade = () => {
}
const handleCloudBuild = () => {
if (!authinfo.value) {
if (!authinfo.value.auth_code) {
authCodeApproveFn()
return
}

View File

@ -1,57 +0,0 @@
<template>
<el-tree :data="data" :props="{ label: 'menu_name' }" show-checkbox :expand-on-click-node="false"
@check-change="handleCheckChange" node-key="menu_key" ref="treeRef" />
</template>
<script lang="ts" setup>
import { debounce } from '@/utils/common'
import { ref, computed, onMounted, nextTick } from 'vue'
const prop = defineProps({
data: {
type: Object,
default: () => { }
},
modelValue: {
type: Array,
default: () => []
}
})
const data = ref([])
data.value.push(prop.data)
const emit = defineEmits(['update:modelValue', 'change'])
const value = computed({
get() {
return prop.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
const treeRef = ref(null)
//
onMounted(() => {
nextTick(() => {
const newArr: any = []
prop.modelValue.forEach(el => checked(el, data.value, newArr))
treeRef.value.setCheckedKeys(newArr)
})
})
const checked = (key: string, data: any, newArr: any) => {
data.forEach((el: any) => {
if (key == el.menu_key) {
if (!el.children || el.children.length == 0) {
newArr.push(key)
}
} else {
if (el.children && el.children.length > 0) {
checked(key, el.children, newArr)
}
}
})
}
const handleCheckChange = debounce((e) => {
value.value = treeRef.value.getCheckedNodes(false, true).map(el => el.menu_key)
})
</script>

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">
<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>
@ -118,13 +118,12 @@ const initialFormData = {
status: 1,
is_show: 1,
menu_key: '',
app_type: '',
addon: '',
menu_short_name: ''
}
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 +166,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')">

View File

@ -55,7 +55,6 @@ import { allRole } from '@/app/api/sys'
import { img, deepClone } from '@/utils/common'
import { AnyObject } from '@/types/global'
const userList = ref<AnyObject>([])
const uid = ref<number | string>('')
const real_name_input = ref(true)

View File

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

View File

@ -5,7 +5,6 @@
<div class="flex justify-between items-center">
<span class="text-page-title">{{ pageName }}</span>
<div class="flex items-center">
<el-button type="primary" class="w-[100px]" @click="addEvent">
{{ t('addMenu') }}

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

@ -74,7 +74,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>
@ -96,7 +96,7 @@ import { getInstallConfig } from '@/app/api/sys'
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'
@ -134,7 +134,7 @@ getInstallConfig().then(({ data }) => {
installPhpConfig.value = data
}).catch()
getAuthinfo().then(res => {
getAuthInfo().then(res => {
if (res.data.data && res.data.data.auth_code) {
authCode.value = res.data.data.auth_code
getWeappPreviewImage()

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 !text-[20px]', 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,6 +109,48 @@ 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: '左上',
@ -105,7 +174,7 @@ const templateList = ref([
}
])
let selectTemplate = ref({})
const selectTemplate = ref({})
templateList.value.forEach((item) => {
if (item.className == diyStore.editComponent.bottomPosition) {
selectTemplate.value = item

View File

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

View File

@ -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>
@ -167,6 +172,7 @@ const inputBoth = (value:any)=>{
})
}
watch(
() => diyStore.global,
(newValue, oldValue) => {
@ -176,14 +182,11 @@ watch(
const showDialog = ref(false)
const showStyle = () => {
selectStyle.value = diyStore.global.topStatusBar.style
showDialog.value = true
}
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

@ -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

@ -89,7 +89,7 @@ import { t } from '@/lang'
import { img } from '@/utils/common'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { getDecoratePage, changeTemplate, getDiyTemplate } from '@/app/api/diy'
import { getDecoratePage, changeTemplate,getDiyTemplate } from '@/app/api/diy'
import storage from '@/utils/storage'
import QRCode from 'qrcode'
import { useClipboard } from '@vueuse/core'
@ -100,7 +100,7 @@ const siteApps = computed(() => {
return systemStore?.apps
})
const type: any = ref('DIY_MEMBER_INDEX')
const type: any = ref('DIY_MEMBER_INDEX');
const page: any = reactive({})
const router = useRouter()
const wapDomain = ref('')

View File

@ -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

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

View File

@ -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

@ -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>

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>
@ -377,7 +376,7 @@ 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 { getInstallConfig } from '@/app/api/sys'
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'
@ -438,7 +437,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
}
@ -837,7 +836,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) {
@ -877,7 +876,7 @@ const save = async (formEl: FormInstance | undefined) => {
if (valid) {
saveLoading.value = true
setAuthinfo(formData)
setAuthInfo(formData)
.then(() => {
saveLoading.value = false
setTimeout(() => {

View File

@ -33,8 +33,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>
@ -110,7 +109,7 @@ const form = reactive({
//
const loginConfig = ref({})
const getLoginConfigFn = async (id: number = 0) => {
const getLoginConfigFn = async () => {
imgLoading.value = true
const data = await (await getLoginConfig()).data
loginConfig.value = data

View File

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

View File

@ -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

@ -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>
@ -205,19 +205,6 @@ 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
}
/**
* 设置标签
*/

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

@ -1,111 +0,0 @@
<template>
<div class="main-container">
<el-form :model="formData" label-width="150px" ref="formRef" class="page-form" v-loading="loading">
<el-card class="box-card !border-none relative" shadow="never" v-if="formData">
<h3 class="panel-title">{{ t('orderInfo') }}</h3>
<el-form-item :label="t('orderNo')">
<div class="input-width">{{ formData.order_no }}</div>
</el-form-item>
<el-form-item :label="t('orderMoney')">
<div class="input-width">{{ formData.order_money }}</div>
</el-form-item>
<el-form-item :label="t('orderDiscountMoney')">
<div class="input-width">{{ formData.order_discount_money }}</div>
</el-form-item>
<el-form-item :label="t('member')">
<div class="input-width">
<div class="flex flex flex-col cursor-pointer" @click="toMember(formData.member_id)">
<span>{{ formData.member.nickname || '' }}</span>
<span>{{ formData.member.mobile || '' }}</span>
</div>
</div>
</el-form-item>
<el-form-item :label="t('ip')">
<div class="input-width">{{ formData.ip }}</div>
</el-form-item>
<el-form-item :label="t('orderFromName')">
<div class="input-width">{{ formData.order_from_name }}</div>
</el-form-item>
<el-form-item :label="t('orderStatus')">
<div class="input-width">{{ formData.order_status_info.name }}</div>
</el-form-item>
<el-form-item :label="t('payTypeName')">
<div class="input-width">{{ formData.pay_type_name }}</div>
</el-form-item>
<el-form-item :label="t('createTime')">
<div class="input-width">{{ formData.create_time || '' }}</div>
</el-form-item>
<el-form-item :label="t('payTime')">
<div class="input-width">{{ formData.pay_time || '' }}</div>
</el-form-item>
<el-form-item :label="t('remark')">
<div class="input-width">{{ formData.remark || '' }}</div>
</el-form-item>
<el-form-item :label="t('memberMessage')">
<div class="input-width">{{ formData.member_message || '' }}</div>
</el-form-item>
</el-card>
</el-form>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import { getRechargeOrderInfo } from '@/app/api/order'
import { useRoute, useRouter } from 'vue-router'
import useTabbarStore from '@/stores/modules/tabbar'
// import useAppStore from '@/stores/modules/app'
const tabbarStore = useTabbarStore()
const route = useRoute()
const router = useRouter()
const orderId: number = parseInt(route.query.order_id)
const loading = ref(true)
const formData: Record<string, any> | null = ref(null)
const setFormData = async (orderId: number = 0) => {
loading.value = true
formData.value = null
await getRechargeOrderInfo(orderId).then(({data}) => {
formData.value = data
}).catch(() => {
})
loading.value = false
}
if (orderId) setFormData(orderId)
else loading.value = false
const formRef = ref<FormInstance>()
const back = () => {
tabbarStore.removeTab(route.path)
router.push({ path: '/finance/recharge' })
}
/**
* 会员详情
*/
const toMember = (memberId: number) => {
router.push(`/member/detail?id=${memberId}`)
}
</script>
<style lang="scss" scoped></style>

View File

@ -1,290 +0,0 @@
<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-page-title">{{ pageName }}</span>
</div>
<el-card class="box-card !border-none table-search-wra base-bg !px-[35px]" shadow="never">
<el-row class="flex">
<el-col :span="12" class="min-w-[100px]">
<el-statistic
:value="rechargeStatistics.recharge_money ? Number.parseFloat(rechargeStatistics.recharge_money).toFixed(2) : '0.00'">
<template #title>
<div class="text-[14px] mb-[9px]">{{ t('totalRechargeMoney') }}</div>
</template>
</el-statistic>
</el-col>
<el-col :span="12" class="min-w-[100px]">
<el-statistic
:value="rechargeStatistics.recharge_refund_money ? Number.parseFloat(rechargeStatistics.recharge_refund_money).toFixed(2) : '0.00'">
<template #title>
<div class="text-[14px] mb-[9px]">{{ t('totalRechargeRefundMoney') }}</div>
</template>
</el-statistic>
</el-col>
</el-row>
</el-card>
<el-card class="box-card !border-none mb-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="orderTableData.searchParam" ref="searchFormRef">
<el-form-item :label="t('rechargeNo')" prop="order_no">
<el-input v-model="orderTableData.searchParam.order_no" :placeholder="t('rechargeNoPlaceholder')" />
</el-form-item>
<el-form-item :label="t('orderFromName')" prop="order_from">
<el-select v-model="orderTableData.searchParam.order_from" clearable class="input-width">
<el-option :label="t('selectPlaceholder')" value="" />
<el-option :label="item" :value="key" v-for="(item, key) in channelList" :key="key"/>
</el-select>
</el-form-item>
<el-form-item :label="t('orderStatus')" prop="order_status">
<el-select v-model="orderTableData.searchParam.order_status" clearable class="input-width">
<el-option :label="t('selectPlaceholder')" value="" />
<el-option :label="item['name']" :value="item['status']" v-for="(item,index) in statusList" :key="index"/>
</el-select>
</el-form-item>
<el-form-item :label="t('createTime')" prop="create_time">
<el-date-picker v-model="orderTableData.searchParam.create_time" type="datetimerange"
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
:end-placeholder="t('endDate')" />
</el-form-item>
<el-form-item :label="t('rechargeMoney')">
<div class="region-input">
<el-form-item prop="start_money">
<input type="text" :placeholder="t('startMoney')" v-model="orderTableData.searchParam.start_money">
</el-form-item>
<span class="separator">-</span>
<el-form-item prop="end_money">
<input type="text" :placeholder="t('endMoney')" v-model="orderTableData.searchParam.end_money">
</el-form-item>
</div>
</el-form-item>
<el-form-item :label="t('payTime')">
<el-date-picker v-model="orderTableData.searchParam.pay_time" type="datetimerange"
value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')"
:end-placeholder="t('endDate')" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadOrderList()">{{ t('search') }}</el-button>
<el-button @click="searchFormRef?.resetFields()">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[16px]">
<el-table :data="orderTableData.data" size="large" v-loading="orderTableData.loading">
<template #empty>
<span>{{ !orderTableData.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column :show-overflow-tooltip="true" :label="t('member')" align="left" min-width="140">
<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="">
<div class="flex flex flex-col">
<span>{{ row.member.nickname || '' }}</span>
<span>{{ row.member.mobile || '' }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="order_no" :show-overflow-tooltip="true" :label="t('rechargeNo')" align="center" min-width="140" />
<el-table-column prop="order_money" :label="t('rechargeMoney')" align="center" min-width="140" />
<el-table-column prop="order_from_name" :label="t('orderFromName')" align="center" min-width="140" />
<el-table-column :label="t('orderStatus')" min-width="120" align="center">
<template #default="{ row }">
{{ row.order_status_info.name }}
</template>
</el-table-column>
<el-table-column prop="pay_type_name" :label="t('payTypeName')" align="center" min-width="140" />
<el-table-column :label="t('createTime')" min-width="180" align="center">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('payTime')" min-width="180" align="center">
<template #default="{ row }">
{{ row.pay_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" align="right" fixed="right" width="130">
<template #default="{ row }">
<el-button type="primary" link @click="infoEvent(row)">{{ t('info') }}</el-button>
<el-button
v-if="[1, 10].includes(row.order_status_info.status) && row.is_enable_refund && row.refund_status == 0"
type="primary" link @click="refundFn(row)">{{ t('refundBtn') }}</el-button>
<template v-for="(item, index) in row.order_status_info.action" :key="index">
<el-button type="primary" link @click="orderEvent(row, item.class)">{{ item.name }}</el-button>
</template>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="orderTableData.page" v-model:page-size="orderTableData.limit"
layout="total, sizes, prev, pager, next, jumper" :total="orderTableData.total"
@size-change="loadOrderList()" @current-change="loadOrderList" />
</div>
</div>
</el-card>
<!-- 是否退款 -->
<el-dialog v-model="refundShowDialog" :title="t('refundBtn')" width="500px" :destroy-on-close="true">
<p>{{ t('refundContent') }}</p>
<template #footer>
<span class="dialog-footer">
<el-button @click="refundShowDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" @click="confirmRefund" :loading="refundLoading">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { getRechargeOrderStatusList, getRechargeOrderList, rechargeRefund, getRechargeStat } from '@/app/api/order'
import { getChannelType } from '@/app/api/sys'
import { useRouter, useRoute } from 'vue-router'
import { AnyObject } from '@/types/global'
import type { FormInstance } from 'element-plus'
import { img } from '@/utils/common'
const route = useRoute()
const router = useRouter()
const pageName = route.meta.title
const memberId: number = parseInt(route.query.id || 0)
const channelList = ref([])
const setChannelList = async () => {
channelList.value = await (await getChannelType({})).data
}
setChannelList()
const orderTableData = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
order_no: '',
order_status: '',
member_id: memberId,
create_time: [],
pay_time: [],
order_from: '',
start_money: '',
end_money: ''
}
})
const rechargeStatistics = ref([])
const checkRechargeInfo = () => {
getRechargeStat({
member_id: memberId
}).then(res => {
rechargeStatistics.value = res.data
})
}
checkRechargeInfo()
const statusList = ref([])
const searchFormRef = ref<FormInstance>()
const setCategoryList = async () => {
statusList.value = await (await getRechargeOrderStatusList()).data
}
setCategoryList()
/**
* 获取文章列表
*/
const loadOrderList = (page: number = 1) => {
orderTableData.loading = true
orderTableData.page = page
getRechargeOrderList({
page: orderTableData.page,
limit: orderTableData.limit,
...orderTableData.searchParam
}).then(res => {
orderTableData.loading = false
orderTableData.data = res.data.data
orderTableData.total = res.data.total
}).catch(() => {
orderTableData.loading = false
})
}
loadOrderList()
/**
* 订单详情
* @param data
*/
const infoEvent = (data: any) => {
router.push(`/order/recharge/detail?order_id=${data.order_id}`)
}
/**
* 订单操作
*/
const orderEvent = (data: any, type: string) => {
}
/**
* 退款操作
*/
const refundShowDialog = ref(false)
let refundData: AnyObject | null = null
const refundLoading = ref(false)
const refundFn = (data: AnyObject) => {
refundShowDialog.value = true
refundData = data
}
/**
* 确认退款
*/
const confirmRefund = () => {
if (refundLoading.value) return
refundLoading.value = true
rechargeRefund(refundData?.order_id).then(res => {
refundShowDialog.value = false
refundLoading.value = false
}).catch(() => {
refundLoading.value = false
})
}
/**
* 会员详情
*/
const toMember = (memberId: number) => {
router.push(`/member/detail?id=${memberId}`)
}
</script>
<style lang="scss" scoped></style>

View File

@ -1,238 +0,0 @@
<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-page-title">{{ pageName }}</span>
</div>
<el-card class="box-card !border-none table-search-wra base-bg !px-[35px]" shadow="never">
<el-row class="flex">
<el-col :span="12">
<div class="statistic-card">
<el-statistic :value="refundStat.refund_all_money"></el-statistic>
<div class="statistic-footer">
<div class="footer-item text-[14px] text-[#666]">
<span>{{ t('accumulateRefundMoney') }}</span>
</div>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="statistic-card">
<el-statistic :value="refundStat.refund_have_money"></el-statistic>
<div class="statistic-footer">
<div class="footer-item text-[14px] text-[#666]">
<span>{{ t('haveRefundMoney') }}</span>
</div>
</div>
</div>
</el-col>
</el-row>
</el-card>
<el-card class="box-card !border-none mb-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="refundTableData.searchParam" ref="searchFormRef">
<el-form-item :label="t('memberInfo')" prop="keywords">
<el-input v-model="refundTableData.searchParam.keywords" class="w-[240px]" :placeholder="t('memberInfoPlaceholder')" />
</el-form-item>
<el-form-item :label="t('refundNumber')" prop="refund_no">
<el-input v-model="refundTableData.searchParam.refund_no" class="w-[240px]" :placeholder="t('refundNumberPlaceholder')" />
</el-form-item>
<el-form-item :label="t('orderNumber')" prop="order_no">
<el-input v-model="refundTableData.searchParam.order_no" class="w-[240px]" :placeholder="t('orderNumberPlaceholder')" />
</el-form-item>
<el-form-item :label="t('refundStatus')" prop="status">
<el-select v-model="refundTableData.searchParam.status" clearable class="input-width">
<el-option :label="t('selectPlaceholder')" value="" />
<el-option :label="item.name" :value="key" v-for="(item, key) in refundList" :key="key" />
</el-select>
</el-form-item>
<el-form-item :label="t('refundTime')" prop="create_time">
<el-date-picker v-model="refundTableData.searchParam.create_time" type="datetimerange" value-format="YYYY-MM-DD HH:mm:ss" :start-placeholder="t('startDate')" :end-placeholder="t('endDate')" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadRefundList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div>
<el-table :data="refundTableData.data" size="large" v-loading="refundTableData.loading">
<template #empty>
<span>{{ !refundTableData.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column :show-overflow-tooltip="true" :label="t('memberInfo')" align="left" min-width="140">
<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="">
<div class="flex flex flex-col">
<span>{{ row.member.nickname || '' }}</span>
<span>{{ row.member.mobile || '' }}</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="refund_no" :label="t('refundNumber')" align="center" min-width="200" />
<el-table-column prop="item.item_name" :label="t('refundSource')" align="center" min-width="140" />
<el-table-column prop="money" :label="t('refundAmount')" align="center" min-width="140" />
<el-table-column :label="t('refundTime')" min-width="180" align="center">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('statusName')" min-width="180" align="center">
<template #default="{ row }">
{{ row.status_name || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" align="right" fixed="right" width="130">
<template #default="{ row }">
<el-button type="primary" link @click="infoEvent(row)">{{ t('info') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="refundTableData.page" v-model:page-size="refundTableData.limit"
layout="total, sizes, prev, pager, next, jumper" :total="refundTableData.total"
@size-change="loadRefundList()" @current-change="loadRefundList" />
</div>
</div>
</el-card>
<el-dialog v-model="refundInfoShowDialog" :title="t('refundDetail')" width="500px" :destroy-on-close="true">
<el-form :model="refundInfo" label-width="120px" ref="formRef" :rules="formRules" class="page-form">
<el-form-item :label="t('nickname')">
<div class="input-width"> {{ refundInfo.member.nickname }} </div>
</el-form-item>
<el-form-item :label="t('refundSource')">
<div class="input-width"> {{ refundInfo.item.item_name }} </div>
</el-form-item>
<el-form-item :label="t('refundAmount')">
<div class="input-width"> {{ refundInfo.money }} </div>
</el-form-item>
<el-form-item :label="t('orderNumber')">
<div class="input-width"> {{ refundInfo.item.order_no }} </div>
</el-form-item>
<el-form-item :label="t('refundNumber')">
<div class="input-width"> {{ refundInfo.refund_no }} </div>
</el-form-item>
<el-form-item :label="t('refundTime')">
<div class="input-width"> {{ refundInfo.create_time }} </div>
</el-form-item>
<el-form-item :label="t('statusName')">
<div class="input-width"> {{ refundInfo.status_name }} </div>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="refundInfoShowDialog = false">{{ t('confirm') }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { t } from '@/lang'
import { img } from '@/utils/common'
import { useRouter, useRoute } from 'vue-router'
import { getRechargeRefund, getRechargeRefundStatus, getRechargeRefundStat } from '@/app/api/order'
import { FormInstance } from 'element-plus'
const router = useRouter()
const route = useRoute()
const pageName = route.meta.title
const searchFormRef = ref<FormInstance>()
const refundTableData = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam: {
refund_no: '',
// member_id,
create_time: [],
status: '',
keywords: '',
order_no: ''
}
})
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadRefundList()
}
/**
* 获取退款列表
*/
const loadRefundList = (page: number = 1) => {
refundTableData.loading = true
refundTableData.page = page
getRechargeRefund({
page: refundTableData.page,
limit: refundTableData.limit,
...refundTableData.searchParam
}).then(res => {
refundTableData.loading = false
refundTableData.data = res.data.data
refundTableData.total = res.data.total
}).catch(() => {
refundTableData.loading = false
})
}
loadRefundList()
const refundList = ref([])
const checkRefundList = () => {
getRechargeRefundStatus().then(res => {
refundList.value = res.data
})
}
checkRefundList()
const refundStat = reactive({
refund_all_money: 0.00,
refund_have_money: 0.00,
refund_Success_money: 0.00,
refund_fail_moey: 0.00
})
const checkRefundStat = () => {
getRechargeRefundStat().then(res => {
refundStat.refund_all_money = res.data.all.money
refundStat.refund_have_money = res.data.have.money
refundStat.refund_Success_money = res.data['3'].money
refundStat.refund_fail_moey = res.data['-1'].money
})
}
checkRefundStat()
const refundInfoShowDialog = ref(false)
const refundInfo = ref({})
const infoEvent = (info:any) => {
refundInfo.value = info
refundInfoShowDialog.value = true
}
/**
* 会员详情
*/
const toMember = (memberId: number) => {
router.push(`/member/detail?id=${memberId}`)
}
</script>
<style lang="scss" scoped></style>

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 || '/admin/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 || '/admin/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

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

View File

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

View File

@ -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

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

View File

@ -6,19 +6,19 @@
<h3 class="panel-title !text-sm">{{ t('commonSetting') }}</h3>
<el-form-item :label="t('logonMode')" prop="type">
<el-checkbox v-model="formData.is_username" :label="t('isUsername')" @change="switchChange($event, 'is_username')" />
<el-checkbox v-model="formData.is_username" :label="t('isUsername')" :true-value="1" :false-value="0" @change="switchChange($event, 'is_username')" />
<div class="form-tip">{{ t('isUsernameTip') }}</div>
<el-checkbox v-model="formData.is_mobile" :label="t('isMobile')" @change="switchChange($event, 'is_mobile')" />
<el-checkbox v-model="formData.is_mobile" :label="t('isMobile')" :true-value="1" :false-value="0" @change="switchChange($event, 'is_mobile')" />
<div class="form-tip">{{ t('isMobileTip') }}</div>
</el-form-item>
<el-form-item :label="t('isBindMobile')" prop="formData.is_bind_mobile">
<el-switch v-model="formData.is_bind_mobile" @change="switchChange($event, 'is_bind_mobile')" />
<el-switch v-model="formData.is_bind_mobile" :active-value="1" :inactive-value="0" @change="switchChange($event, 'is_bind_mobile')" />
<div class="form-tip">{{ t('isBindMobileTip') }}</div>
</el-form-item>
<el-form-item :label="t('agreement')" prop="formData.agreement_show">
<el-switch v-model="formData.agreement_show" @change="switchChange($event, 'agreement_show')" />
<el-switch v-model="formData.agreement_show" :active-value="1" :inactive-value="0" @change="switchChange($event, 'agreement_show')" />
<div class="form-tip">{{ t('agreementTips') }}</div>
</el-form-item>
</el-card>
@ -27,7 +27,7 @@
<h3 class="panel-title !text-sm">{{ t('tripartiteSetting') }}</h3>
<el-form-item :label="t('isAuthRegister')" prop="formData.is_auth_register">
<el-switch v-model="formData.is_auth_register" @change="switchChange($event, 'is_auth_register')" />
<el-switch v-model="formData.is_auth_register" :active-value="1" :inactive-value="0" @change="switchChange($event, 'is_auth_register')" />
<div class="form-tip">{{ t('isAuthRegisterTip') }}</div>
</el-form-item>
</el-card>
@ -47,6 +47,7 @@ import { t } from '@/lang'
import { getLoginConfig, setLoginConfig } from '@/app/api/member'
import { FormInstance } from 'element-plus'
import { useRoute } from 'vue-router'
import { cloneDeep } from 'lodash-es'
const route = useRoute()
const pageName = route.meta.title
@ -63,26 +64,26 @@ 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()
// }
// }
// }
// ]
}
})
const setFormData = async (id: number = 0) => {
const setFormData = async () => {
const data = await (await getLoginConfig()).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = Boolean(Number(data[key]))
if (data[key] != undefined) formData[key] = Number(data[key])
})
loading.value = false
}
@ -96,7 +97,7 @@ const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate((valid) => {
if (valid) {
const save = JSON.parse(JSON.stringify(formData))
const save = cloneDeep(formData)
Object.keys(save).forEach((key) => {
save[key] = Number(save[key])
})

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('noticeKeyPlaceholder')" 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>

View File

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

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