AIDaohang/templates/edit_app.html
2025-07-06 23:23:23 +08:00

338 lines
14 KiB
HTML

{% extends "base.html" %}
{% block title %}编辑应用{% endblock %}
{% block content %}
<div class="card">
<div class="card-header">
<h4>编辑应用</h4>
</div>
<div class="card-body">
<form method="post">
<div class="mb-3">
<label class="form-label">标题</label>
<input type="text" name="title" class="form-control" value="{{ app.title }}" required>
</div>
<div class="mb-3">
<label class="form-label">URL</label>
<input type="url" name="url" class="form-control" value="{{ app.url }}" required>
</div>
<!-- 在图标选择部分修改 -->
<div class="mb-3">
<label class="form-label">图标</label>
<input type="hidden" name="icon" id="selectedIcon" value="" required>
<div class="d-flex align-items-center mb-3">
<div class="icon-preview me-3">
<i id="iconPreview" class="fas fa-question-circle fa-2x"></i>
<img id="iconImagePreview" src="" style="display: none; max-width: 32px; max-height: 32px;">
</div>
<button type="button" class="btn btn-outline-primary me-2" data-bs-toggle="modal" data-bs-target="#iconModal">
<i class="fas fa-icons me-2"></i>选择图标
</button>
<button type="button" class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#iconImageModal">
<i class="fas fa-image me-2"></i>选择图片
</button>
</div>
</div>
<!-- 添加图标图片选择模态框 -->
<div class="modal fade" id="iconImageModal" tabindex="-1" aria-labelledby="iconImageModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="iconImageModalLabel">选择图标图片</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="container-fluid">
<div class="input-group mb-3">
<span class="input-group-text"><i class="fas fa-search"></i></span>
<input type="text" id="iconImageSearch" class="form-control" placeholder="搜索图标图片...">
</div>
<div class="row row-cols-3 row-cols-sm-4 row-cols-md-5 row-cols-lg-6 row-cols-xl-8 g-3" id="iconImageGrid">
{% for attachment in attachments if attachment.type == 'icon' %}
<div class="col">
<div class="icon-image-item p-3 text-center rounded" data-filename="{{ attachment.filename }}" title="{{ attachment.filename }}">
<img src="{{ url_for('uploaded_icon', filename=attachment.filename) }}" style="max-width: 50px; max-height: 50px;" class="img-thumbnail mb-2">
<div class="small text-truncate">{{ attachment.filename }}</div>
</div>
</div>
{% else %}
<div class="col-12 text-center py-3">
<p>暂无图标图片</p>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="modal-footer">
<div class="me-auto">
<span id="selectedIconImageName">未选择图片</span>
</div>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="confirmIconImage">确认选择</button>
</div>
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">主分类</label>
<select name="main_category" id="main_category" class="form-select" required>
<option value="">请选择</option>
{% for main_id, cat in categories.items() %}
<option value="{{ main_id }}" {% if app.category.main == main_id %}selected{% endif %}>{{ cat.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">子分类</label>
<select name="sub_category" id="sub_category" class="form-select" required>
{% if app.category.main in categories %}
{% for sub_id, subData in categories[app.category.main].sub.items() %}
<option value="{{ sub_id }}" {% if app.category.sub == sub_id %}selected{% endif %}>{{ subData.name }}</option>
{% endfor %}
{% else %}
<option value="">请先选择主分类</option>
{% endif %}
</select>
</div>
<div class="mb-3">
<label class="form-label">描述</label>
<textarea name="description" class="form-control" rows="3">{{ app.description if app.description else '' }}</textarea>
</div>
<div class="mb-3 form-check">
<input type="checkbox" name="private" class="form-check-input" id="privateCheck" {% if app.private %}checked{% endif %}>
<label class="form-check-label" for="privateCheck">私有应用(仅登录后可见)</label>
</div>
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<button type="submit" class="btn btn-success me-md-2">
<i class="fas fa-save me-2"></i>保存修改
</button>
<a href="{{ url_for('index') }}" class="btn btn-secondary">
<i class="fas fa-arrow-left me-2"></i>返回
</a>
</div>
</form>
</div>
</div>
<!-- 图标选择模态框 -->
<div class="modal fade" id="iconModal" tabindex="-1" aria-labelledby="iconModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="iconModalLabel">选择图标</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="container-fluid">
<div class="input-group mb-3">
<span class="input-group-text"><i class="fas fa-search"></i></span>
<input type="text" id="iconSearch" class="form-control" placeholder="搜索图标...">
</div>
<div class="row row-cols-3 row-cols-sm-4 row-cols-md-5 row-cols-lg-6 row-cols-xl-8 g-3" id="iconGrid">
{% for icon, name in icons.items() %}
<div class="col">
<div class="icon-item p-3 text-center rounded {% if app.icon == icon %}selected{% endif %}"
data-icon="{{ icon }}" title="{{ name }}">
<i class="{{ icon }} fa-2x mb-2"></i>
<div class="small text-truncate">{{ name }}</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="modal-footer">
<div class="me-auto">
<span id="selectedIconName">
{% if app.icon %}
{{ icons[app.icon] if app.icon in icons else '自定义图标' }}
{% else %}
未选择图标
{% endif %}
</span>
</div>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="confirmIcon">确认选择</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
document.addEventListener('DOMContentLoaded', function() {
let selectedIcon = '{{ app.icon if app.icon else "" }}';
let selectedIconName = '{% if app.icon %}{{ icons[app.icon] if app.icon in icons else "自定义图标" }}{% else %}未选择图标{% endif %}';
// 图标搜索功能
document.getElementById('iconSearch').addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
const iconItems = document.querySelectorAll('.icon-item');
iconItems.forEach(item => {
const iconName = item.getAttribute('title').toLowerCase();
const iconCode = item.dataset.icon.toLowerCase();
if (iconName.includes(searchTerm) || iconCode.includes(searchTerm)) {
item.closest('.col').style.display = 'block';
} else {
item.closest('.col').style.display = 'none';
}
});
});
// 图标点击选择
document.querySelectorAll('.icon-item').forEach(item => {
item.addEventListener('click', function() {
// 移除所有选中状态
document.querySelectorAll('.icon-item').forEach(i => {
i.classList.remove('selected');
});
// 添加选中状态
this.classList.add('selected');
selectedIcon = this.dataset.icon;
selectedIconName = this.getAttribute('title');
// 更新底部显示
document.getElementById('selectedIconName').textContent = selectedIconName;
});
});
// 确认选择
document.getElementById('confirmIcon').addEventListener('click', function() {
if (selectedIcon) {
document.getElementById('selectedIcon').value = selectedIcon;
document.getElementById('iconPreview').className = selectedIcon + ' fa-2x';
bootstrap.Modal.getInstance(document.getElementById('iconModal')).hide();
} else {
alert('请先选择一个图标');
}
});
// 主分类变化时加载子分类
document.getElementById('main_category').addEventListener('change', function() {
const mainId = this.value;
if (!mainId) return;
fetch('/get_subcategories/' + mainId)
.then(res => res.json())
.then(data => {
const subSelect = document.getElementById('sub_category');
subSelect.innerHTML = '<option value="">请选择</option>';
for (const [id, subData] of Object.entries(data)) {
const option = document.createElement('option');
option.value = id;
option.textContent = subData.name;
subSelect.appendChild(option);
}
// 尝试保留原来的子分类选择
if ('{{ app.category.sub }}' && data['{{ app.category.sub }}']) {
subSelect.value = '{{ app.category.sub }}';
}
});
});
// 初始化时高亮已选图标
if (selectedIcon) {
const selectedItem = document.querySelector(`.icon-item[data-icon="${selectedIcon}"]`);
if (selectedItem) {
selectedItem.classList.add('selected');
}
}
});
// 图标图片选择功能
let selectedIconImage = '';
let selectedIconImageName = '';
// 图标图片搜索功能
document.getElementById('iconImageSearch').addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
const iconImageItems = document.querySelectorAll('.icon-image-item');
iconImageItems.forEach(item => {
const filename = item.dataset.filename.toLowerCase();
if (filename.includes(searchTerm)) {
item.closest('.col').style.display = 'block';
} else {
item.closest('.col').style.display = 'none';
}
});
});
// 图标图片点击选择
document.querySelectorAll('.icon-image-item').forEach(item => {
item.addEventListener('click', function() {
// 移除所有选中状态
document.querySelectorAll('.icon-image-item').forEach(i => {
i.classList.remove('selected');
});
// 添加选中状态
this.classList.add('selected');
selectedIconImage = this.dataset.filename;
selectedIconImageName = this.getAttribute('title');
// 更新底部显示
document.getElementById('selectedIconImageName').textContent = selectedIconImageName;
});
});
// 确认选择图标图片
document.getElementById('confirmIconImage').addEventListener('click', function() {
if (selectedIconImage) {
document.getElementById('selectedIcon').value = '/upload/icon/' + selectedIconImage;
document.getElementById('iconPreview').style.display = 'none';
const iconImagePreview = document.getElementById('iconImagePreview');
iconImagePreview.src = '/upload/icon/' + selectedIconImage;
iconImagePreview.style.display = 'inline';
bootstrap.Modal.getInstance(document.getElementById('iconImageModal')).hide();
} else {
alert('请先选择一张图片');
}
});
</script>
<style>
.icon-preview {
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
background-color: #f8f9fa;
border-radius: 5px;
}
.icon-item {
cursor: pointer;
transition: all 0.2s;
border: 1px solid transparent;
}
.icon-item:hover {
background-color: #f8f9fa;
border-color: #dee2e6;
}
.icon-item.selected {
background-color: #e7f1ff;
border-color: #86b7fe;
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
}
#iconGrid {
max-height: 60vh;
overflow-y: auto;
}
#selectedIconName {
font-weight: bold;
color: #0d6efd;
}
</style>
{% endblock %}