682 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			HTML
		
	
	
	
			
		
		
	
	
			682 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			HTML
		
	
	
	
| <!DOCTYPE html>
 | |
| <html lang="zh-CN">
 | |
| <head>
 | |
|     <meta charset="UTF-8">
 | |
|     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | |
|     <title>商户管理</title>
 | |
|     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
 | |
|     <style>
 | |
|         * {
 | |
|             margin: 0;
 | |
|             padding: 0;
 | |
|             box-sizing: border-box;
 | |
|         }
 | |
| 
 | |
|         body {
 | |
|             font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", 微软雅黑, Arial, sans-serif;
 | |
|             background-color: #f5f5f5;
 | |
|             color: #333;
 | |
|             height: 100vh;
 | |
|             margin: 0;
 | |
|             padding: 0;
 | |
|         }
 | |
| 
 | |
|         .container {
 | |
|             max-width: 1600px;
 | |
|             margin: 0 auto;
 | |
|             padding: 20px;
 | |
|         }
 | |
| 
 | |
|         .page-header {
 | |
|             background: white;
 | |
|             padding: 16px 24px;
 | |
|             margin-bottom: 16px;
 | |
|             border-radius: 8px;
 | |
|             box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
 | |
|         }
 | |
| 
 | |
|         .page-title {
 | |
|             font-size: 24px;
 | |
|             font-weight: 600;
 | |
|             color: #262626;
 | |
|         }
 | |
| 
 | |
|         .btn {
 | |
|             padding: 10px 20px;
 | |
|             border: none;
 | |
|             border-radius: 5px;
 | |
|             cursor: pointer;
 | |
|             font-size: 14px;
 | |
|             font-weight: 500;
 | |
|             transition: all 0.3s ease;
 | |
|             display: inline-flex;
 | |
|             align-items: center;
 | |
|             gap: 5px;
 | |
|         }
 | |
| 
 | |
|         .btn-success {
 | |
|             background-color: #52c41a;
 | |
|             color: #fff;
 | |
|         }
 | |
| 
 | |
|         .btn-success:hover {
 | |
|             background-color: #73d13d;
 | |
|         }
 | |
| 
 | |
|         .btn-warning {
 | |
|             background-color: #faad14;
 | |
|             color: #fff;
 | |
|         }
 | |
| 
 | |
|         .btn-warning:hover {
 | |
|             background-color: #ffc53d;
 | |
|         }
 | |
| 
 | |
|         .section {
 | |
|             background: white;
 | |
|             padding: 24px;
 | |
|             margin-bottom: 16px;
 | |
|             border-radius: 8px;
 | |
|             box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
 | |
|         }
 | |
| 
 | |
|         .section-title {
 | |
|             font-size: 18px;
 | |
|             font-weight: 600;
 | |
|             color: #262626;
 | |
|             margin-bottom: 20px;
 | |
|             padding-bottom: 12px;
 | |
|             border-bottom: 1px solid #f0f0f0;
 | |
|         }
 | |
|         
 | |
|         .form-container {
 | |
|             background-color: #fafafa;
 | |
|             padding: 20px;
 | |
|             border-radius: 6px;
 | |
|             border: 1px solid #e8e8e8;
 | |
|         }
 | |
|         
 | |
|         .form-row {
 | |
|             display: flex;
 | |
|             gap: 20px;
 | |
|             align-items: flex-start;
 | |
|             margin-bottom: 20px;
 | |
|         }
 | |
| 
 | |
|         .form-group {
 | |
|             flex: 1;
 | |
|             display: flex;
 | |
|             flex-direction: column;
 | |
|         }
 | |
| 
 | |
|         .form-group label {
 | |
|             display: block;
 | |
|             margin-bottom: 8px;
 | |
|             font-weight: 500;
 | |
|             color: #333;
 | |
|         }
 | |
|         
 | |
|         .form-group label .required {
 | |
|             color: red;
 | |
|             margin-right: 4px;
 | |
|         }
 | |
| 
 | |
|         .form-group input,
 | |
|         .form-group select,
 | |
|         .form-group .input-display {
 | |
|             width: 100%;
 | |
|             padding: 12px 15px;
 | |
|             border: 1px solid #d9d9d9;
 | |
|             border-radius: 4px;
 | |
|             font-size: 14px;
 | |
|             transition: border-color 0.3s ease;
 | |
|             background-color: #fff;
 | |
|         }
 | |
|         
 | |
|         .form-group .input-display {
 | |
|             background-color: #f5f5f5;
 | |
|             cursor: not-allowed;
 | |
|         }
 | |
| 
 | |
|         .form-group input:focus,
 | |
|         .form-group select:focus {
 | |
|             outline: none;
 | |
|             border-color: #1890ff;
 | |
|             box-shadow: 0 0 5px rgba(24, 144, 255, 0.3);
 | |
|         }
 | |
| 
 | |
|         .password-hint {
 | |
|             padding: 12px 15px;
 | |
|             background-color: #f6ffed;
 | |
|             color: #52c41a;
 | |
|             font-weight: 500;
 | |
|             border: 1px solid #b7eb8f;
 | |
|             border-radius: 4px;
 | |
|             text-align: center;
 | |
|         }
 | |
| 
 | |
|         .permissions-container {
 | |
|             background-color: #fafafa;
 | |
|             padding: 20px;
 | |
|             border-radius: 6px;
 | |
|             border: 1px solid #e8e8e8;
 | |
|             max-height: 500px;
 | |
|             overflow-y: auto;
 | |
|         }
 | |
| 
 | |
|         .permission-tree {
 | |
|             list-style: none;
 | |
|         }
 | |
| 
 | |
|         .permission-item {
 | |
|             margin-bottom: 8px;
 | |
|         }
 | |
| 
 | |
|         .permission-node {
 | |
|             display: flex;
 | |
|             align-items: center;
 | |
|             padding: 12px 15px;
 | |
|             border-radius: 4px;
 | |
|             transition: all 0.3s ease;
 | |
|             cursor: pointer;
 | |
|             background-color: #fff;
 | |
|             border: 1px solid #e8e8e8;
 | |
|             margin-bottom: 5px;
 | |
|         }
 | |
| 
 | |
|         .permission-node.selected {
 | |
|             background-color: #e6f7ff;
 | |
|             border-color: #1890ff;
 | |
|         }
 | |
| 
 | |
|         .permission-checkbox {
 | |
|             margin-right: 12px;
 | |
|             width: 18px;
 | |
|             height: 18px;
 | |
|             cursor: pointer;
 | |
|             accent-color: #1890ff;
 | |
|         }
 | |
| 
 | |
|         .expand-btn {
 | |
|             background: none;
 | |
|             border: none;
 | |
|             cursor: pointer;
 | |
|             padding: 2px 8px;
 | |
|             margin-right: 12px;
 | |
|             color: #333;
 | |
|             font-size: 14px;
 | |
|             transition: all 0.3s ease;
 | |
|             min-width: 28px;
 | |
|             display: flex;
 | |
|             align-items: center;
 | |
|             justify-content: center;
 | |
|         }
 | |
| 
 | |
|         .permission-label {
 | |
|             font-size: 14px;
 | |
|             color: #333;
 | |
|             user-select: none;
 | |
|             flex: 1;
 | |
|             font-weight: 500;
 | |
|         }
 | |
| 
 | |
|         .permission-children {
 | |
|             margin-left: 35px;
 | |
|             padding-left: 20px;
 | |
|             border-left: 1px dashed #d9d9d9;
 | |
|             display: none;
 | |
|         }
 | |
| 
 | |
|         .permission-children.expanded {
 | |
|             display: block;
 | |
|         }
 | |
| 
 | |
|         .actions {
 | |
|             background: white;
 | |
|             padding: 24px;
 | |
|             margin-bottom: 16px;
 | |
|             border-radius: 8px;
 | |
|             box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
 | |
|             display: flex;
 | |
|             justify-content: flex-end;
 | |
|             gap: 12px;
 | |
|         }
 | |
|         
 | |
|         .image-uploader {
 | |
|             width: 100px;
 | |
|             height: 100px;
 | |
|             border: 1px dashed #d9d9d9;
 | |
|             border-radius: 4px;
 | |
|             display: flex;
 | |
|             align-items: center;
 | |
|             justify-content: center;
 | |
|             cursor: pointer;
 | |
|             flex-direction: column;
 | |
|             color: #999;
 | |
|         }
 | |
|         
 | |
|         .switch {
 | |
|             position: relative;
 | |
|             display: inline-block;
 | |
|             width: 60px;
 | |
|             height: 34px;
 | |
|         }
 | |
| 
 | |
|         .switch input {
 | |
|             opacity: 0;
 | |
|             width: 0;
 | |
|             height: 0;
 | |
|         }
 | |
| 
 | |
|         .slider {
 | |
|             position: absolute;
 | |
|             cursor: pointer;
 | |
|             top: 0;
 | |
|             left: 0;
 | |
|             right: 0;
 | |
|             bottom: 0;
 | |
|             background-color: #ccc;
 | |
|             transition: .4s;
 | |
|             border-radius: 34px;
 | |
|         }
 | |
| 
 | |
|         .slider:before {
 | |
|             position: absolute;
 | |
|             content: "";
 | |
|             height: 26px;
 | |
|             width: 26px;
 | |
|             left: 4px;
 | |
|             bottom: 4px;
 | |
|             background-color: white;
 | |
|             transition: .4s;
 | |
|             border-radius: 50%;
 | |
|         }
 | |
| 
 | |
|         input:checked + .slider {
 | |
|             background-color: #52c41a;
 | |
|         }
 | |
| 
 | |
|         input:checked + .slider:before {
 | |
|             transform: translateX(26px);
 | |
|         }
 | |
|         
 | |
|     </style>
 | |
| </head>
 | |
| <body>
 | |
|     <div class="container">
 | |
|         <!-- 页面标题 -->
 | |
|         <div class="page-header">
 | |
|             <h1 class="page-title" id="pageTitle">创建新商户</h1>
 | |
|         </div>
 | |
|             <!-- 操作类型选择 -->
 | |
|             <div class="section">
 | |
|                 <div class="form-container">
 | |
|                     <div class="form-row">
 | |
|                         <div class="form-group">
 | |
|                             <label for="actionType">操作类型</label>
 | |
|                             <select id="actionType">
 | |
|                                 <option value="create">创建新商户</option>
 | |
|                                 <option value="update">维护商户信息</option>
 | |
|                             </select>
 | |
|                         </div>
 | |
|                     </div>
 | |
|                 </div>
 | |
|             </div>
 | |
|             
 | |
|             <div id="create-merchant">
 | |
|                 <!-- 商户信息区域 -->
 | |
|                 <div class="section">
 | |
|                     <h2 class="section-title">信息区域</h2>
 | |
|                     <div class="form-container">
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="merchantAccount"><span class="required">*</span>商户账号</label>
 | |
|                                 <input type="text" id="merchantAccount" placeholder="请输入商户账号">
 | |
|                             </div>
 | |
|                             <div class="form-group">
 | |
|                                 <label>初始密码</label>
 | |
|                                 <div class="password-hint">123456</div>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                     </div>
 | |
|                 </div>
 | |
|                 
 | |
|                 <!-- 商户需提供的信息 -->
 | |
|                 <div class="section">
 | |
|                     <h2 class="section-title">商户需提供的信息</h2>
 | |
|                     <div class="form-container">
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="boothName"><span class="required">*</span>摊位名称(顾客可见)</label>
 | |
|                                 <input type="text" id="boothName" placeholder="测试摊主">
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="mainCategory"><span class="required">*</span>主营类目</label>
 | |
|                                 <select id="mainCategory">
 | |
|                                     <option value="">请选择主营类目</option>
 | |
|                                 </select>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="boothBg"><span class="required">*</span>摊位背景图</label>
 | |
|                                 <div class="image-uploader">
 | |
|                                     <i class="fas fa-camera"></i>
 | |
|                                     <span>(0/1)</span>
 | |
|                                 </div>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="contactPhone">摊位联系电话(顾客可见)</label>
 | |
|                                 <input type="text" id="contactPhone" placeholder="请输入联系电话/手机号">
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="boothPhotos"><span class="required">*</span>摊位照片</label>
 | |
|                                 <div class="image-uploader">
 | |
|                                     <i class="fas fa-camera"></i>
 | |
|                                     <span>(0/5)</span>
 | |
|                                 </div>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="boothLocation"><span class="required">*</span>摊位位置</label>
 | |
|                                 <select id="boothLocation">
 | |
|                                     <option value="">请选择摊位位置</option>
 | |
|                                 </select>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="boothAddress"><span class="required">*</span>摊位详细地址</label>
 | |
|                                 <input type="text" id="boothAddress" placeholder="请输入摊位地址">
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="license">许可证</label>
 | |
|                                 <div class="image-uploader">
 | |
|                                     <i class="fas fa-camera"></i>
 | |
|                                     <span>(0/5)</span>
 | |
|                                 </div>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label>是否自动营业</label>
 | |
|                                 <div>
 | |
|                                     <label class="switch">
 | |
|                                       <input type="checkbox" checked>
 | |
|                                       <span class="slider"></span>
 | |
|                                     </label>
 | |
|                                 </div>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <h3 class="section-title" style="font-size: 1.2rem; margin-top: 20px;">自提点配置</h3>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="pickupLocation"><span class="required">*</span>顾客自提点位置</label>
 | |
|                                 <select id="pickupLocation">
 | |
|                                     <option value="">请选择顾客自提点位置</option>
 | |
|                                 </select>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="pickupAddress"><span class="required">*</span>自提点详细地址</label>
 | |
|                                 <input type="text" id="pickupAddress" placeholder="请输入自提点地址">
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="pickupImage">自提点位置示意图</label>
 | |
|                                 <div class="image-uploader">
 | |
|                                     <i class="fas fa-camera"></i>
 | |
|                                     <span>(0/1)</span>
 | |
|                                 </div>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                         <div class="form-row">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="deliveryTime"><span class="required">*</span>承诺送达自提点时间</label>
 | |
|                                 <input type="text" id="deliveryTime" placeholder="请输入数字">
 | |
|                             </div>
 | |
|                         </div>
 | |
|                     </div>
 | |
|                 </div>
 | |
|             </div>
 | |
|             
 | |
|             <div id="update-merchant" style="display: none;">
 | |
|                 <div class="section">
 | |
|                     <h2 class="section-title">信息区域</h2>
 | |
|                     <div class="form-container">
 | |
|                         <div class="form-row" style="align-items: flex-end;">
 | |
|                             <div class="form-group">
 | |
|                                 <label for="existingMerchantAccount">选择商户账号</label>
 | |
|                                 <select id="existingMerchantAccount">
 | |
|                                     <option value="">请选择要维护的商户</option>
 | |
|                                     <option value="merchant001">商户001</option>
 | |
|                                     <option value="merchant002">商户002</option>
 | |
|                                 </select>
 | |
|                             </div>
 | |
|                             <div class="form-group">
 | |
|                                 <button class="btn btn-warning">重置为初始密码</button>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                     </div>
 | |
|                 </div>
 | |
|             </div>
 | |
| 
 | |
|             <!-- 商户权限 -->
 | |
|             <div class="section">
 | |
|                 <h2 class="section-title">商户权限</h2>
 | |
|                 <div class="permissions-container">
 | |
|                     <ul id="permissionTree" class="permission-tree">
 | |
|                         <!-- 权限树 -->
 | |
|                     </ul>
 | |
|                 </div>
 | |
|             </div>
 | |
| 
 | |
|             <!-- 操作按钮 -->
 | |
|         <div class="actions">
 | |
|             <button class="btn btn-warning">
 | |
|                 <i class="fas fa-times"></i> 取消
 | |
|             </button>
 | |
|             <button class="btn btn-success">
 | |
|                 <i class="fas fa-save"></i> 提交
 | |
|             </button>
 | |
|         </div>
 | |
|     </div>
 | |
| 
 | |
|     <script>
 | |
|         document.addEventListener('DOMContentLoaded', () => {
 | |
|             const actionType = document.getElementById('actionType');
 | |
|             const createMerchant = document.getElementById('create-merchant');
 | |
|             const updateMerchant = document.getElementById('update-merchant');
 | |
|             const pageTitle = document.getElementById('pageTitle');
 | |
| 
 | |
|             actionType.addEventListener('change', (e) => {
 | |
|                 if (e.target.value === 'create') {
 | |
|                     createMerchant.style.display = 'block';
 | |
|                     updateMerchant.style.display = 'none';
 | |
|                     pageTitle.textContent = '创建新商户';
 | |
|                 } else {
 | |
|                     createMerchant.style.display = 'none';
 | |
|                     updateMerchant.style.display = 'block';
 | |
|                     pageTitle.textContent = '维护商户信息';
 | |
|                 }
 | |
|             });
 | |
|             
 | |
|             // 权限树JS逻辑
 | |
|             const permissions = [
 | |
|                 { id: 1, code: 'GOODS_MANAGE', name: '商品管理', parentCode: '' },
 | |
|                 { id: 2, code: 'GOODS_LIST', name: '商品列表', parentCode: 'GOODS_MANAGE' },
 | |
|                 { id: 3, code: 'GOODS_ADD', name: '添加商品', parentCode: 'GOODS_MANAGE' },
 | |
|                 { id: 4, code: 'ORDER_MANAGE', name: '订单管理', parentCode: '' },
 | |
|                 { id: 5, code: 'ORDER_LIST', name: '订单列表', parentCode: 'ORDER_MANAGE' },
 | |
|                 { id: 6, code: 'ORDER_DETAIL', name: '订单详情', parentCode: 'ORDER_MANAGE' },
 | |
|             ];
 | |
|             
 | |
|             let selectedPermissions = new Set();
 | |
|             const permissionMap = {};
 | |
|             permissions.forEach(p => permissionMap[p.code] = p);
 | |
| 
 | |
|             function buildPermissionTree(data) {
 | |
|                 const map = {};
 | |
|                 const roots = [];
 | |
|                 data.forEach(item => {
 | |
|                     map[item.code] = { ...item, children: [] };
 | |
|                 });
 | |
|                 data.forEach(item => {
 | |
|                     if (item.parentCode && map[item.parentCode]) {
 | |
|                         map[item.parentCode].children.push(map[item.code]);
 | |
|                     } else {
 | |
|                         roots.push(map[item.code]);
 | |
|                     }
 | |
|                 });
 | |
|                 return roots;
 | |
|             }
 | |
| 
 | |
|             function createPermissionNode(item) {
 | |
|                 const li = document.createElement('li');
 | |
|                 li.className = 'permission-item';
 | |
|                 
 | |
|                 const nodeDiv = document.createElement('div');
 | |
|                 nodeDiv.className = 'permission-node';
 | |
| 
 | |
|                 if (item.children.length > 0) {
 | |
|                     const expandBtn = document.createElement('button');
 | |
|                     expandBtn.className = 'expand-btn';
 | |
|                     expandBtn.innerHTML = '<i class="fas fa-chevron-right"></i>';
 | |
|                     expandBtn.onclick = (e) => {
 | |
|                         e.stopPropagation();
 | |
|                         const childrenContainer = li.querySelector('.permission-children');
 | |
|                         if (childrenContainer) {
 | |
|                             childrenContainer.classList.toggle('expanded');
 | |
|                             expandBtn.innerHTML = childrenContainer.classList.contains('expanded') 
 | |
|                                 ? '<i class="fas fa-chevron-down"></i>'
 | |
|                                 : '<i class="fas fa-chevron-right"></i>';
 | |
|                         }
 | |
|                     };
 | |
|                     nodeDiv.appendChild(expandBtn);
 | |
|                 } else {
 | |
|                     const placeholder = document.createElement('span');
 | |
|                     placeholder.style.width = '28px';
 | |
|                     placeholder.style.display = 'inline-block';
 | |
|                     nodeDiv.appendChild(placeholder);
 | |
|                 }
 | |
| 
 | |
|                 const checkbox = document.createElement('input');
 | |
|                 checkbox.type = 'checkbox';
 | |
|                 checkbox.className = 'permission-checkbox';
 | |
|                 checkbox.dataset.permissionCode = item.code;
 | |
|                 checkbox.onchange = (e) => handlePermissionChange(e, item);
 | |
|                 nodeDiv.appendChild(checkbox);
 | |
| 
 | |
|                 const label = document.createElement('span');
 | |
|                 label.className = 'permission-label';
 | |
|                 label.textContent = item.name;
 | |
|                 label.onclick = () => checkbox.click();
 | |
|                 nodeDiv.appendChild(label);
 | |
|                 
 | |
|                 li.appendChild(nodeDiv);
 | |
| 
 | |
|                 if (item.children.length > 0) {
 | |
|                     const childrenContainer = document.createElement('ul');
 | |
|                     childrenContainer.className = 'permission-children';
 | |
|                     item.children.forEach(child => {
 | |
|                         childrenContainer.appendChild(createPermissionNode(child));
 | |
|                     });
 | |
|                     li.appendChild(childrenContainer);
 | |
|                 }
 | |
|                 
 | |
|                 return li;
 | |
|             }
 | |
| 
 | |
|             function handlePermissionChange(event, permission) {
 | |
|                 const checkbox = event.target;
 | |
|                 const isChecked = checkbox.checked;
 | |
|                 const node = checkbox.closest('.permission-node');
 | |
| 
 | |
|                 if (isChecked) {
 | |
|                     selectedPermissions.add(permission.code);
 | |
|                     node.classList.add('selected');
 | |
|                     selectParentPermissions(permission);
 | |
|                     selectChildrenPermissions(permission, true);
 | |
|                 } else {
 | |
|                     selectedPermissions.delete(permission.code);
 | |
|                     node.classList.remove('selected');
 | |
|                     selectChildrenPermissions(permission, false);
 | |
|                     uncheckParentIfNeeded(permission);
 | |
|                 }
 | |
|                  console.log('Selected permissions:', Array.from(selectedPermissions));
 | |
|             }
 | |
| 
 | |
|             function selectParentPermissions(permission) {
 | |
|                 if (!permission.parentCode) return;
 | |
|                 const parent = permissionMap[permission.parentCode];
 | |
|                 if (!parent) return;
 | |
| 
 | |
|                 const parentCheckbox = document.querySelector(`[data-permission-code="${parent.code}"]`);
 | |
|                 if (parentCheckbox && !parentCheckbox.checked) {
 | |
|                     parentCheckbox.checked = true;
 | |
|                     parentCheckbox.closest('.permission-node').classList.add('selected');
 | |
|                     selectedPermissions.add(parent.code);
 | |
|                     selectParentPermissions(parent);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             function selectChildrenPermissions(permission, select) {
 | |
|                 const children = permissions.filter(p => p.parentCode === permission.code);
 | |
|                 children.forEach(child => {
 | |
|                     const childCheckbox = document.querySelector(`[data-permission-code="${child.code}"]`);
 | |
|                     if (childCheckbox) {
 | |
|                         childCheckbox.checked = select;
 | |
|                         const childNode = childCheckbox.closest('.permission-node');
 | |
|                         if (select) {
 | |
|                             selectedPermissions.add(child.code);
 | |
|                             childNode.classList.add('selected');
 | |
|                         } else {
 | |
|                             selectedPermissions.delete(child.code);
 | |
|                             childNode.classList.remove('selected');
 | |
|                         }
 | |
|                         selectChildrenPermissions(child, select);
 | |
|                     }
 | |
|                 });
 | |
|             }
 | |
| 
 | |
|             function uncheckParentIfNeeded(permission) {
 | |
|                 if (!permission.parentCode) return;
 | |
|                 const parent = permissionMap[permission.parentCode];
 | |
|                 if (!parent) return;
 | |
| 
 | |
|                 const siblings = permissions.filter(p => p.parentCode === parent.code);
 | |
|                 const hasSelectedSibling = siblings.some(s => selectedPermissions.has(s.code));
 | |
| 
 | |
|                 if (!hasSelectedSibling) {
 | |
|                     const parentCheckbox = document.querySelector(`[data-permission-code="${parent.code}"]`);
 | |
|                     if (parentCheckbox && parentCheckbox.checked) {
 | |
|                         parentCheckbox.checked = false;
 | |
|                         parentCheckbox.closest('.permission-node').classList.remove('selected');
 | |
|                         selectedPermissions.delete(parent.code);
 | |
|                         uncheckParentIfNeeded(parent);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             const treeData = buildPermissionTree(permissions);
 | |
|             const treeContainer = document.getElementById('permissionTree');
 | |
|             treeContainer.innerHTML = '';
 | |
|             treeData.forEach(item => {
 | |
|                 treeContainer.appendChild(createPermissionNode(item));
 | |
|             });
 | |
|         });
 | |
|     </script>
 | |
| </body>
 | |
| </html>
 |