dm-design/平台端web/权限管理/权限分配.html

837 lines
26 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>权限分配</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f5f7fa;
color: #333;
height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #2c3e50, #3498db);
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: #3498db;
color: #fff;
}
.btn-primary:hover {
background-color: #2980b9;
transform: translateY(-2px);
}
.btn-success {
background-color: #27ae60;
color: #fff;
}
.btn-success:hover {
background-color: #229954;
}
.btn-warning {
background-color: #f39c12;
color: #fff;
}
.btn-warning:hover {
background-color: #e67e22;
}
/* 内容区域 */
.content {
padding: 30px;
}
.section {
margin-bottom: 40px;
}
.section-title {
font-size: 1.4rem;
font-weight: 600;
color: #2c3e50;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid #ecf0f1;
}
/* 账号创建区域 */
.account-form {
background-color: #f8f9fa;
padding: 25px;
border-radius: 8px;
border: 1px solid #dee2e6;
}
.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: #2c3e50;
}
.form-group input,
.form-group select {
width: 100%;
padding: 12px 15px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
transition: border-color 0.3s ease;
}
.form-group input:focus,
.form-group select:focus {
outline: none;
border-color: #3498db;
box-shadow: 0 0 5px rgba(52, 152, 219, 0.3);
}
/* 菜市场选择框样式 */
.market-select-container {
position: relative;
}
.market-select {
cursor: pointer;
}
.market-dropdown {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: #fff;
border: 1px solid #ddd;
border-top: none;
border-radius: 0 0 5px 5px;
max-height: 200px;
overflow-y: auto;
z-index: 1000;
display: none;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.market-dropdown.show {
display: block;
}
.market-option {
padding: 10px 15px;
cursor: pointer;
transition: background-color 0.2s ease;
}
.market-option:hover {
background-color: #f8f9fa;
}
.market-option.selected {
background-color: #3498db;
color: #fff;
}
.market-filter {
padding: 10px 15px;
border: none;
border-bottom: 1px solid #eee;
width: 100%;
outline: none;
}
/* 权限分配区域 */
.permissions-container {
background-color: #f8f9fa;
padding: 25px;
border-radius: 8px;
border: 1px solid #dee2e6;
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: 6px;
transition: all 0.3s ease;
cursor: pointer;
background-color: #fff;
border: 1px solid #e9ecef;
margin-bottom: 5px;
}
.permission-node:hover {
background-color: #f8f9fa;
border-color: #3498db;
box-shadow: 0 2px 8px rgba(52, 152, 219, 0.15);
}
.permission-node.selected {
background-color: #e3f2fd;
border-color: #3498db;
}
.permission-checkbox {
margin-right: 12px;
width: 18px;
height: 18px;
cursor: pointer;
accent-color: #3498db;
}
.expand-btn {
background: #3498db;
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: #2c3e50;
user-select: none;
flex: 1;
font-weight: 500;
}
.permission-children {
margin-left: 35px;
margin-top: 8px;
border-left: 2px solid #3498db;
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: #3498db;
}
.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: #edf7ff;
border-color: #bbdefb;
font-weight: 600;
}
.permission-item.child .permission-node {
margin-left: 15px;
background-color: #f8f9fa;
}
/* 操作区域 */
.actions {
display: flex;
justify-content: flex-end;
gap: 10px;
padding-top: 20px;
border-top: 1px solid #dee2e6;
margin-top: 30px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.container {
margin: 10px;
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">
<button class="btn btn-warning" onclick="resetForm()">
🔄 重置
</button>
</div>
</div>
<!-- 内容区域 -->
<div class="content">
<!-- 账号创建区域 -->
<div class="section">
<h2 class="section-title">账号信息</h2>
<div class="account-form">
<div class="form-row">
<div class="form-group">
<label for="marketSelect">菜市场选择 *</label>
<div class="market-select-container">
<input type="text" id="marketSelect" class="market-select"
placeholder="请选择菜市场" readonly onclick="toggleMarketDropdown()">
<div id="marketDropdown" class="market-dropdown">
<input type="text" id="marketFilter" class="market-filter"
placeholder="输入菜市场名称搜索..."
oninput="filterMarkets(this.value)">
<div id="marketOptions"></div>
</div>
</div>
</div>
<div class="form-group">
<label for="phoneNumber">账号手机号 *</label>
<input type="tel" id="phoneNumber" placeholder="请输入手机号" maxlength="11">
</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()">取消</button>
<button class="btn btn-success" onclick="saveAssignment()">💾 保存分配</button>
</div>
</div>
</div>
<script>
// 菜市场数据
const markets = [
{ id: 1, name: '中央菜市场', code: 'CENTRAL_MARKET' },
{ id: 2, name: '东区菜市场', code: 'EAST_MARKET' },
{ id: 3, name: '西区菜市场', code: 'WEST_MARKET' },
{ id: 4, name: '南区菜市场', code: 'SOUTH_MARKET' },
{ id: 5, name: '北区菜市场', code: 'NORTH_MARKET' },
{ id: 6, name: '新华菜市场', code: 'XINHUA_MARKET' },
{ id: 7, name: '人民菜市场', code: 'RENMIN_MARKET' },
{ id: 8, name: '建设菜市场', code: 'JIANSHE_MARKET' }
];
// 权限数据(从权限编辑页面获取的示例数据)
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 selectedMarket = null;
let selectedPermissions = new Set();
// 初始化页面
document.addEventListener('DOMContentLoaded', function() {
initMarketOptions();
initPermissionTree();
bindEvents();
});
// 初始化菜市场选项
function initMarketOptions() {
const optionsContainer = document.getElementById('marketOptions');
optionsContainer.innerHTML = '';
markets.forEach(market => {
const option = document.createElement('div');
option.className = 'market-option';
option.textContent = market.name;
option.dataset.marketId = market.id;
option.onclick = () => selectMarket(market);
optionsContainer.appendChild(option);
});
}
// 选择菜市场
function selectMarket(market) {
selectedMarket = market;
document.getElementById('marketSelect').value = market.name;
document.getElementById('marketDropdown').classList.remove('show');
// 更新选中状态
document.querySelectorAll('.market-option').forEach(option => {
option.classList.toggle('selected', option.dataset.marketId == market.id);
});
}
// 切换菜市场下拉框显示
function toggleMarketDropdown() {
const dropdown = document.getElementById('marketDropdown');
dropdown.classList.toggle('show');
if (dropdown.classList.contains('show')) {
document.getElementById('marketFilter').focus();
}
}
// 过滤菜市场
function filterMarkets(keyword) {
const options = document.querySelectorAll('.market-option');
keyword = keyword.toLowerCase();
options.forEach(option => {
const marketName = option.textContent.toLowerCase();
option.style.display = marketName.includes(keyword) ? 'block' : 'none';
});
}
// 初始化权限树
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.addEventListener('click', function(e) {
const dropdown = document.getElementById('marketDropdown');
const selectContainer = document.querySelector('.market-select-container');
if (!selectContainer.contains(e.target)) {
dropdown.classList.remove('show');
}
});
// 手机号输入验证
document.getElementById('phoneNumber').addEventListener('input', function(e) {
let value = e.target.value.replace(/\D/g, '');
if (value.length > 11) {
value = value.slice(0, 11);
}
e.target.value = value;
});
}
// 重置表单
function resetForm() {
if (confirm('确定要重置所有信息吗?')) {
// 重置菜市场选择
selectedMarket = null;
document.getElementById('marketSelect').value = '';
document.querySelectorAll('.market-option').forEach(option => {
option.classList.remove('selected');
});
// 重置手机号
document.getElementById('phoneNumber').value = '';
// 重置权限选择
selectedPermissions.clear();
document.querySelectorAll('.permission-checkbox').forEach(checkbox => {
checkbox.checked = false;
});
// 重置搜索
document.getElementById('marketFilter').value = '';
filterMarkets('');
}
}
// 取消分配
function cancelAssignment() {
if (confirm('确定要取消权限分配吗?未保存的更改将丢失。')) {
window.history.back();
}
}
// 保存权限分配
function saveAssignment() {
// 验证菜市场
if (!selectedMarket) {
alert('请选择菜市场!');
return;
}
// 验证手机号
const phoneNumber = document.getElementById('phoneNumber').value.trim();
if (!phoneNumber) {
alert('请输入手机号!');
return;
}
if (!/^1[3-9]\d{9}$/.test(phoneNumber)) {
alert('请输入正确的手机号格式!');
return;
}
// 验证权限选择
if (selectedPermissions.size === 0) {
alert('请至少选择一个权限!');
return;
}
// 构建保存数据
const assignmentData = {
market: selectedMarket,
phoneNumber: phoneNumber,
permissions: Array.from(selectedPermissions)
};
console.log('保存权限分配数据:', assignmentData);
// 这里应该调用API保存数据
alert('权限分配保存成功!');
}
</script>
</body>
</html>