feat: 统一编辑Modal样式,添加sticky底部按钮栏,目标内容使用Markdown编辑器
This commit is contained in:
+80
-28
@@ -1,5 +1,11 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block page_css %}
|
||||
<style>
|
||||
.goal-editor-textarea { font-family: monospace; font-size: 13px; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid py-4">
|
||||
<h2 class="mb-4">🎯 目标管理</h2>
|
||||
@@ -67,7 +73,7 @@
|
||||
|
||||
<!-- 目标编辑 Modal -->
|
||||
<div class="modal fade" id="goalModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="goalModalTitle">新建目标</h5>
|
||||
@@ -75,35 +81,43 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="goal-id">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">目标名称</label>
|
||||
<input type="text" class="form-control" id="goal-name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">级别</label>
|
||||
<select class="form-select" id="goal-level">
|
||||
<option value="启蒙">启蒙</option>
|
||||
<option value="入门" selected>入门</option>
|
||||
<option value="进阶">进阶</option>
|
||||
<option value="熟练">熟练</option>
|
||||
<option value="精通">精通</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">分类</label>
|
||||
<select class="form-select" id="goal-category">
|
||||
<option value="综合">综合(涉及多方面)</option>
|
||||
<option value="乐理相关">乐理相关</option>
|
||||
<option value="演奏能力">演奏能力</option>
|
||||
<option value="其他">其他</option>
|
||||
</select>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">目标名称</label>
|
||||
<input type="text" class="form-control" id="goal-name" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">级别</label>
|
||||
<select class="form-select" id="goal-level">
|
||||
<option value="启蒙">启蒙</option>
|
||||
<option value="入门" selected>入门</option>
|
||||
<option value="进阶">进阶</option>
|
||||
<option value="熟练">熟练</option>
|
||||
<option value="精通">精通</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">分类</label>
|
||||
<select class="form-select" id="goal-category">
|
||||
<option value="综合">综合(涉及多方面)</option>
|
||||
<option value="乐理相关">乐理相关</option>
|
||||
<option value="演奏能力">演奏能力</option>
|
||||
<option value="其他">其他</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">目标内容 (Markdown)</label>
|
||||
<textarea class="form-control" id="goal-content" rows="8"></textarea>
|
||||
<textarea class="form-control goal-editor-textarea" id="goal-content" rows="15"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="modal-footer-with-top">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary" id="save-goal">保存</button>
|
||||
</div>
|
||||
@@ -111,6 +125,19 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.modal-footer-with-top {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.5rem;
|
||||
padding: 1rem;
|
||||
border-top: 1px solid #dee2e6;
|
||||
background: #f8f9fa;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- 关系管理 Modal -->
|
||||
<div class="modal fade" id="relationModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
@@ -249,7 +276,7 @@ async function saveGoal() {
|
||||
const name = document.getElementById('goal-name').value;
|
||||
const level = document.getElementById('goal-level').value;
|
||||
const category = document.getElementById('goal-category').value;
|
||||
const content = document.getElementById('goal-content').value;
|
||||
const content = goalEditor ? goalEditor.value() : document.getElementById('goal-content').value;
|
||||
|
||||
if (!name) { alert('请输入目标名称'); return; }
|
||||
|
||||
@@ -277,6 +304,8 @@ async function saveGoal() {
|
||||
}
|
||||
}
|
||||
|
||||
let goalEditor = null;
|
||||
|
||||
function editGoal(id) {
|
||||
fetch(`${API_BASE}/${id}`)
|
||||
.then(r => r.json())
|
||||
@@ -285,8 +314,26 @@ function editGoal(id) {
|
||||
document.getElementById('goal-name').value = g.name;
|
||||
document.getElementById('goal-level').value = g.level || '入门';
|
||||
document.getElementById('goal-category').value = g.category || '综合';
|
||||
document.getElementById('goal-content').value = g.content || '';
|
||||
document.getElementById('goalModalTitle').textContent = '编辑目标';
|
||||
|
||||
// 初始化或更新 Markdown 编辑器
|
||||
const contentEl = document.getElementById('goal-content');
|
||||
if (window.EasyMDE) {
|
||||
if (goalEditor) {
|
||||
goalEditor.toTextArea();
|
||||
goalEditor = null;
|
||||
}
|
||||
goalEditor = new EasyMDE({
|
||||
element: contentEl,
|
||||
spellChecker: false,
|
||||
status: false,
|
||||
toolbar: ['bold', 'italic', 'heading', '|', 'code', 'quote', 'unordered-list', '|', 'preview', 'side-by-side', 'fullscreen'],
|
||||
initialValue: g.content || ''
|
||||
});
|
||||
} else {
|
||||
contentEl.value = g.content || '';
|
||||
}
|
||||
|
||||
new bootstrap.Modal(document.getElementById('goalModal')).show();
|
||||
});
|
||||
}
|
||||
@@ -406,8 +453,13 @@ document.getElementById('goalModal').addEventListener('hidden.bs.modal', () => {
|
||||
document.getElementById('goal-name').value = '';
|
||||
document.getElementById('goal-level').value = '入门';
|
||||
document.getElementById('goal-category').value = '综合';
|
||||
document.getElementById('goal-content').value = '';
|
||||
document.getElementById('goalModalTitle').textContent = '新建目标';
|
||||
// 清理 Markdown 编辑器
|
||||
if (goalEditor) {
|
||||
goalEditor.toTextArea();
|
||||
goalEditor = null;
|
||||
}
|
||||
document.getElementById('goal-content').value = '';
|
||||
});
|
||||
|
||||
loadGoals();
|
||||
|
||||
+29
-13
@@ -12,6 +12,16 @@
|
||||
.category-演奏能力 { background: #e8f5e9; color: #2e7d32; }
|
||||
.category-其他 { background: #fff3e0; color: #e65100; }
|
||||
.editor-textarea { font-family: monospace; font-size: 13px; }
|
||||
.modal-footer-with-top {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.5rem;
|
||||
padding: 1rem;
|
||||
border-top: 1px solid #dee2e6;
|
||||
background: #f8f9fa;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
@@ -121,25 +131,31 @@
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">问题名称 *</label>
|
||||
<input type="text" class="form-control" id="editProblemName">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">分类</label>
|
||||
<select class="form-select" id="editProblemCategory">
|
||||
<option value="综合">综合</option>
|
||||
<option value="乐理相关">乐理相关</option>
|
||||
<option value="演奏能力">演奏能力</option>
|
||||
<option value="其他">其他</option>
|
||||
</select>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-8">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">问题名称 *</label>
|
||||
<input type="text" class="form-control" id="editProblemName">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">分类</label>
|
||||
<select class="form-select" id="editProblemCategory">
|
||||
<option value="综合">综合</option>
|
||||
<option value="乐理相关">乐理相关</option>
|
||||
<option value="演奏能力">演奏能力</option>
|
||||
<option value="其他">其他</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">问题内容 (Markdown)</label>
|
||||
<textarea class="form-control editor-textarea" id="editProblemContent" rows="20"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="modal-footer-with-top">
|
||||
<button type="button" class="btn btn-secondary" id="cancelEditProblemBtn">取消</button>
|
||||
<button type="button" class="btn btn-primary" onclick="saveProblem()">保存</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user