diff --git a/.env.development b/.env.development index 2ccc7eb..8fa72ce 100644 --- a/.env.development +++ b/.env.development @@ -1,4 +1,4 @@ -# VITE_API_BASE='https://hwjb.homilychart.com/dev/admin' +VITE_API_BASE='https://hwjb.homilychart.com/dev/admin' # 测试环境 # VITE_API_BASE='http://54.255.212.181:10704/' # 正式环境 @@ -13,7 +13,7 @@ VITE_UPLOAD_URL=http://39.101.133.168:8828/hljw/api/aws/upload # 本地 # VITE_API_BASE='http://localhost:8081/' # 孙加倍 -VITE_API_BASE='http://192.168.40.12:8081' +# VITE_API_BASE='http://192.168.40.12:8081' # Lijianlin # VITE_API_BASE='http://192.168.9.41:8081/' diff --git a/src/router/index.js b/src/router/index.js index 4c20539..7176533 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -319,7 +319,7 @@ const routes = [ { path: 'receiveManager', name: "receiveManager", - component: () => import("../views/moneyManage/receiveDetail/receiveManage.vue"), + component: () => import("../views/moneyManage/receiveDetail/receiveFinance.vue"), meta: { permissionId: [67, 79] } }, {//地区财务 @@ -385,7 +385,7 @@ const routes = [ }, // 频道管理 { - path: '/channelManage', + path: 'channelManage', name: 'channelManage', meta: { permissionId: 124 }, children: [ diff --git a/src/utils/menuTreePermission.js b/src/utils/menuTreePermission.js index 99dc1b9..a502085 100644 --- a/src/utils/menuTreePermission.js +++ b/src/utils/menuTreePermission.js @@ -187,7 +187,7 @@ export const findMenuById = (menuList, targetId) => { // 递归判断某个 menuId 是否存在 export const hasMenuPermission = (tree, targetId) => { for (const node of tree) { - console.log(node.id) + // console.log(node.id) if (node.id === targetId) return true; if (node.children && hasMenuPermission(node.children, targetId)) return true; } diff --git a/src/utils/menuUtils.js b/src/utils/menuUtils.js index aec0e4e..b8ba460 100644 --- a/src/utils/menuUtils.js +++ b/src/utils/menuUtils.js @@ -91,8 +91,13 @@ export const getRoutePath = (menu) => { '退款-总部财务':'/moneyManage/refundDetail/refundHeader', '执行明细': '/moneyManage/executor', - }; + '频道管理': '/channelManage', + '打赏管理': '/channelManage/reward', + '铁粉管理': '/channelManage/fans', + '小黄车管理': '/channelManage/cart', + }; + // console.log('1111',menu.menuName) // 未匹配的菜单默认使用id作为路由(可根据实际需求调整) return routeMap[menu.menuName] || '/noPermission' diff --git a/src/views/audit/bean/beanAudit.vue b/src/views/audit/bean/beanAudit.vue index a6dcdc7..81c0fd3 100644 --- a/src/views/audit/bean/beanAudit.vue +++ b/src/views/audit/bean/beanAudit.vue @@ -173,6 +173,9 @@ const reason = ref('') const rejectRow = ref({ id: null })// 驳回行数据 +const passRow = ref({ + id: null +})// 通过行数据 const popconfirmRef = ref(null) // 操作权限(金豆审核相关,与充值权限格式对齐) @@ -337,13 +340,14 @@ const showApproveDialog = (row) => { ElMessage.error('暂无权限') return } + passRow.value.id = row.id approveDialogVisible.value = true } // 处理通过操作 // 为什么使用handleApproveConfirm页面就加载不出来,使用handleApprove就可以, // (发现问题:加了防抖,名称为handleApprove,修改名称一致即可) -const handleApproveConfirm = async (row) => { +const handleApproveConfirm = async function() {// 不要再传row了!哪有row!!! if (!hasbeanWaitThough) { ElMessage.error('暂无权限') return @@ -351,7 +355,7 @@ const handleApproveConfirm = async (row) => { clicked.value = true try { const params = { - id: row.id, + id: passRow.value.id, auditName: adminData.value.adminName } await API({ url: '/beanAudit/status1', data: params }) diff --git a/src/views/channelManage/cart/cart.vue b/src/views/channelManage/cart/cart.vue index e69de29..9695aed 100644 --- a/src/views/channelManage/cart/cart.vue +++ b/src/views/channelManage/cart/cart.vue @@ -0,0 +1,676 @@ + + + + + \ No newline at end of file diff --git a/src/views/channelManage/fans/fans.vue b/src/views/channelManage/fans/fans.vue index e69de29..b2c8733 100644 --- a/src/views/channelManage/fans/fans.vue +++ b/src/views/channelManage/fans/fans.vue @@ -0,0 +1,657 @@ + + + + + diff --git a/src/views/channelManage/reward/reward.vue b/src/views/channelManage/reward/reward.vue index e69de29..aff62ee 100644 --- a/src/views/channelManage/reward/reward.vue +++ b/src/views/channelManage/reward/reward.vue @@ -0,0 +1,700 @@ + + + + + diff --git a/src/views/moneyManage/receiveDetail/receiveFinance.vue b/src/views/moneyManage/receiveDetail/receiveFinance.vue index e09f91a..34cc35f 100644 --- a/src/views/moneyManage/receiveDetail/receiveFinance.vue +++ b/src/views/moneyManage/receiveDetail/receiveFinance.vue @@ -190,8 +190,7 @@ - + + +
+
+ +
+
+ {{ textContent }} +
+
+ +
+
+ +
+
@@ -406,6 +424,108 @@ + + + +
+
+
+ 精网号 + +
+
+ 客户姓名 + +
+
+ 所属地区 + +
+
+ 活动名称 + +
+
+ 产品名称 + +
+
+ 产品数量 + +
+
+
+ 永久金币: + +
+
+ 免费金币: + +
+
+
+ 付款币种 + +
+
+ 付款金额 + +
+
+ 支付方式 + +
+
+ 付款时间 + +
+
+ 转账凭证 + + + + + +
+
+ 备注 + +
+
+
+
+ 退款模式 + + 全部退款 + 部分退款 + +
+
+ 退款理由 + +
+
ps:请在退款理由表明用户的退款需求。
+
+ 重置 + 提交 +
+
+
+
@@ -419,6 +539,7 @@ import request from '@/util/http.js'; import moment from 'moment'; import _ from 'lodash'; import { Plus } from '@element-plus/icons-vue'; +import { startsWith } from './utils/util.js' // 地区财务专属组件 import CurrencySelect from '@/components/MoneyManage/CurrencySelect.vue'; @@ -474,7 +595,38 @@ const tooltipContent = ref(''); const tooltipLeft = ref(0); const tooltipTop = ref(0); -// 基础数据(地区财务专用) +// 退款确认弹窗 +const refundConfirmDialog = ref(false) +const textContent = ref('') + + +//退款弹窗 +const refundDialog = ref(false) +const refundFormData = ref({}) + +const openRefundDialog = () => { + refundDialog.value = true + closeConfirmRefund() + +} +const closeRefundForm = () => { + refundDialog.value = false + refundFormData.value = {} +} + +const isRefundGold = ref(false) +const ifRefundGold = () => { + if (refundFormData.value.goodsName === '金币充值') { + isRefundGold.value = true + refundFormData.value.goodNum = 0 + } else { + isRefundGold.value = false + } +} + + + +// 基础数据 const adminData = ref({}); const activityList = ref([]); const customOptions = ref(['美元(USD)', '港币(HKD)', '新币(SGD)', '马币(MYR)', '泰铢(THB)', '加币(CAD)', '越南盾(VDN)', '韩元(KRW)']); @@ -482,6 +634,23 @@ const paytypeList = ["Stripe-链接收款", "PaymentAsia-链接收款", "Ipay88- const paytypeOptions = ref([...paytypeList]); // ===================== 2. 核心功能函数(仅地区财务) ===================== + +//确认退款弹窗 +const openRefundConfirm = (row) => { + textContent.value = '将要对该订单退款!' + refundConfirmDialog.value = true + refundFormData.value = { ...row } + ifRefundGold() + console.log(row); + +} + +const closeConfirmRefund = () => { + refundConfirmDialog.value = false + textContent.value = '' +} + + // 2.1 数据加载:获取地区财务订单列表 const getlist = async () => { try { @@ -544,6 +713,54 @@ const getlist = async () => { } }; +//提交退款 +const submitRefund = async () => { + try { + const result = await request({ + url: '/Money/add', + data: { + jwcode: refundFormData.value.jwcode, // 精网号(必填) + name: refundFormData.value.name, // 姓名(必填) + market: refundFormData.value.marketName, // 所属地区(必填) + activity: refundFormData.value.activity, // 活动名称(可选) + bankCode: refundFormData.value.bankCode, // 银行流水订单号(必填) + goodsName: refundFormData.value.goodsName, // 商品名称(必填) + goodNum: refundFormData.value.goodNum, // 商品数量(必填,默认0) + paymentCurrency: refundFormData.value.paymentCurrency, // 付款币种(必填) + paymentAmount: (refundFormData.value.paymentAmount) * 100, // 付款金额(必填) + receivedCurrency: refundFormData.value.receivedCurrency, // 到账币种(必填) + receivedAmount: (refundFormData.value.receivedAmount) * 100, // 到账金额(必填) + handlingCharge: (refundFormData.value.handlingCharge) * 100, // 手续费(可选) + receivedMarket: refundFormData.value.receivedMarket, // 到账地区(可选) + payType: refundFormData.value.payType, // 支付方式(必填) + payTime: refundFormData.value.payTime, // 付款时间,格式:yyyy-MM-dd HH:mm:ss(可选) + receivedTime: refundFormData.value.receivedTime, // 到账时间,格式:yyyy-MM-dd HH:mm:ss(可选) + areaServise: adminData.value.adminName, // 提交人(可选) + submitterId: adminData.value.id, + voucher: refundFormData.value.voucher, // 转账凭证URL(可选) + remark: refundFormData.value.remark, // 备注信息(可选) + refundReason: refundFormData.value.refundReason, // 退款备注-客服填写(可选) + refundModel: refundFormData.value.refundModel, // 退款方式:0-全额,1-部分(可选) + id: refundFormData.value.id, //订单id + orderCode: refundFormData.value.orderCode, + permanentGold: (refundFormData.value.permanentGold) * 100 || 0, + freeGold: (refundFormData.value.freeGold) * 100 || 0 + } + }) + if (result.code == 200) { + ElMessage.success('新增退款成功') + getlist() + closeRefundForm() + } else { + ElMessage.error(result.msg) + getlist() + } + console.log('返回参数:', result); + } catch (error) { + console.log(error); + } +} + // 2.2 搜索与重置 const search = () => { getlist(); @@ -823,6 +1040,9 @@ onMounted(async () => { window.history.back(); }); } + //背景预加载 + const bgImg = new Image(); + bgImg.src = '/src/assets/收款明细撤回背景.png'; }); // 2.10 未使用函数占位(避免报错) @@ -1102,6 +1322,37 @@ const handlePagination = (type, val) => { font-weight: 800; padding-bottom: 15px; } + + .refundDialog { + .left { + width: 50%; + height: 70vh; + min-height: 700px; + padding: 0 2vw; + + .add-item { + display: flex; + align-items: center; + margin-bottom: 1vh; + } + + .image { + width: 4vw !important; + height: 4vw !important; + } + } + + .right { + width: 50%; + height: 50vh; + + .add-item { + display: flex; + align-items: center; + margin-bottom: 1vh; + } + } + } } // 表格样式统一 @@ -1130,4 +1381,80 @@ const handlePagination = (type, val) => { overflow-y: auto; white-space: pre-wrap; } + +.recallDialog { + //撤回弹窗提示 + height: 392px; + width: 700px; + background-image: url('/src/assets/收款明细撤回背景.png'); + position: fixed; // 固定定位,相对于浏览器窗口 + top: 50%; // 距离顶部50% + left: 50%; // 距离左侧50% + transform: translate(-50%, -50%); // 向左、向上平移自身宽高的50%,实现居中 + z-index: 1000; // 确保在其他元素上层显示 + + .close { + position: absolute; + left: 625px; + top: 20px; + height: 38px; + width: 38px; + opacity: 0; + + .Btn { + height: 100%; + width: 100%; + border-radius: 10px; + } + } + + .text { + position: absolute; + left: 185px; + top: 190px; + height: 67px; + width: 500px; + + .txt { + height: 100%; + width: 100%; + color: #001a42; + font-family: "PingFang SC"; + font-size: 48px; + font-style: normal; + font-weight: 900; + line-height: normal; + } + } + + .cancle { + position: absolute; + left: 185px; + top: 304px; + height: 55px; + width: 150px; + opacity: 0; + + .Btn { + height: 100%; + width: 100%; + border-radius: 20px; + } + } + + .confirm { + position: absolute; + left: 375px; + top: 304px; + height: 55px; + width: 150px; + opacity: 0; + + .Btn { + height: 100%; + width: 100%; + border-radius: 20px; + } + } +} \ No newline at end of file diff --git a/src/views/moneyManage/receiveDetail/receiveManage.vue b/src/views/moneyManage/receiveDetail/receiveManage.vue deleted file mode 100644 index 539f8c8..0000000 --- a/src/views/moneyManage/receiveDetail/receiveManage.vue +++ /dev/null @@ -1,1174 +0,0 @@ - - - \ No newline at end of file diff --git a/src/views/moneyManage/receiveDetail/receiveService.vue b/src/views/moneyManage/receiveDetail/receiveService.vue index 609c3d0..d797412 100644 --- a/src/views/moneyManage/receiveDetail/receiveService.vue +++ b/src/views/moneyManage/receiveDetail/receiveService.vue @@ -363,6 +363,14 @@ 部分退款 +
+ 永久金币 +   个 +
+
+ 免费金币 +   个 +
退款理由 { + // 处理前缀为空字符串的情况(空字符串是所有字符串的前缀) + if (prefix === '') { + return true; + } + // 处理主字符串长度小于前缀长度的情况 + if (mainStr.length < prefix.length) { + return false; + } + // 比较主字符串开头与前缀相同长度的部分 + return mainStr.substring(0, prefix.length) === prefix; +} \ No newline at end of file diff --git a/src/views/permissions/rolePermission.vue b/src/views/permissions/rolePermission.vue index d8f34d0..341a6b0 100644 --- a/src/views/permissions/rolePermission.vue +++ b/src/views/permissions/rolePermission.vue @@ -9,6 +9,7 @@ import { storeToRefs } from "pinia" const adminStore = useAdminStore(); const { adminData, menuTree } = storeToRefs(adminStore); import { permissionMapping, findMenuById } from "@/utils/menuTreePermission.js" +import { tr } from 'element-plus/es/locales.mjs' // 表单验证ref const Ref = ref(null) @@ -35,7 +36,7 @@ const addRole = ref({ market: '' }) const addRoleMarket = ref([]) - +const channelList = ref(['美股', '港股', 'hc第一频道']) const getRoleList = async function (val) { if (!findMenuById(menuTree.value, permissionMapping.view_role_information)) { ElMessage.error('无此权限') @@ -196,7 +197,8 @@ const handleAddRole = async function () { "roleName": addRole.value.roleName, "menuIds": finalCheckedKeys, "fatherId": addRole.value.parentId, - "market": addRole.value.market + "market": addRole.value.market, + channel: addRole.value.channel } }) if (res.code === 200) { @@ -317,6 +319,7 @@ const handleEditRolePermissionCheck = (checkedNodes, checkedInfo) => { // 判断是否有选中的节点 if (allCheckedNodes.length === 0) { permissionEditRoleObj.value.checkedKeys = [] + ifHasChannel.value = false return } @@ -326,13 +329,22 @@ const handleEditRolePermissionCheck = (checkedNodes, checkedInfo) => { console.log('编辑角色选中的权限ID:', checkedKeys) console.log('选中的节点数量:', allCheckedNodes.length) + if (checkedKeys.includes(124) || checkedKeys.includes(125) || checkedKeys.includes(126) || checkedKeys.includes(127)) { + ifHasChannel.value = true + } else { + ifHasChannel.value = false + } }; + +//用于标记是否勾选频道管理 +const ifHasChannel = ref(false) const handleCheckChange = async (checkedNodes, checkedInfo) => { const { checkedKeys, checkedNodes: allCheckedNodes } = checkedInfo // 判断是否有选中的节点 if (allCheckedNodes.length === 0) { addRole.value.checkedKeys = [] + ifHasChannel.value = false return } @@ -348,6 +360,12 @@ const handleCheckChange = async (checkedNodes, checkedInfo) => { // 将Set转换为数组并更新 addRole.value.checkedKeys = Array.from(allKeys) console.log('新增角色包含所有父级的选中项:', addRole.value.checkedKeys) + if (addRole.value.checkedKeys.includes(124)) { + ifHasChannel.value = true + console.log('勾选了频道'); + } else { + ifHasChannel.value = false + } } const selectParentNodes = (treeData, nodeId, checkedKeys) => { if (!Array.isArray(treeData)) return false @@ -413,18 +431,38 @@ const collectIds2 = (tree) => { return ids } +const collectIdsAll = (tree) => { + let ids = [] + tree.forEach((node) => { + ids.push(node.id) + // 如果当前节点没有 children 或 children 为空,说明是叶子节点 + if (node.children || node.children.length === 0) { + ids = ids.concat(collectIdsAll(node.children)) + } + }) + return ids +} + // 编辑角色初始化 const permissionEditRoleInit = async function (row) { console.log('row', row) console.log('row.tree', row.tree) + let EditIds = collectIdsAll(row.tree) + console.log(EditIds); + permissionEditRoleObj.value = {} permissionEditRoleObj.value.id = row.id permissionEditRoleObj.value.roleName = row.roleName permissionEditRoleObj.value.market = row.market permissionEditRoleObj.value.parentId = row.fatherId permissionEditRoleObj.value.parentName = row.fatherName - + permissionEditRoleObj.value.channel = row.channel + if (EditIds.includes(124)) { + ifHasChannel.value = true + } else { + ifHasChannel.value = false + } try { let roleId = permissionEditRoleObj.value.parentId; // 如果没有上级角色,设置为管理员的id @@ -636,9 +674,9 @@ onMounted(async function () {
- +
@@ -686,6 +724,11 @@ onMounted(async function () { 暂无数据 + + + + +
@@ -729,6 +772,12 @@ onMounted(async function () { 暂无数据
+ + + + + +