综述: 更新权限管理页面和样式设计文档
- 删除账号权限分配页面文件 - 新增商户管理页面文件 - 更新样式设计文档内容
This commit is contained in:
		
							parent
							
								
									ae7ab62fc8
								
							
						
					
					
						commit
						2c1a3243ed
					
				|  | @ -0,0 +1,687 @@ | |||
| <!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 { | ||||
|             width: 100%; | ||||
|             height: 100vh; | ||||
|             margin: 0; | ||||
|             background-color: #fff; | ||||
|             border-radius: 0; | ||||
|             box-shadow: none; | ||||
|             overflow-y: auto; | ||||
|         } | ||||
| 
 | ||||
|         .header { | ||||
|             background-color: rgb(9, 84, 43); | ||||
|             color: #fff; | ||||
|             padding: 20px 30px; | ||||
|             display: flex; | ||||
|             justify-content: space-between; | ||||
|             align-items: center; | ||||
|         } | ||||
| 
 | ||||
|         .header h1 { | ||||
|             font-size: 1.8rem; | ||||
|             font-weight: 600; | ||||
|         } | ||||
| 
 | ||||
|         .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; | ||||
|         } | ||||
| 
 | ||||
|         .content { | ||||
|             padding: 30px; | ||||
|         } | ||||
| 
 | ||||
|         .section { | ||||
|             margin-bottom: 40px; | ||||
|         } | ||||
| 
 | ||||
|         .section-title { | ||||
|             font-size: 1.4rem; | ||||
|             font-weight: 600; | ||||
|             color: #333; | ||||
|             margin-bottom: 20px; | ||||
|             padding-bottom: 10px; | ||||
|             border-bottom: 2px solid #f0f0f0; | ||||
|         } | ||||
|          | ||||
|         .form-container { | ||||
|             background-color: #fafafa; | ||||
|             padding: 25px; | ||||
|             border-radius: 8px; | ||||
|             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: 25px; | ||||
|             border-radius: 8px; | ||||
|             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 { | ||||
|             display: flex; | ||||
|             justify-content: flex-end; | ||||
|             gap: 10px; | ||||
|             padding-top: 20px; | ||||
|             border-top: 1px solid #e8e8e8; | ||||
|             margin-top: 30px; | ||||
|         } | ||||
|          | ||||
|         .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="header"> | ||||
|             <h1 id="pageTitle">创建新商户</h1> | ||||
|         </div> | ||||
| 
 | ||||
|         <!-- 内容区域 --> | ||||
|         <div class="content"> | ||||
|             <!-- 操作类型选择 --> | ||||
|             <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> | ||||
|     </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> | ||||
|  | @ -1,859 +0,0 @@ | |||
| <!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 { | ||||
|             width: 100%; | ||||
|             height: 100vh; | ||||
|             margin: 0; | ||||
|             background-color: #fff; | ||||
|             border-radius: 0; | ||||
|             box-shadow: none; | ||||
|             overflow-y: auto; | ||||
|         } | ||||
| 
 | ||||
|         .header { | ||||
|             background-color: rgb(9, 84, 43); | ||||
|             color: #fff; | ||||
|             padding: 20px 30px; | ||||
|             display: flex; | ||||
|             justify-content: space-between; | ||||
|             align-items: center; | ||||
|         } | ||||
| 
 | ||||
|         .header h1 { | ||||
|             font-size: 1.8rem; | ||||
|             font-weight: 600; | ||||
|         } | ||||
| 
 | ||||
|         .header-actions { | ||||
|             display: flex; | ||||
|             gap: 10px; | ||||
|         } | ||||
| 
 | ||||
|         .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-primary { | ||||
|             background-color: #1890ff; | ||||
|             color: #fff; | ||||
|         } | ||||
| 
 | ||||
|         .btn-primary:hover { | ||||
|             background-color: #40a9ff; | ||||
|             transform: translateY(-2px); | ||||
|         } | ||||
|          | ||||
|         .tab-btn { | ||||
|             margin-right: 10px; | ||||
|         } | ||||
|          | ||||
|         .tab-btn:not(.active) { | ||||
|             background-color: #f0f0f0; | ||||
|             color: #666; | ||||
|         } | ||||
|          | ||||
|         .tab-btn:not(.active):hover { | ||||
|             background-color: #e0e0e0; | ||||
|             color: #333; | ||||
|         } | ||||
| 
 | ||||
|         .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; | ||||
|         } | ||||
| 
 | ||||
|         /* 内容区域 */ | ||||
|         .content { | ||||
|             padding: 30px; | ||||
|         } | ||||
| 
 | ||||
|         .section { | ||||
|             margin-bottom: 40px; | ||||
|         } | ||||
| 
 | ||||
|         .section-title { | ||||
|             font-size: 1.4rem; | ||||
|             font-weight: 600; | ||||
|             color: #333; | ||||
|             margin-bottom: 20px; | ||||
|             padding-bottom: 10px; | ||||
|             border-bottom: 2px solid #f0f0f0; | ||||
|         } | ||||
| 
 | ||||
|         /* 账号创建区域 */ | ||||
|         .account-form { | ||||
|             background-color: #fafafa; | ||||
|             padding: 25px; | ||||
|             border-radius: 8px; | ||||
|             border: 1px solid #e8e8e8; | ||||
|         } | ||||
| 
 | ||||
|         .form-row { | ||||
|             display: flex; | ||||
|             gap: 20px; | ||||
|             align-items: end; | ||||
|         } | ||||
| 
 | ||||
|         .form-group { | ||||
|             flex: 1; | ||||
|             margin-bottom: 20px; | ||||
|         } | ||||
| 
 | ||||
|         .form-group label { | ||||
|             display: block; | ||||
|             margin-bottom: 8px; | ||||
|             font-weight: 500; | ||||
|             color: #333; | ||||
|         } | ||||
| 
 | ||||
|         .form-group input, | ||||
|         .form-group select { | ||||
|             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:focus, | ||||
|         .form-group select:focus { | ||||
|             outline: none; | ||||
|             border-color: #1890ff; | ||||
|             box-shadow: 0 0 5px rgba(24, 144, 255, 0.3); | ||||
|         } | ||||
| 
 | ||||
|         /* 权限分配区域 */ | ||||
|         .permissions-container { | ||||
|             background-color: #fafafa; | ||||
|             padding: 25px; | ||||
|             border-radius: 8px; | ||||
|             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:hover { | ||||
|             background-color: #f5f5f5; | ||||
|             border-color: #1890ff; | ||||
|             box-shadow: 0 2px 8px rgba(24, 144, 255, 0.15); | ||||
|         } | ||||
|          | ||||
|         .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: #1890ff; | ||||
|             border: none; | ||||
|             cursor: pointer; | ||||
|             padding: 2px 8px; | ||||
|             margin-right: 12px; | ||||
|             color: #fff; | ||||
|             font-size: 14px; | ||||
|             transition: all 0.3s ease; | ||||
|             min-width: 28px; | ||||
|             border-radius: 4px; | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: center; | ||||
|         } | ||||
| 
 | ||||
|         .expand-btn.collapsed { | ||||
|             transform: rotate(-90deg); | ||||
|         } | ||||
| 
 | ||||
|         .permission-label { | ||||
|             font-size: 14px; | ||||
|             color: #333; | ||||
|             user-select: none; | ||||
|             flex: 1; | ||||
|             font-weight: 500; | ||||
|         } | ||||
| 
 | ||||
|         .permission-children { | ||||
|             margin-left: 35px; | ||||
|             margin-top: 8px; | ||||
|             border-left: 2px solid #1890ff; | ||||
|             padding-left: 20px; | ||||
|             display: none; | ||||
|             position: relative; | ||||
|         } | ||||
|          | ||||
|         .permission-children::before { | ||||
|             content: ''; | ||||
|             position: absolute; | ||||
|             left: 0; | ||||
|             top: -8px; | ||||
|             height: calc(100% + 16px); | ||||
|             width: 2px; | ||||
|             background-color: #1890ff; | ||||
|         } | ||||
| 
 | ||||
|         .permission-children.expanded { | ||||
|             display: block; | ||||
|             animation: fadeIn 0.3s ease-in-out; | ||||
|         } | ||||
|          | ||||
|         @keyframes fadeIn { | ||||
|             from { opacity: 0; transform: translateY(-5px); } | ||||
|             to { opacity: 1; transform: translateY(0); } | ||||
|         } | ||||
| 
 | ||||
|         .permission-item.parent > .permission-node { | ||||
|             background-color: #f0f9ff; | ||||
|             border-color: #d9f3ff; | ||||
|             font-weight: 600; | ||||
|         } | ||||
| 
 | ||||
|         .permission-item.child .permission-node { | ||||
|             margin-left: 15px; | ||||
|             background-color: #fafafa; | ||||
|         } | ||||
| 
 | ||||
|         /* 操作区域 */ | ||||
|         .actions { | ||||
|             display: flex; | ||||
|             justify-content: flex-end; | ||||
|             gap: 10px; | ||||
|             padding-top: 20px; | ||||
|             border-top: 1px solid #e8e8e8; | ||||
|             margin-top: 30px; | ||||
|         } | ||||
| 
 | ||||
|         /* 响应式设计 */ | ||||
|         @media (max-width: 768px) { | ||||
|             .container { | ||||
|                 margin: 0; | ||||
|                 border-radius: 0; | ||||
|             } | ||||
|              | ||||
|             .header { | ||||
|                 padding: 15px 20px; | ||||
|                 flex-direction: column; | ||||
|                 gap: 15px; | ||||
|             } | ||||
|              | ||||
|             .content { | ||||
|                 padding: 20px; | ||||
|             } | ||||
|              | ||||
|             .form-row { | ||||
|                 flex-direction: column; | ||||
|                 gap: 0; | ||||
|             } | ||||
|         } | ||||
|     </style> | ||||
| </head> | ||||
| <body> | ||||
|     <div class="container"> | ||||
|         <!-- 头部 --> | ||||
|         <div class="header"> | ||||
|             <h1>账号权限分配</h1> | ||||
|             <div class="header-actions"> | ||||
|             </div> | ||||
|         </div> | ||||
| 
 | ||||
|         <!-- 内容区域 --> | ||||
|         <div class="content"> | ||||
|             <!-- 账号创建区域 --> | ||||
|             <div class="section"> | ||||
|                 <h2 class="section-title">账号信息</h2> | ||||
|                 <div class="account-form"> | ||||
|                     <!-- Tab导航 --> | ||||
|                     <div class="form-row"> | ||||
|                         <div class="form-group"> | ||||
|                             <label>账号类型</label> | ||||
|                             <div class="tab-container"> | ||||
|                                 <button class="btn btn-primary tab-btn active" onclick="switchTab('sub_merchant')">子经营者</button> | ||||
|                                 <button class="btn btn-primary tab-btn" onclick="switchTab('merchant')">商户</button> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                      | ||||
|                     <div class="form-row"> | ||||
|                         <div class="form-group"> | ||||
|                             <label for="typeSelect">操作类型 *</label> | ||||
|                             <select id="typeSelect" onchange="handleTypeChange()"> | ||||
|                                 <option value="">请选择操作类型</option> | ||||
|                                 <option value="create">创建新账号</option> | ||||
|                                 <option value="update">更新账号权限</option> | ||||
|                             </select> | ||||
|                         </div> | ||||
|                         <div class="form-group"> | ||||
|                             <label for="account">账号 *</label> | ||||
|                             <input type="text" id="account" placeholder="请输入账号"> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                      | ||||
|                     <!-- 初始密码字段 --> | ||||
|                     <div class="form-row" id="passwordRow" style="display: none;"> | ||||
|                         <div class="form-group"> | ||||
|                             <label for="password">初始密码</label> | ||||
|                             <span id="password" style="display: block; padding: 12px 15px; border: 1px solid #d9d9d9; border-radius: 4px; background-color: #fafafa;">123456</span> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                      | ||||
|                     <!-- 重置密码按钮 --> | ||||
|                     <div class="form-row" id="resetPasswordBtnGroup" style="display: none;"> | ||||
|                         <div class="form-group"> | ||||
|                             <label> </label> | ||||
|                             <button class="btn btn-warning" onclick="resetPassword()">重置为初始密码</button> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <!-- 权限分配区域 --> | ||||
|             <div class="section"> | ||||
|                 <h2 class="section-title">权限分配</h2> | ||||
|                 <div class="permissions-container"> | ||||
|                     <ul id="permissionTree" class="permission-tree"> | ||||
|                         <!-- 权限树将通过JavaScript动态生成 --> | ||||
|                     </ul> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <!-- 操作按钮 --> | ||||
|             <div class="actions"> | ||||
|                 <button class="btn btn-warning" onclick="cancelAssignment()"> | ||||
|                     <i class="fas fa-times"></i> 取消 | ||||
|                 </button> | ||||
|                 <button class="btn btn-success" onclick="saveAssignment()"> | ||||
|                     <i class="fas fa-save"></i> 保存分配 | ||||
|                 </button> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
|     <script> | ||||
|         // 账号类型数据 | ||||
|         const accountTypes = [ | ||||
|             { id: 1, name: '子经营者', code: 'sub_merchant' }, | ||||
|             { id: 2, name: '商户', code: 'merchant' } | ||||
|         ]; | ||||
|          | ||||
|         // 操作类型数据 | ||||
|         const operationTypes = [ | ||||
|             { value: 'create', name: '创建新账号' }, | ||||
|             { value: 'update', name: '更新账号权限' } | ||||
|         ]; | ||||
| 
 | ||||
|         // 权限数据(从权限编辑页面获取的示例数据) | ||||
|         const permissions = [ | ||||
|             { | ||||
|                 id: 1, | ||||
|                 code: 'SYSTEM', | ||||
|                 name: '系统管理', | ||||
|                 description: '系统管理模块', | ||||
|                 parentCode: '', | ||||
|                 type: 'menu' | ||||
|             }, | ||||
|             { | ||||
|                 id: 2, | ||||
|                 code: 'SYSTEM_USER', | ||||
|                 name: '用户管理', | ||||
|                 description: '用户管理功能', | ||||
|                 parentCode: 'SYSTEM', | ||||
|                 type: 'menu' | ||||
|             }, | ||||
|             { | ||||
|                 id: 3, | ||||
|                 code: 'SYSTEM_USER_ADD', | ||||
|                 name: '添加用户', | ||||
|                 description: '添加新用户按钮', | ||||
|                 parentCode: 'SYSTEM_USER', | ||||
|                 type: 'button' | ||||
|             }, | ||||
|             { | ||||
|                 id: 4, | ||||
|                 code: 'SYSTEM_USER_EDIT', | ||||
|                 name: '编辑用户', | ||||
|                 description: '编辑用户信息按钮', | ||||
|                 parentCode: 'SYSTEM_USER', | ||||
|                 type: 'button' | ||||
|             }, | ||||
|             { | ||||
|                 id: 5, | ||||
|                 code: 'SYSTEM_ROLE', | ||||
|                 name: '角色管理', | ||||
|                 description: '角色管理功能', | ||||
|                 parentCode: 'SYSTEM', | ||||
|                 type: 'menu' | ||||
|             }, | ||||
|             { | ||||
|                 id: 6, | ||||
|                 code: 'CONTENT', | ||||
|                 name: '内容管理', | ||||
|                 description: '内容管理模块', | ||||
|                 parentCode: '', | ||||
|                 type: 'menu' | ||||
|             } | ||||
|         ]; | ||||
| 
 | ||||
|         let selectedAccountType = null; | ||||
|         let selectedOperationType = null; | ||||
|         let selectedPermissions = new Set(); | ||||
| 
 | ||||
|         // 初始化页面 | ||||
|         document.addEventListener('DOMContentLoaded', function() { | ||||
|             initPermissionTree(); | ||||
|             bindEvents(); | ||||
|         }); | ||||
|          | ||||
|         // Tab切换功能 | ||||
|         function switchTab(tabCode) { | ||||
|             // 更新选中的账号类型 | ||||
|             selectedAccountType = accountTypes.find(type => type.code === tabCode); | ||||
|              | ||||
|             // 更新tab按钮样式 | ||||
|             document.querySelectorAll('.tab-btn').forEach(btn => { | ||||
|                 btn.classList.remove('active'); | ||||
|             }); | ||||
|             event.target.classList.add('active'); | ||||
|              | ||||
|             console.log('已切换到账号类型:', selectedAccountType); | ||||
|              | ||||
|             // 根据操作类型推荐权限 | ||||
|             if (selectedOperationType) { | ||||
|                 recommendPermissionsForAccountType(selectedAccountType, selectedOperationType); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 处理操作类型变化 | ||||
|         function handleTypeChange() { | ||||
|             const select = document.getElementById('typeSelect'); | ||||
|             const selectedValue = select.value; | ||||
|              | ||||
|             if (selectedValue) { | ||||
|                 selectedOperationType = operationTypes.find(type => type.value === selectedValue); | ||||
|                 console.log('已选择操作类型:', selectedOperationType); | ||||
|                  | ||||
|                 // 显示/隐藏密码字段 | ||||
|                 const passwordRow = document.getElementById('passwordRow'); | ||||
|                 const resetPasswordBtnGroup = document.getElementById('resetPasswordBtnGroup'); | ||||
|                  | ||||
|                 if (selectedValue === 'create') { | ||||
|                     passwordRow.style.display = 'flex'; | ||||
|                     resetPasswordBtnGroup.style.display = 'none'; | ||||
|                 } else if (selectedValue === 'update') { | ||||
|                     passwordRow.style.display = 'none'; | ||||
|                     resetPasswordBtnGroup.style.display = 'block'; | ||||
|                 } | ||||
|                  | ||||
|                 // 根据账号类型和操作类型推荐权限 | ||||
|                 if (selectedAccountType) { | ||||
|                     recommendPermissionsForAccountType(selectedAccountType, selectedOperationType); | ||||
|                 } | ||||
|             } else { | ||||
|                 selectedOperationType = null; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 根据账号类型和操作类型推荐权限 | ||||
|         function recommendPermissionsForAccountType(accountType, operationType) { | ||||
|             // 根据不同账号类型和操作类型推荐默认权限 | ||||
|             const recommendedPermissions = []; | ||||
|             if (accountType.code === 'sub_merchant') { | ||||
|                 // 子经营者推荐基础权限 | ||||
|                 recommendedPermissions.push('CONTENT'); | ||||
|             } else if (accountType.code === 'merchant') { | ||||
|                 // 商户推荐更多权限 | ||||
|                 recommendedPermissions.push('SYSTEM', 'CONTENT'); | ||||
|             } | ||||
|              | ||||
|             // 自动勾选推荐的权限 | ||||
|             recommendedPermissions.forEach(permissionCode => { | ||||
|                 const checkbox = document.querySelector(`[data-permission-code="${permissionCode}"]`); | ||||
|                 if (checkbox && !checkbox.checked) { | ||||
|                     checkbox.checked = true; | ||||
|                     selectedPermissions.add(permissionCode); | ||||
|                     updatePermissionDisplay(); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         // 重置密码功能 | ||||
|         function resetPassword() { | ||||
|             if (confirm('确定要将密码重置为初始密码123456吗?')) { | ||||
|                 alert('密码已重置为初始密码123456!'); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 初始化权限树 | ||||
|         function initPermissionTree() { | ||||
|             const tree = buildPermissionTree(permissions); | ||||
|             const treeContainer = document.getElementById('permissionTree'); | ||||
|             treeContainer.innerHTML = ''; | ||||
|              | ||||
|             tree.forEach(item => { | ||||
|                 treeContainer.appendChild(createPermissionNode(item)); | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         // 构建权限树 | ||||
|         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 ' + (item.children.length > 0 ? 'parent' : 'child'); | ||||
|              | ||||
|             const nodeDiv = document.createElement('div'); | ||||
|             nodeDiv.className = 'permission-node'; | ||||
|              | ||||
|             // 展开/收起按钮 | ||||
|             if (item.children.length > 0) { | ||||
|                 const expandBtn = document.createElement('button'); | ||||
|                 expandBtn.className = 'expand-btn'; | ||||
|                 expandBtn.textContent = '▼'; | ||||
|                 expandBtn.onclick = (e) => { | ||||
|                     e.stopPropagation(); | ||||
|                     togglePermissionChildren(expandBtn, li); | ||||
|                 }; | ||||
|                 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}(${item.description || item.code})`; | ||||
|             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 togglePermissionChildren(btn, li) { | ||||
|             const children = li.querySelector('.permission-children'); | ||||
|             if (!children) return; | ||||
|              | ||||
|             const isExpanded = children.classList.contains('expanded'); | ||||
|             children.classList.toggle('expanded'); | ||||
|             btn.textContent = isExpanded ? '▶' : '▼'; | ||||
|             btn.classList.toggle('collapsed', isExpanded); | ||||
|         } | ||||
| 
 | ||||
|         // 处理权限选择变化 | ||||
|         function handlePermissionChange(event, permission) { | ||||
|             const checkbox = event.target; | ||||
|             const isChecked = checkbox.checked; | ||||
|             const permissionCode = permission.code; | ||||
|             const node = checkbox.closest('.permission-node'); | ||||
|              | ||||
|             // 更新节点选中样式 | ||||
|             if (node) { | ||||
|                 if (isChecked) { | ||||
|                     node.classList.add('selected'); | ||||
|                 } else { | ||||
|                     node.classList.remove('selected'); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             if (isChecked) { | ||||
|                 selectedPermissions.add(permissionCode); | ||||
|                 // 选中子级权限时,自动选中所有父级权限 | ||||
|                 selectParentPermissions(permission); | ||||
|                 // 如果是父权限,自动选中所有子权限 | ||||
|                 if (permission.children && permission.children.length > 0) { | ||||
|                     selectChildrenPermissions(permission, true); | ||||
|                 } | ||||
|             } else { | ||||
|                 selectedPermissions.delete(permissionCode); | ||||
|                 // 如果是父权限,自动取消所有子权限 | ||||
|                 if (permission.children && permission.children.length > 0) { | ||||
|                     selectChildrenPermissions(permission, false); | ||||
|                 } | ||||
|                 // 如果是子权限,检查是否需要取消父权限 | ||||
|                 uncheckParentIfNeeded(permission); | ||||
|             } | ||||
|              | ||||
|             updatePermissionDisplay(); | ||||
|         } | ||||
| 
 | ||||
|         // 选择所有父级权限 | ||||
|         function selectParentPermissions(permission) { | ||||
|             if (!permission.parentCode) return; | ||||
|              | ||||
|             // 查找父权限 | ||||
|             const parent = permissions.find(p => p.code === permission.parentCode); | ||||
|             if (!parent) return; | ||||
|              | ||||
|             // 选中父权限 | ||||
|             const parentCheckbox = document.querySelector(`[data-permission-code="${parent.code}"]`); | ||||
|             if (parentCheckbox && !parentCheckbox.checked) { | ||||
|                 parentCheckbox.checked = true; | ||||
|                 selectedPermissions.add(parent.code); | ||||
|             } | ||||
|              | ||||
|             // 递归选中上级父权限 | ||||
|             selectParentPermissions(parent); | ||||
|         } | ||||
| 
 | ||||
|         // 选择/取消子权限 | ||||
|         function selectChildrenPermissions(parent, select) { | ||||
|             if (!parent.children) return; | ||||
|              | ||||
|             parent.children.forEach(child => { | ||||
|                 const childCheckbox = document.querySelector(`[data-permission-code="${child.code}"]`); | ||||
|                 if (childCheckbox) { | ||||
|                     childCheckbox.checked = select; | ||||
|                     if (select) { | ||||
|                         selectedPermissions.add(child.code); | ||||
|                     } else { | ||||
|                         selectedPermissions.delete(child.code); | ||||
|                     } | ||||
|                      | ||||
|                     // 递归处理子权限 | ||||
|                     selectChildrenPermissions(child, select); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         // 检查是否需要取消父权限选择 | ||||
|         function uncheckParentIfNeeded(permission) { | ||||
|             if (!permission.parentCode) return; | ||||
|              | ||||
|             // 查找父权限 | ||||
|             const parent = permissions.find(p => p.code === permission.parentCode); | ||||
|             if (!parent) return; | ||||
|              | ||||
|             // 检查父权限的所有子权限是否都未选中 | ||||
|             const siblings = permissions.filter(p => p.parentCode === parent.code); | ||||
|             const hasSelectedSibling = siblings.some(sibling => selectedPermissions.has(sibling.code)); | ||||
|              | ||||
|             if (!hasSelectedSibling) { | ||||
|                 const parentCheckbox = document.querySelector(`[data-permission-code="${parent.code}"]`); | ||||
|                 if (parentCheckbox) { | ||||
|                     parentCheckbox.checked = false; | ||||
|                     selectedPermissions.delete(parent.code); | ||||
|                     // 递归检查上级父权限 | ||||
|                     uncheckParentIfNeeded(parent); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 更新权限显示 | ||||
|         function updatePermissionDisplay() { | ||||
|             // 这里可以添加一些UI反馈,比如显示已选权限数量等 | ||||
|             console.log('已选择权限:', Array.from(selectedPermissions)); | ||||
|         } | ||||
| 
 | ||||
|         // 绑定事件 | ||||
|         function bindEvents() { | ||||
|             // 账号输入验证 | ||||
|             document.getElementById('account').addEventListener('input', function(e) { | ||||
|                 // 可以根据需要添加账号输入验证逻辑 | ||||
|                 // 目前保持账号输入不限制格式 | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         // 重置表单 | ||||
|         function resetForm() { | ||||
|             if (confirm('确定要重置所有信息吗?')) { | ||||
|                 // 重置账号类型选择(默认选择第一个tab) | ||||
|                 selectedAccountType = accountTypes[0]; | ||||
|                 document.querySelectorAll('.tab-btn').forEach(btn => { | ||||
|                     btn.classList.remove('active'); | ||||
|                 }); | ||||
|                 document.querySelector('.tab-btn').classList.add('active'); | ||||
|                  | ||||
|                 // 重置操作类型选择 | ||||
|                 selectedOperationType = null; | ||||
|                 document.getElementById('typeSelect').value = ''; | ||||
|                  | ||||
|                 // 重置账号 | ||||
|                 document.getElementById('account').value = ''; | ||||
|                  | ||||
|                 // 隐藏密码字段和重置密码按钮 | ||||
|                 document.getElementById('passwordRow').style.display = 'none'; | ||||
|                 document.getElementById('resetPasswordBtnGroup').style.display = 'none'; | ||||
|                  | ||||
|                 // 重置权限选择 | ||||
|                 selectedPermissions.clear(); | ||||
|                 document.querySelectorAll('.permission-checkbox').forEach(checkbox => { | ||||
|                     checkbox.checked = false; | ||||
|                 }); | ||||
|                  | ||||
|                 // 重置权限样式 | ||||
|                 document.querySelectorAll('.permission-node').forEach(node => { | ||||
|                     node.classList.remove('selected'); | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 取消分配 | ||||
|         function cancelAssignment() { | ||||
|             if (confirm('确定要取消权限分配吗?未保存的更改将丢失。')) { | ||||
|                 // 在实际应用中,这可能需要重定向到其他页面 | ||||
|                 window.location.reload(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 保存权限分配 | ||||
|         function saveAssignment() { | ||||
|             // 验证账号类型选择 | ||||
|             if (!selectedAccountType) { | ||||
|                 alert('请选择账号类型!'); | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             // 验证操作类型选择 | ||||
|             if (!selectedOperationType) { | ||||
|                 alert('请选择操作类型!'); | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             // 验证账号 | ||||
|             const account = document.getElementById('account').value.trim(); | ||||
|             if (!account) { | ||||
|                 alert('请输入账号!'); | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             // 验证权限选择 | ||||
|             if (selectedPermissions.size === 0) { | ||||
|                 alert('请至少选择一个权限!'); | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             // 构建保存数据 | ||||
|             const assignmentData = { | ||||
|                 accountType: selectedAccountType, | ||||
|                 operationType: selectedOperationType, | ||||
|                 account: account, | ||||
|                 permissions: Array.from(selectedPermissions) | ||||
|             }; | ||||
|              | ||||
|             console.log('保存权限分配数据:', assignmentData); | ||||
|              | ||||
|             // 这里应该调用API保存数据 | ||||
|             alert('权限分配保存成功!'); | ||||
|              | ||||
|             // 可选:保存后重置表单 | ||||
|             // resetForm(); | ||||
|         } | ||||
|     </script> | ||||
| </body> | ||||
| </html> | ||||
		Loading…
	
		Reference in New Issue