AIDaohang/templates/categories.html

439 lines
24 KiB
HTML
Raw Permalink 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.

{% extends "base.html" %}
{% block title %}分类管理{% endblock %}
{% block content %}
<!-- 添加子分类模态框 -->
<div class="modal fade" id="addSubCategoryModal" tabindex="-1" aria-labelledby="addSubCategoryModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addSubCategoryModalLabel">添加子分类</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="post" action="{{ url_for('add_sub_category') }}" id="subCategoryForm">
<div class="modal-body">
<input type="hidden" name="main_id" id="modalMainId">
<div class="mb-3">
<label for="sub_id" class="form-label">子分类 ID</label>
<input type="text" name="sub_id" class="form-control" required>
</div>
<div class="mb-3">
<label for="sub_name" class="form-label">子分类名称</label>
<input type="text" name="sub_name" class="form-control" required>
</div>
<div class="mb-3">
<label for="weight" class="form-label">权重</label>
<input type="number" name="weight" class="form-control" value="0">
</div>
<div class="mb-3">
<label for="color" class="form-label">颜色</label>
<input type="color" name="color" class="form-control form-control-color" value="#4895ef">
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="sub_private_modal" name="private">
<label class="form-check-label" for="sub_private_modal">私有</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary">添加</button>
</div>
</form>
</div>
</div>
</div>
<!-- 添加应用模态框 -->
<div class="modal fade" id="addAppModal" tabindex="-1" aria-labelledby="addAppModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addAppModalLabel">添加应用</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="post" action="{{ url_for('add_app_from_category') }}">
<div class="modal-body">
<input type="hidden" name="main_category" id="modalAppMainCategory">
<input type="hidden" name="sub_category" id="modalAppSubCategory">
<div class="mb-3">
<label for="title" class="form-label">应用名称</label>
<input type="text" name="title" class="form-control" required>
</div>
<div class="mb-3">
<label for="url" class="form-label">URL</label>
<input type="text" name="url" class="form-control" required>
</div>
<div class="mb-3">
<label for="icon" class="form-label">图标</label>
<div class="input-group mb-3">
<input type="text" id="iconSearch" class="form-control" placeholder="搜索图标名称或描述..." onkeyup="filterIcons()">
</div>
<div class="alert alert-info mb-3" id="selectedIconInfo" style="display: none;">
<strong>已选择图标:</strong>
<span id="selectedIconCode"></span>
<span id="selectedIconComment"></span>
</div>
<div class="row g-3" id="iconContainer" style="max-height: 400px; overflow-y: auto;">
{% for icon, comment in icons.items() %}
<div class="col-4 col-md-3 col-lg-2 icon-item" data-icon="{{ icon }}" data-comment="{{ comment }}">
<div class="card icon-card h-100" onclick="selectIcon(this, '{{ icon }}', '{{ comment }}')">
<div class="card-body text-center d-flex flex-column">
<div class="mb-2">
<i class="{{ icon }} fa-2x"></i>
</div>
<div class="mt-auto">
<small class="text-truncate d-block">{{ comment }}</small>
<small class="text-muted d-block">{{ icon }}</small>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<select name="icon" id="iconSelect" class="form-select" required style="display: none;">
{% for icon, comment in icons.items() %}
<option value="{{ icon }}">{{ comment }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="description" class="form-label">描述</label>
<textarea name="description" class="form-control"></textarea>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="private" name="private">
<label class="form-check-label" for="private">私有</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary">添加</button>
</div>
</form>
</div>
</div>
</div>
<div class="card">
<div class="card-body">
<div class="mb-4">
<h5>添加主分类</h5>
<form method="post" action="{{ url_for('add_main_category') }}">
<div class="row g-3">
<div class="col-12 col-md-2">
<input type="text" name="id" class="form-control" placeholder="主分类 ID" required>
</div>
<div class="col-12 col-md-3">
<input type="text" name="name" class="form-control" placeholder="主分类名称" required>
</div>
<div class="col-12 col-md-1">
<input type="number" name="weight" class="form-control" placeholder="权重" value="0">
</div>
<div class="col-12 col-md-1">
<input type="color" name="color" class="form-control form-control-color" value="#4361ee" title="选择颜色">
</div>
<div class="col-12 col-md-2 d-flex align-items-center">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="main_private" name="private">
<label class="form-check-label" for="main_private">私有</label>
</div>
</div>
<div class="col-12 col-md-1">
<button type="submit" class="btn btn-primary w-100">
<i class="fas fa-plus"></i> 添加
</button>
</div>
</div>
</form>
</div>
<div class="mb-4">
<h5>添加子分类</h5>
<form method="post" action="{{ url_for('add_sub_category') }}">
<div class="row g-3">
<div class="col-12 col-md-2">
<select name="main_id" class="form-select" required>
<option value="">选择主分类</option>
{% for main_id, cat in categories.items()|sort(attribute='1.weight', reverse=True) %}
<option value="{{ main_id }}">{{ cat.name }}</option>
{% endfor %}
</select>
</div>
<div class="col-12 col-md-2">
<input type="text" name="sub_id" class="form-control" placeholder="子分类 ID" required>
</div>
<div class="col-12 col-md-3">
<input type="text" name="sub_name" class="form-control" placeholder="子分类名称" required>
</div>
<div class="col-12 col-md-1">
<input type="number" name="weight" class="form-control" placeholder="权重" value="0">
</div>
<div class="col-12 col-md-1">
<input type="color" name="color" class="form-control form-control-color" value="#4895ef" title="选择颜色">
</div>
<div class="col-12 col-md-2 d-flex align-items-center">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="sub_private" name="private">
<label class="form-check-label" for="sub_private">私有</label>
</div>
</div>
<div class="col-12 col-md-1">
<button type="submit" class="btn btn-success w-100">
<i class="fas fa-plus"></i> 添加
</button>
</div>
</div>
</form>
</div>
<div>
<h5>已存在的分类</h5>
<!-- 桌面端显示 -->
<div class="d-none d-md-block">
<div class="list-group">
{% for main_id, cat in categories.items()|sort(attribute='1.weight', reverse=True) %}
<div class="list-group-item">
<div class="d-flex justify-content-between align-items-center flex-wrap">
<div class="mb-2 mb-md-0">
<strong>{{ cat.name }}</strong>ID: {{ main_id }})
<span class="badge" style="background-color: {{ cat.color }}; color: white;">{{ cat.get('weight', 0) }}</span>
{% if cat.get('private', False) %}
<span class="badge bg-warning text-dark ms-2">私有</span>
{% endif %}
</div>
<div>
<button class="btn btn-sm btn-success me-2"
data-bs-toggle="modal"
data-bs-target="#addSubCategoryModal"
onclick="setMainId('{{ main_id }}')">
<i class="fas fa-plus"></i> 添加子分类
</button>
<a href="{{ url_for('edit_main_category', main_id=main_id) }}"
class="btn btn-sm btn-primary me-2">
<i class="fas fa-edit"></i> 编辑
</a>
<a href="{{ url_for('delete_main_category', main_id=main_id) }}"
class="btn btn-sm btn-danger"
onclick="return confirm('确认删除整个主分类?')">
<i class="fas fa-trash"></i> 删除
</a>
</div>
</div>
<ul class="mt-2 list-group list-group-flush">
{% for sub_id, subData in cat.sub.items()|sort(attribute='1.weight', reverse=True) %}
<li class="list-group-item d-flex justify-content-between align-items-center flex-wrap">
<span class="mb-2 mb-md-0">
{{ subData.name }}ID: {{ sub_id }})
<span class="badge" style="background-color: {{ subData.color }}; color: white;">{{ subData.get('weight', 0) }}</span>
{% if cat.get('sub_private', {}).get(sub_id, False) %}
<span class="badge bg-warning text-dark ms-2">私有</span>
{% endif %}
</span>
<div>
<button class="btn btn-sm btn-success me-2"
data-bs-toggle="modal"
data-bs-target="#addAppModal"
onclick="setCategory('{{ main_id }}', '{{ sub_id }}')">
<i class="fas fa-plus"></i> 添加应用
</button>
<a href="{{ url_for('edit_sub_category', main_id=main_id, sub_id=sub_id) }}"
class="btn btn-sm btn-primary me-2">
<i class="fas fa-edit"></i> 编辑
</a>
<a href="{{ url_for('delete_sub_category', main_id=main_id, sub_id=sub_id) }}"
class="btn btn-sm btn-outline-danger"
onclick="return confirm('确认删除该子分类?')">
<i class="fas fa-trash"></i> 删除
</a>
</div>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>
</div>
<!-- 移动端显示 -->
<div class="d-md-none">
<div class="accordion" id="categoryAccordion">
{% for main_id, cat in categories.items()|sort(attribute='1.weight', reverse=True) %}
<div class="card mb-3">
<div class="card-header d-flex justify-content-between align-items-center" style="background-color: {{ cat.color }}; color: white;">
<div>
<strong>{{ cat.name }}</strong> (ID: {{ main_id }})
<span class="badge bg-light text-dark ms-2">{{ cat.get('weight', 0) }}</span>
{% if cat.get('private', False) %}
<span class="badge bg-warning text-dark ms-2">私有</span>
{% endif %}
</div>
<div>
<button class="btn btn-sm btn-light me-2" type="button" data-bs-toggle="collapse" data-bs-target="#collapse{{ loop.index }}" aria-expanded="true" aria-controls="collapse{{ loop.index }}">
<i class="fas fa-chevron-down"></i>
</button>
</div>
</div>
<div id="collapse{{ loop.index }}" class="collapse show" data-bs-parent="#categoryAccordion">
<div class="card-body">
<div class="d-flex justify-content-between mb-3">
<button class="btn btn-sm btn-success flex-grow-1 me-2"
data-bs-toggle="modal"
data-bs-target="#addSubCategoryModal"
onclick="setMainId('{{ main_id }}')">
<i class="fas fa-plus"></i> 添加子分类
</button>
<a href="{{ url_for('edit_main_category', main_id=main_id) }}"
class="btn btn-sm btn-primary flex-grow-1 me-2">
<i class="fas fa-edit"></i> 编辑主分类
</a>
<a href="{{ url_for('delete_main_category', main_id=main_id) }}"
class="btn btn-sm btn-danger flex-grow-1"
onclick="return confirm('确认删除整个主分类?')">
<i class="fas fa-trash"></i> 删除
</a>
</div>
<h6 class="mb-3">子分类列表</h6>
{% for sub_id, subData in cat.sub.items()|sort(attribute='1.weight', reverse=True) %}
<div class="card mb-2">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-2">
<div>
<strong>{{ subData.name }}</strong> (ID: {{ sub_id }})
<span class="badge" style="background-color: {{ subData.color }}; color: white;">{{ subData.get('weight', 0) }}</span>
{% if cat.get('sub_private', {}).get(sub_id, False) %}
<span class="badge bg-warning text-dark ms-2">私有</span>
{% endif %}
</div>
</div>
<div class="d-flex justify-content-between">
<button class="btn btn-sm btn-success flex-grow-1 me-2"
data-bs-toggle="modal"
data-bs-target="#addAppModal"
onclick="setCategory('{{ main_id }}', '{{ sub_id }}')">
<i class="fas fa-plus"></i> 添加应用
</button>
<a href="{{ url_for('edit_sub_category', main_id=main_id, sub_id=sub_id) }}"
class="btn btn-sm btn-primary flex-grow-1 me-2">
<i class="fas fa-edit"></i> 编辑
</a>
<a href="{{ url_for('delete_sub_category', main_id=main_id, sub_id=sub_id) }}"
class="btn btn-sm btn-outline-danger flex-grow-1"
onclick="return confirm('确认删除该子分类?')">
<i class="fas fa-trash"></i> 删除
</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="mt-4">
<a href="{{ url_for('index') }}" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> 返回首页
</a>
</div>
</div>
</div>
<script>
function setMainId(mainId) {
document.getElementById('modalMainId').value = mainId;
}
function setCategory(mainId, subId) {
document.getElementById('modalAppMainCategory').value = mainId;
document.getElementById('modalAppSubCategory').value = subId;
}
function filterIcons() {
const searchTerm = document.getElementById('iconSearch').value.toLowerCase();
const iconItems = document.querySelectorAll('.icon-item');
iconItems.forEach(item => {
const iconName = item.getAttribute('data-icon').toLowerCase();
const iconComment = item.getAttribute('data-comment').toLowerCase();
if (iconName.includes(searchTerm) || iconComment.includes(searchTerm)) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
});
}
function selectIcon(element, icon, comment) {
// 移除所有选中状态
document.querySelectorAll('.icon-card').forEach(card => {
card.classList.remove('border-primary', 'bg-light');
});
// 添加选中状态
element.classList.add('border-primary', 'bg-light');
// 更新隐藏的select元素
const select = document.getElementById('iconSelect');
select.value = icon;
// 显示选中的图标信息
const selectedIconInfo = document.getElementById('selectedIconInfo');
document.getElementById('selectedIconCode').textContent = icon;
document.getElementById('selectedIconComment').textContent = " - " + comment;
selectedIconInfo.style.display = 'block';
// 触发change事件
const event = new Event('change');
select.dispatchEvent(event);
}
// 初始化时隐藏select元素并显示图标网格
document.addEventListener('DOMContentLoaded', function() {
const select = document.getElementById('iconSelect');
select.style.display = 'none';
});
</script>
<style>
.icon-card {
cursor: pointer;
transition: all 0.2s;
height: 100%;
}
.icon-card:hover {
transform: scale(1.05);
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}
.icon-card.border-primary {
border: 2px solid #0d6efd !important;
}
.icon-item {
margin-bottom: 1rem;
}
#iconContainer {
padding: 10px;
}
#selectedIconInfo {
padding: 10px;
border-radius: 5px;
}
#selectedIconCode {
font-family: monospace;
color: #0d6efd;
}
#selectedIconComment {
color: #6c757d;
}
</style>
{% endblock %}